简体   繁体   中英

How do I force the same hash value for different object instantiations in RoR?

I'm using RoR 5.0.1. I have a model that is not persisted to a database. It has two fields

first_field
second_field

How do I force different instantiations of the object in which its fields have the same value to have the same hash value? Right now it seems each unique creation of an object has a different hash value, even if the individual attributes have the same values . So if I create two different objects

o1 = MyObject.new({:first_field => 5, :second_field => "a"})

o2 = MyObject.new({:first_field => 5, :second_field => "a"})

I'd like them to have the same hash values even though they are different instantiations of the object.

The behavior you're looking for isn't entirely clear from your question. However, if you want (as Michael Gorman asks) the instances of MyObject to share the same hash instance (such that changes to the values o1 are reflected in the values of o2 ), then you could do something like:

  class MyObject

    def initialize(hsh = {})
      @hsh = hsh
      hsh.each do |k,v|
        class_eval do

          # define the getter
          define_method(k) do 
            @hsh[k]
          end

          # define the setter
          define_method("#{k}=") do |val|
            @hsh[k] = val
          end

        end
      end
    end

  end

Then create a single instance of a hash :

  hsh = {first_field: 5, second_field: "a"}

And instantiate your two objects with this hash :

  o1 = MyObject.new(hsh)
  o2 = MyObject.new(hsh)

Both instances will have the same first_field value:

  2.3.1 :030 > o1.first_field
   => 5 
  2.3.1 :031 > o2.first_field
   => 5 

And changes in o1.first_field will be reflected in o2.first_field :

  2.3.1 :033 > o1.first_field = 7
   => 7 
  2.3.1 :034 > o1.first_field
   => 7 
  2.3.1 :035 > o2.first_field
   => 7 

Same with second_field :

  2.3.1 :037 > o1.second_field
   => "a" 
  2.3.1 :038 > o2.second_field
   => "a" 

  2.3.1 :040 > o1.second_field = "b"
   => "b" 
  2.3.1 :041 > o1.second_field
   => "b" 
  2.3.1 :042 > o2.second_field
   => "b" 

Since the setter and getter are generated dynamically, you could do something like:

  hsh = {first_field: 5, second_field: "a", nth_field: {foo: :bar}}
  o1 = MyObject.new(hsh)

And o1 will respond to nth_field without having to do any extra coding on MyObject :

  2.3.1 :048 > o1.nth_field
   => {:foo=>:bar}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM