루비의 숨겨진 기능


160

"숨겨진 기능 ..."meme을 계속하면서, 루비 프로그래밍 언어의 덜 알려졌지만 유용한 기능을 공유해 보자.

Ruby on Rails를 사용하지 않고 핵심 Ruby로이 토론을 제한하십시오.

또한보십시오:

( 답변 당 하나의 숨겨진 기능 만 제공하십시오 .)

감사합니다


커뮤니티 위키 여야 함
SilentGhost

답변:


80

Ruby 1.9부터 Proc # ===는 Proc # call의 별칭으로 Proc 객체는 다음과 같은 경우에 사용할 수 있습니다.

def multiple_of(factor)
  Proc.new{|product| product.modulo(factor).zero?}
end

case number
  when multiple_of(3)
    puts "Multiple of 3"
  when multiple_of(7)
    puts "Multiple of 7"
end

1
실제로이 작업을 수행하기 위해 보석을 한 시점에 작성했지만 내 코드는 (a) 혼란스럽고 (b) 느 렸습니다. 기능이 핵심으로 만들어 져서 매우 기쁩니다.
James A. Rosen

76

피터 쿠퍼는이 좋은 목록 루비 트릭을. 아마도 내가 가장 좋아하는 것은 단일 항목과 컬렉션을 모두 열거하는 것입니다. 즉, 비 컬렉션 오브젝트는 해당 오브젝트 만 포함하는 콜렉션으로 취급합니다.

[*items].each do |item|
  # ...
end

38
이것의보다 명백하고 (더 나은) 형태는 Array (items)입니다. 각각
mislav

items문자열 인 경우 [*…]로 묶을 필요가 없습니다. String.each는 예상대로 문자를 반복하지 않습니다. 그냥 블록으로 돌아갑니다.
mxcl

이것이 어떤 용도로 사용됩니까? 그냥 궁금해서
Ed S.

1
@ Ed : 메소드를 작성하고 메소드 사용자가 varargs 목록 또는 Array를 전달하도록 허용하는 것이 좋습니다.
James A. Rosen

64

이것이 어떻게 숨겨져 있는지 모르지만 1 차원 배열에서 해시를 만들어야 할 때 유용하다는 것을 알았습니다.

fruit = ["apple","red","banana","yellow"]
=> ["apple", "red", "banana", "yellow"]

Hash[*fruit]    
=> {"apple"=>"red", "banana"=>"yellow"}

