3

ハッシュコレクションをクラスのメソッドに変換するために使用している次のコードがあります(アクティブレコードのようなものです)。私が抱えている問題は、セッターが機能していないことです。私はまだRubyに慣れていないので、少し振り返ったと思います。

class TheClass
  def initialize
    @properties = {"my hash"}
    self.extend @properties.to_methods
  end
end

class Hash
  def to_methods
    hash = self
    Module.new do
      hash.each_pair do |key, value|
        define_method key do
          value
        end
        define_method("#{key}=") do |val|
          instance_variable_set("@#{key}", val)
        end
      end
    end
  end
end

メソッドが作成され、クラスで読み取ることができますが、設定しても機能しません。

myClass = TheClass.new
item = myClass.property # will work.
myClass.property = item # this is what is currently not working.
4

4 に答える 4

8

動的プロパティを設定することが目標の場合は、OpenStructを使用できます。

require 'ostruct'

person = OpenStruct.new
person.name = "Jennifer Tilly"
person.age = 52

puts person.name     
# => "Jennifer Tilly"
puts person.phone_number 
# => nil

ハッシュからそれらを作成するためのサポートも組み込まれています

hash = { :name => "Earth", :population => 6_902_312_042 }
planet = OpenStruct.new(hash)
于 2011-03-11T14:12:11.183 に答える
4

getterメソッドは、常に元のハッシュの値を返します。インスタンス変数を設定しても、それは変わりません。ゲッターにインスタンス変数を参照させる必要があります。何かのようなもの:

hash.each_pair do |key, value|
  define_method key do
    instance_variable_get("@#{key}")
  end
  # ... define the setter as before
end

また、最初にインスタンス変数を設定する必要があります。

@properties.each_pair do |key,val|
  instance_variable_set("@#{key}",val)
end

initializeメソッドで。

注:これが最善の方法であることを保証するものではありません。私はRubyの専門家ではありません。しかし、それは機能します。

于 2011-03-11T14:02:42.910 に答える
2

それは私にとってはうまく機能します(もちろん、コードの明らかな構文エラーを修正した後):

myClass.instance_variable_get(:@property) # => nil
myClass.property = 42
myClass.instance_variable_get(:@property) # => 42

Ruby ではインスタンス変数は常にプライベートであり、ゲッターを定義することはないため、(リフレクション以外で) 外部から実際にそれらを見ることはできませんが、それはコードが機能しないという意味ではありません。機能していることを確認できないことのみを意味します。

于 2011-03-11T14:07:49.090 に答える
0

これは本質的に、私が method_missing で提案していたことです。どちらのルートについても、使用する理由または使用しない理由を説明するのに十分なほど詳しくないため、上記で質問しました。基本的に、これによりプロパティが自動生成されます。

def method_missing sym, *args
   name = sym.to_s
   aname = name.sub("=","")

   self.class.module_eval do 
      attr_accessor aname
   end
  send name, args.first unless aname == name
end
于 2011-03-11T14:04:32.667 に答える