Ruby Metaprogramming : 동적 인스턴스 변수 이름


94

다음 해시가 있다고 가정 해 보겠습니다.

{ :foo => 'bar', :baz => 'qux' }

객체의 인스턴스 변수가되도록 키와 값을 어떻게 동적으로 설정할 수 있습니까?

class Example
  def initialize( hash )
    ... magic happens here...
  end
end

... 그래서 모델 내부에서 다음과 같이 끝납니다.

@foo = 'bar'
@baz = 'qux'

?

답변:


168

당신이 찾고있는 방법은 instance_variable_set입니다. 그래서:

hash.each { |name, value| instance_variable_set(name, value) }

또는 더 간단히

hash.each &method(:instance_variable_set)

인스턴스 변수 이름에 "@"가 누락 된 경우 (OP의 예에서와 같이) 추가해야하므로 다음과 비슷합니다.

hash.each { |name, value| instance_variable_set("@#{name}", value) }

18
1.9.3에서 나를 위해 작동하지 않았습니다. 나는 이것을 대신 사용했다hash.each {|k,v| instance_variable_set("@#{k}",v)}
Andrei

3
사랑 루비에 대한 또 다른 이유
jschorr

hash.each &method(:instance_variable_set)에서 메서드 instance_variable_set가 필요한 두 개의 매개 변수를받는 방법을 설명해 주 시겠습니까?
Arnold Roa

재귀 적으로 수행하는 방법에 대한 아이디어가 있습니까? (입력 해시에 여러 수준이있는 경우)
nemenems

13
h = { :foo => 'bar', :baz => 'qux' }

o = Struct.new(*h.keys).new(*h.values)

o.baz
 => "qux" 
o.foo
 => "bar" 

1
꽤 흥미 롭군요 ... 두 번째 체인이 정확히 무엇을 .new()하고 있습니까?
Andrew

3
@Andrew : Struct.new해시 키를 기반으로 새 클래스를 만든 다음 두 번째 new는 방금 만든 클래스의 첫 번째 개체를 만들어 Hash 값으로 초기화합니다. 참조 ruby-doc.org/core-1.8.7/classes/Struct.html
DigitalRoss

2
이것은 실제로 Struct가 만든 것이므로 실제로 할 수있는 정말 좋은 방법입니다.

2
또는 OpenStruct를 사용 하십시오 . require 'ostruct'; h = {:foo => 'foo'}; o = OpenStruct.new(h); o.foo == 'foo'
저스틴 포스

내 키를 기호에 매핑해야했습니다.Struct.new(*hash.keys.map { |str| str.to_sym }).new(*hash.values)
erran

7

당신은 우리가 울고 싶어합니다 :)

어쨌든 참조 Object#instance_variable_getObject#instance_variable_set .

즐거운 코딩입니다.


어 그래, 나는 궁금해 할 수 없었다 ... 왜? 이것을 사용하기에 좋은 시간이 언제입니까?
Zach Smith

예를 들어 set_entity모든 컨트롤러에 대한 일반 콜백을 원하고 기존 인스턴스 변수를 방해하고 싶지 않을 수 있습니다def set_entity(name, model); instance_variable_set(name, model.find_by(params[:id])); end;
user1201917

5

send사용자가 존재하지 않는 인스턴스 변수를 설정하지 못하도록하는 방법 을 사용할 수도 있습니다 .

def initialize(hash)
  hash.each { |key, value| send("#{key}=", value) }
end

send클래스에 attr_accessor인스턴스 변수 와 같은 setter가있을 때 사용하십시오 .

class Example
  attr_accessor :foo, :baz
  def initialize(hash)
    hash.each { |key, value| send("#{key}=", value) }
  end
end
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.