Hash[ [["apple","red"], ["banana","yellow"] ]동일한 결과 를 생성합니다.
Marc-André Lafortune

54

내가 좋아하는 트릭은 *Array 이외의 객체 에서 splat ( ) 확장기 를 사용하는 것입니다. 정규식 일치에 대한 예는 다음과 같습니다.

match, text, number = *"Something 981".match(/([A-z]*) ([0-9]*)/)

다른 예는 다음과 같습니다.

a, b, c = *('A'..'Z')

Job = Struct.new(:name, :occupation)
tom = Job.new("Tom", "Developer")
name, occupation = *tom

13
또한 궁금한 점은 스 플랫의 대상에서 암시 적으로 to_a를 호출하여 작동합니다.
Bob Aman

1
경기에 관심이 없다면을 가질 수 있습니다 text, number = *"text 555".match(/regexp/)[1..-1].
Andrew Grimm

text, number = "Something 981".scan(/([A-z]*) ([0-9]*)/).flatten.map{|m| Integer(m) rescue m}
Jonas Elfström

7
두 가지 좋은 트릭이지만 마술이 너무 많은 지점이 있어야합니다!
tomafro

1
@ 앤드류, 그 경기가 nil을 돌려 줄 수 있다고 생각 했습니까? nil에는 방법이 없습니다 []
Alexey

52

와우, 플립 플롭 연산자에 대해서는 아무도 언급하지 않았습니다 :

1.upto(100) do |i|
  puts i if (i == 3)..(i == 15)
end

11
맞아요. 누군가 나에게 이것을 설명해야 할 것입니다. 작동하지만 이유를 알 수 없습니다.
밥 아만

12
플립 플롭 연산자는 상태가 가득 찬 경우입니다. 그 상태는 가능한 한 빨리 true로 전환 i == 3false로 전환 i != 3i == 15. 플립 플롭과 유사 : en.wikipedia.org/wiki/Flip-flop_%28electronics%29
Konstantin Haase 2016 년

1
나는 이것을 숨겨진 기능이라고 부르지 않을 것입니다. 몇 년 전에 #Ruby on Freenode에서 처음 소개 된 것을 기억합니다. 나는 이것을 제외하고 어느 시점에서 기본적으로 Ruby의 모든 단일 기능을 사용했습니다 .
ELLIOTTCABLE

1
나는 그것을 성가신이라고 부르지 않을 것입니다. 그것은 당신이 사용하지 않은 것입니다. 나는 그것을 사용하며 특히 일부 기준에 따라 파일에서 라인 블록을 잡을 때 코드를 훌륭하게 줄일 수 있습니다.
Tin Man

49

루비의 멋진 점 중 하나는 메소드 또는 클래스 정의와 같이 다른 언어가 찌푸린 곳에서 메소드를 호출하고 코드를 실행할 수 있다는 것입니다.

예를 들어, 런타임까지 알 수없는 수퍼 클래스가있는 클래스를 작성하려면 (예 : 임의) 다음을 수행하십시오.

class RandomSubclass < [Array, Hash, String, Fixnum, Float, TrueClass].sample

end

RandomSubclass.superclass # could output one of 6 different classes.

이것은 1.9 Array#sample방법 (1.8.7 전용, 참조 Array#choice)을 사용하며 예제는 꽤 고안되었지만 여기에서 힘을 볼 수 있습니다.

또 다른 멋진 예는 고정되지 않은 기본 매개 변수 값을 넣는 기능입니다 (다른 언어가 자주 요구하는 것처럼).

def do_something_at(something, at = Time.now)
   # ...
end

물론 첫 번째 예제의 문제점은 호출 시간이 아니라 정의 시간에 평가된다는 것입니다. 따라서 수퍼 클래스가 선택되면 나머지 프로그램의 수퍼 클래스가 유지됩니다.

그러나 두 번째 예에서 전화 할 때마다 do_something_atat변수는 메소드가 호출 된 시간이 될 것입니다 (물론, 아주 아주 가까운 그것에)


2
참고 : Array # rand는 ActiveSupport에서 제공하며 레일 외부에서도 쉽게 사용할 수 있습니다.require 'activesupport'
rfunduk

Array # choice는 1.8.7에 있습니다.
Josh Lee

24
Array # choice는 1.8.7 에만 해당됩니다 ! 그것을 사용하지 마십시오, 1.9에 사라지고 1.8.8에 사라질 것입니다. #sample 사용
Marc-André Lafortune

파이썬 : 클래스 DictList ([딕셔너리 목록] random.randint (0,1)]) 패스
아 누락 Uniyal

def do_something_at (something, at = lambda {Time.now}) at.call # 지금 동적으로 시간 종료 할당
Jack Kinsella

47

또 다른 작은 기능- Fixnum최대 36까지의 기지 로 변환 :

>> 1234567890.to_s(2)
=> "1001001100101100000001011010010"

>> 1234567890.to_s(8)
=> "11145401322"

>> 1234567890.to_s(16)
=> "499602d2"

>> 1234567890.to_s(24)
=> "6b1230i"

>> 1234567890.to_s(36)
=> "kf12oi"

Huw Walters가 언급했듯이 다른 방법으로 변환하는 것은 간단합니다.

>> "kf12oi".to_i(36)
=> 1234567890

1
그리고 완전성 String#to_s(base)을 위해 정수로 다시 변환하는 데 사용할 수 있습니다. "1001001100101100000001011010010".to_i(2), "499602d2".to_i(16)등 모든 반환 원래 Fixnum.
휴 월터스

40

기본값으로 해시! 이 경우 배열입니다.

parties = Hash.new {|hash, key| hash[key] = [] }
parties["Summer party"]
# => []

parties["Summer party"] << "Joe"
parties["Other party"] << "Jane"

메타 프로그래밍에 매우 유용합니다.


1
그래 맞아 루비 해시는 이미 기본값이 '='로 할당 된 경우 '<<'연산자를 허용 할 수 있습니다 (빈 할당이라도 상관하지 않음). 그렇지 않으면 해시는 '<<'를 허용하지 않습니다. CMIIW
mhd

39

Ruby 1.9 소스를 다운로드하고 발행 make golf하면 다음과 같은 작업을 수행 할 수 있습니다.

make golf

./goruby -e 'h'
# => Hello, world!

./goruby -e 'p St'
# => StandardError

./goruby -e 'p 1.tf'
# => 1.0

./goruby19 -e 'p Fil.exp(".")'
"/home/manveru/pkgbuilds/ruby-svn/src/trunk"

golf_prelude.c더 깔끔한 것들을 숨기려면를 읽으십시오 .


38

1.9 Proc 기능에 추가 된 또 다른 재미있는 기능은 Proc # curry입니다. 이것은 n 개의 인수를 수락하는 Proc를 n 개의 수락하는 n-1로 바꿀 수있게합니다. 여기에 위에서 언급 한 Proc # === 팁과 결합됩니다.

it_is_day_of_week = lambda{ |day_of_week, date| date.wday == day_of_week }
it_is_saturday = it_is_day_of_week.curry[6]
it_is_sunday = it_is_day_of_week.curry[0]

case Time.now
when it_is_saturday
  puts "Saturday!"
when it_is_sunday
  puts "Sunday!"
else
  puts "Not the weekend"
end

35

부울이 아닌 값에 대한 부울 연산자

&&||

둘 다 마지막으로 평가 된 식의 값을 반환합니다.

그렇기 때문에 ||=변수가 정의되지 않은 경우 오른쪽에 반환 된 값으로 변수를 업데이트합니다. 이것은 명시 적으로 문서화되어 있지는 않지만 일반적인 지식입니다.

그러나 &&=그다지 널리 알려지지 않았습니다.

string &&= string + "suffix"

에 해당

if string
  string = string + "suffix"
end

변수가 정의되지 않은 경우 진행되지 않아야하는 파괴적인 작업에 매우 편리합니다.


2
보다 정확하게 string &&= string + "suffix" 는에 해당합니다 string = string && string + "suffix". 그건 &&및 것은 ||, 자신의 두 번째 인수가 곡괭이에서 설명 페이지를 반환합니다. 154 (1 부-루비의 양상, 표현, 조건부 실행).
Richard Michael

29

Rails가 제공하는 Symbol # to_proc 함수는 정말 멋집니다.

대신에

Employee.collect { |emp| emp.name }

당신은 쓸 수 있습니다:

Employee.collect(&:name)

이것은 분명히 블록을 사용하는 것보다 "수십배 느립니다". igvita.com/2008/07/08/6-optimization-tips-for-ruby-mri
Charles Roper

방금 시도해 보았지만 둘 사이에는 큰 차이가 없었습니다. 이 "순서"항목의 출처를 잘 모르겠습니다. (Ruby 1.8.7 사용)
Matt Grande

1
Rails 외부에서이 작업을 수행하는 것도 편리하며 require 'activesupport'실제로 대부분의 도우미가있는 곳이기 때문에 수행 할 수 있습니다 .
rfunduk

8
이것은 active_support의 구현으로 인해 느려졌습니다. 즉, 여러 인수를 허용하므로 (1..10) .inject & : *와 같은 멋진 똥을 할 수 있지만 주요 유스 케이스는 종종 각 멤버의 메소드 만 호출했습니다. 수집 예 : % w (빠른 갈색 여우) .map & : upcase. 1.8.7부터 핵심 루비이며 성능이 합리적입니다.
Steve Graham 8:26에

4
@thenduks : 그리고 루비 1.8.7과 1.9의 적극적인 지원 없이도 가능합니다.
Andrew Grimm

28

마지막으로 루비에서는 문자열을 구분하려는 모든 문자를 사용할 수 있습니다. 다음 코드를 사용하십시오.

message = "My message"
contrived_example = "<div id=\"contrived\">#{message}</div>"

문자열 내에서 큰 따옴표를 이스케이프하지 않으려면 다른 구분 기호를 사용하면됩니다.

contrived_example = %{<div id="contrived-example">#{message}</div>}
contrived_example = %[<div id="contrived-example">#{message}</div>]

구분 기호를 이스케이프 처리하지 않아도 될뿐만 아니라 다음 구분 기호를 사용하여 더 나은 여러 줄 문자열을 사용할 수 있습니다.

sql = %{
    SELECT strings 
    FROM complicated_table
    WHERE complicated_condition = '1'
}

19
하지 모든 문자,하지만 여전히 꽤 멋지다. 또한 다른 리터럴과 함께 작동합니다 : % () / % {} / % [] / % <> / % || % r () / % r {} / % r [] / % r <> / % r || % w () / % w {} / % w [] / % w <> / % w ||
Bo Jeanes

<docBlock ... BLOCK (여러 줄의 SQL 문 등)
Martin T.

26

define_method 명령을 사용하여 흥미롭고 잘 알려지지 않은 메소드를 동적으로 생성하는 것을 발견했습니다. 예를 들면 다음과 같습니다.

((0..9).each do |n|
    define_method "press_#{n}" do
      @number = @number.to_i * 10 + n
    end
  end

위의 코드는 'define_method'명령을 사용하여 "press1"- "press9"메소드를 동적으로 작성합니다. essentailly가 동일한 코드를 포함하는 10 가지 메소드를 모두 입력하는 대신 define 메소드 명령을 사용하여 필요에 따라 이러한 메소드를 즉시 생성합니다.


4
define_method의 유일한 문제점은 ruby ​​1.8에서 블록을 매개 변수로 전달할 수 없다는 것입니다. 해결 방법 은 이 블로그 게시물 을 참조하십시오 .
Andrew Grimm


23

module_function

module_function 으로 선언 된 모듈 메소드 는 모듈을 포함하는 클래스에서 개인용 인스턴스 메소드 로 자신의 사본을 작성 합니다.

module M
  def not!
    'not!'
  end
  module_function :not!
end

class C
  include M

  def fun
    not!
  end
end

M.not!     # => 'not!
C.new.fun  # => 'not!'
C.new.not! # => NoMethodError: private method `not!' called for #<C:0x1261a00>

인수없이 module_function 을 사용 하면 module_function 문 다음에 오는 모든 모듈 메소드가 자동으로 module_functions가됩니다.

module M
  module_function

  def not!
    'not!'
  end

  def yea!
    'yea!'
  end
end


class C
  include M

  def fun
    not! + ' ' + yea!
  end
end
M.not!     # => 'not!'
M.yea!     # => 'yea!'
C.new.fun  # => 'not! yea!'

4
모듈에서 private 메소드를 선언하려면 private 키워드를 사용하십시오. module_function은 모듈을 포함하는 클래스에서 메소드를 전용으로 설정하는 것 외에도 메소드를 모듈 인스턴스에 복사합니다. 대부분의 경우 이것은 원하는 것이 아닙니다.
tomafro 2009

나는 당신이 개인을 사용할 수 있다는 것을 알고 있습니다. 그러나 이것은 루비의 숨겨진 기능에 관한 질문입니다. 그리고 나는 대부분의 사람들이 문서에서 그것을보고 그것을 가지고 놀기 시작할 때까지 module_function (나 자신을 포함)에 대해 들어 본 적이 없다고 생각합니다.
newtonapple

사용하는 대신 module_function(2 방법) 만 사용하는 것입니다 extend self(꽤 좋은 보이는 : D를)
J -_- L


21

경고 :이 항목은 2008 년 1 위 Most Horrendous Hack 으로 선정되었습니다 . 사실, 전염병처럼 피하십시오.하지만 가장 확실한 것은 숨겨진 루비입니다.

수퍼 레이터는 Ruby에 새로운 연산자 추가

코드에서 일부 고유 한 작업을위한 초 비밀 핸드 셰이크 연산자를 원하십니까? 코드 골프를하는 것처럼? -~ + ~-또는 <---와 같은 연산자를 사용하십시오. 마지막 연산자는 예제에서 항목의 순서를 반대로하는 데 사용됩니다.

나는 그것을 감탄하는 것 이상으로 수퍼 레이터 프로젝트 와 아무 관련이 없습니다 .


19

나는 파티에 늦었지만

두 개의 동일한 길이의 배열을 쉽게 가져 와서 하나의 배열로 키를 제공하고 다른 하나는 값을 해시로 전환 할 수 있습니다.

a = [:x, :y, :z]
b = [123, 456, 789]

Hash[a.zip(b)]
# => { :x => 123, :y => 456, :z => 789 }

이는 Array # zip이 두 배열의 값을 "zip"으로 만들기 때문에 작동합니다.

a.zip(b)  # => [[:x, 123], [:y, 456], [:z, 789]]

그리고 Hash []는 그러한 배열을 취할 수 있습니다. 나는 사람들이 이것을하는 것을 보았습니다.

Hash[*a.zip(b).flatten]  # unnecessary!

어느 결과가 같은 결과를 낼지 모르지만, 스 플랫과 플래 튼은 전적으로 불필요합니다. 아마도 과거에는 없었을까요?)


3
이것은 실제로 오랫동안 문서화되지 않았습니다 ( redmine.ruby-lang.org/issues/show/1385 참조 ). 이 새로운 폼은 Ruby 1.8.7의 새로운 기능입니다
Marc-André

19

루비에서 자동 활성화 해시

def cnh # silly name "create nested hash"
  Hash.new {|h,k| h[k] = Hash.new(&h.default_proc)}
end
my_hash = cnh
my_hash[1][2][3] = 4
my_hash # => { 1 => { 2 => { 3 =>4 } } }

이것은 단지 편리 할 수 ​​있습니다.


1
나는 네이티브 해시 초기화와 같은 느낌을 갖도록 모듈로 포장 할 것이다.module InfHash; def self.new; Hash.new {|h,k| h[k] = Hash.new(&h.default_proc)}; end; end
asaaki

16

배열 파괴

(a, b), c, d = [ [:a, :b ], :c, [:d1, :d2] ]

어디:

a #=> :a
b #=> :b
c #=> :c
d #=> [:d1, :d2]

이 기법을 사용하면 간단한 할당을 사용하여 원하는 깊이의 중첩 배열에서 원하는 정확한 값을 얻을 수 있습니다.


15

Class.new()

런타임에 새 클래스를 작성하십시오. 인수는 파생 클래스가 될 수 있으며 블록은 클래스 본문입니다. 또한보고 할 수 있습니다 const_set/const_get/const_defined?, 새로운 클래스가 제대로 등록하려면 그래서 inspect이름 대신 번호를 출력합니다.

매일 필요한 것은 아니지만 할 때 매우 편리합니다.


1
MyClass = Class.new Array do; def hi; 'hi'; end; end에 해당하는 것 같습니다 class MyClass < Array; def hi; 'hi'; end; end.
yfeldblum

1
아마도 내가 생각했던 것보다 더 사실 일 것입니다. 상수가 아닌 변수에서 상속받을 수도 있습니다. 그러나 런타임에 클래스 이름을 구성해야하는 경우 설탕 버전 (초)이 작동하지 않는 것 같습니다. (물론 평가, 물론.)
Justin Love

이 기술은 메타 프로그래밍 루비 책에 잘 설명되어 있습니다.
Paul Pladijs

13

연속적인 숫자의 배열을 만듭니다.

x = [*0..5]

x를 [0, 1, 2, 3, 4, 5]로 설정


그러나 짧고 달콤하지는 않습니다.)
horseyguy

2
간결함은 객관적이며, 가독성은 맛과 경험의 문제입니다
Alexey

splat ( *) 연산자는 기본적으로 to_a어쨌든 호출 합니다.
Matheus Moreira

13

Rubyland에서 볼 수있는 많은 마법은 메타 프로그래밍과 관련이 있습니다. 메타 프로그래밍은 단순히 코드를 작성하는 코드를 작성하는 것입니다. 루비의 attr_accessor, attr_reader, 그리고 attr_writer그들이 표준 패턴 다음 한 줄에 두 가지 방법을 생성한다는 점에서, 모든 단순 메타 프로그래밍입니다. Rails는 has_oneand와 같은 관계 관리 방법을 사용하여 많은 메타 프로그래밍을 수행합니다 belongs_to.

그러나 class_eval동적으로 작성된 코드를 실행 하는 데 사용 하는 자체 메타 프로그래밍 트릭을 만드는 것은 매우 간단 합니다.

다음 예제는 랩퍼 오브젝트가 특정 메소드를 내부 오브젝트로 전달할 수 있도록합니다.

class Wrapper
  attr_accessor :internal

  def self.forwards(*methods)
    methods.each do |method|
      define_method method do |*arguments, &block|
        internal.send method, *arguments, &block
      end
    end
  end

  forwards :to_i, :length, :split
end

w = Wrapper.new
w.internal = "12 13 14"
w.to_i        # => 12
w.length      # => 8
w.split('1')  # => ["", "2 ", "3 ", "4"]

이 메소드 Wrapper.forwards는 메소드 이름의 기호를 가져 와서 methods배열에 저장합니다 . 그런 다음 주어진 각 define_method인수에 대해 모든 인수와 블록을 포함하여 메시지를 보내는 작업을 수행하는 새 메소드를 작성하는 데 사용 합니다.

메타 프로그래밍 문제에 대한 훌륭한 리소스 는 Lucky Stiff의 "메타 프로그래밍을 분명히 보는 이유" 입니다.


먼저 루비에서 메타 프로그래밍을 시작하겠습니다. 시작하기 위해 몇 가지 참조를 제공 할 수 있습니까 (주어진 링크 이외)? 책도 마찬가지입니다. 감사.
Chirantan 2009

PragProg의 videocasting 세리 "루비 개체 모델 및 메타 프로그래밍"메타 프로그래밍의 좋은 소개 루비를 사용하여 : pragprog.com/screencasts/v-dtrubyom/...
caffo

@Chirantan, Metaprogramming Ruby를 살펴보십시오 .
Paul Pladijs

12

===(obj)사례 비교에 응답하는 모든 것을 사용하십시오 .

case foo
when /baz/
  do_something_with_the_string_matching_baz
when 12..15
  do_something_with_the_integer_between_12_and_15
when lambda { |x| x % 5 == 0 }
  # only works in Ruby 1.9 or if you alias Proc#call as Proc#===
  do_something_with_the_integer_that_is_a_multiple_of_5
when Bar
  do_something_with_the_instance_of_Bar
when some_object
  do_something_with_the_thing_that_matches_some_object
end

Module(따라서는 Class) Regexp, Date(기타) === 모두 사용될 수있다, 다른 많은 클래스 인스턴스 메소드를 정의한다.

Ruby 1.9에서 와 같이 별칭이 지정 되었음을 상기시켜 준 Farrel 에게 감사합니다 .Proc#callProc#===


11

"루비"바이너리 (적어도 MRI)는 perl one-liner를 매우 대중적으로 만든 많은 스위치를 지원합니다.

중요한 것들 :

  • -n "gets"만으로 외부 루프를 설정합니다.이 파일은 주어진 파일 이름 또는 STDIN과 마술처럼 작동하여 $ _에 각 읽기 행을 설정합니다.
  • -p -n과 유사하지만 put각 루프 반복 끝에 자동 s가 있습니다.
  • -a $ F에 저장된 각 입력 라인에서 .split에 대한 자동 호출
  • -i 내부 편집 입력 파일
  • -l 입력시 .chomp에 대한 자동 호출
  • -e 코드를 실행
  • -c 소스 코드 확인
  • -w 경고와 함께

몇 가지 예 :

# Print each line with its number:
ruby -ne 'print($., ": ", $_)' < /etc/irbrc

# Print each line reversed:
ruby -lne 'puts $_.reverse' < /etc/irbrc

# Print the second column from an input CSV (dumb - no balanced quote support etc):
ruby -F, -ane 'puts $F[1]' < /etc/irbrc

# Print lines that contain "eat"
ruby -ne 'puts $_ if /eat/i' < /etc/irbrc

# Same as above:
ruby -pe 'next unless /eat/i' < /etc/irbrc

# Pass-through (like cat, but with possible line-end munging):
ruby -p -e '' < /etc/irbrc

# Uppercase all input:
ruby -p -e '$_.upcase!' < /etc/irbrc

# Same as above, but actually write to the input file, and make a backup first with extension .bak - Notice that inplace edit REQUIRES input files, not an input STDIN:
ruby -i.bak -p -e '$_.upcase!' /etc/irbrc

더 유용하고 실용적인 톤을 찾기 위해 Google "루비 원 라이너"및 "펄 원 라이너"를 자유롭게 사용하십시오. 본질적으로 루비를 awk와 sed의 상당히 강력한 대체물로 사용할 수 있습니다.


10

전송 () 메소드는 루비의 모든 클래스 나 객체에 사용할 수있는 범용 방법이다. 재정의되지 않으면 send ()는 문자열을 허용하고 문자열이 전달 된 메서드의 이름을 호출합니다. 예를 들어, 사용자가 "Clr"버튼을 클릭하면 'press_clear'문자열이 send () 메소드로 전송되고 'press_clear'메소드가 호출됩니다. send () 메소드를 사용하면 Ruby에서 함수를 재미 있고 동적으로 호출 할 수 있습니다.

 %w(7 8 9 / 4 5 6 * 1 2 3 - 0 Clr = +).each do |btn|
    button btn, :width => 46, :height => 46 do
      method = case btn
        when /[0-9]/: 'press_'+btn
        when 'Clr': 'press_clear'
        when '=': 'press_equals'
        when '+': 'press_add'
        when '-': 'press_sub'
        when '*': 'press_times'
        when '/': 'press_div'
      end

      number.send(method)
      number_field.replace strong(number)
    end
  end

이 기능에 대해서는 Blogging Shoes : The Simple-Calc Application 에서 더 자세히 설명합니다 .


보안 허점을 여는 좋은 방법 인 것 같습니다.
mP.

4
가능한 한 기호를 사용합니다.
reto

9

실제로 필요하지 않은 것이 필요하다고 말하는 클래스 또는 모듈을 속이십시오.

$" << "something"

이것은 예를 들어 A를 요구할 때 유용하지만 B에는 필요하지만 코드에는 B가 필요하지 않습니다 (그리고 A는 코드를 통해 그것을 사용하지 않을 것입니다).

예를 들어 Backgroundrb 's bdrb_test_helper requires 'test/spec'이지만 코드에서 전혀 사용하지 않습니다.

$" << "test/spec"
require File.join(File.dirname(__FILE__) + "/../bdrb_test_helper")

gem A에 foo-1.0.0이 필요하고 gem B에 foo-1.0.1이 필요한 문제를 해결합니까?
Andrew Grimm

"something"의 코드를 사용할 수 없기 때문에 아니요. "something"이 필요하다는 것만 시뮬레이트하지만 실제로는 필요하지 않습니다. $ "는 require에 의해로드 된 모듈 이름을 포함하는 배열입니다 (모듈을 두 번로드하지 못하게하는 데 사용됩니다). 따라서이를 보석을 속이는 데 사용하면 보석이 실제"무언가 "를 사용하려고 할 때 충돌이 발생합니다. 코드가 존재하지 않기 때문에, 대신 최신 버전 대신에 젬의 구체적인 버전 (예 : foo-1.0.0)을 강제로 강제로 래딩 할 수도 있습니다 : docs.rubygems.org/read/chapter/4#page71
olegueret

9

Fixnum#to_s(base)어떤 경우에는 정말 유용 할 수 있습니다. 이러한 경우 중 하나는 36의 밑을 사용하여 난수를 문자열로 변환하여 난수 (의사) 고유 토큰을 생성하는 것입니다.

길이 8의 토큰 :

rand(36**8).to_s(36) => "fmhpjfao"
rand(36**8).to_s(36) => "gcer9ecu"
rand(36**8).to_s(36) => "krpm0h9r"

길이 6의 토큰 :

rand(36**6).to_s(36) => "bvhl8d"
rand(36**6).to_s(36) => "lb7tis"
rand(36**6).to_s(36) => "ibwgeh"

9

임의의 수의 매개 변수를 허용하고 모든 매개 변수를 버리는 메소드 정의

def hello(*)
    super
    puts "hello!"
end

위의 hello메소드 puts "hello"는 화면에서 호출하고 호출 super하면되지만 수퍼 클래스 hello는 매개 변수도 정의해야하기 때문에 실제로 매개 변수 자체를 사용할 필요가 없으므로 이름을 지정할 필요가 없습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.