简体   繁体   中英

Ruby - How to Merge a Hash into a method

I have this method

def method1
 {
  headers: { 'Content-Type' => 'application/json' }
 }
end

and this another method for merge a another key and value into this method1 hash, so

def merge_hash
  method1.merge!(body: { params: 123 }
end

so when i call method1 again i expect he returns a marged body and my questions is why not this happens or how i can do it?

Each time you call method1 it returns a new object:

> method1.object_id
=> 47220476550040 
> method1.object_id
=> 47220476543700 

To achieve what you want you can memorize it after the first call:

def method1
  @method1 ||= {
    headers: { 'Content-Type' => 'application/json' }
  }
end

> method1.object_id
=> 47220477154400 
> method1.object_id
=> 47220477154400 

I suggest to not mutate a hash this way because it can lead to bugs.

Of course method1 's return value does not change, because you haven't changed the method itself.

You can use the old and evil technique called alias method chain .

# Define a new method `method1_without_body`
# whose implementation is exactly the same
# as `method1` at this moment.
alias method1_without_body method1

# Define a new method that calls `method1_without_body`.
# Make sure that it does NOT call `method1`,
# or you'll get a stack overflow.
def method1_with_body
  method1_without_body.merge!(body: { params: 123 })
end

# Define a new method `method1`
# whose implementation is exactly the same
# as `method1_with_body`.
# This method shadows the previous implementation of `method1`.
alias method1 method1_with_body

or if you are using Rails < 5, then just

def method1_with_body
  method1_without_body.merge!(body: { params: 123 })
end

alias_method_chain :method1, :body

then when you call method1 , it returns the hash with both headers and body.

By the way, this technique was deprecated since Rails 5 and was totally removed later (I forgot in which minor version).

Perhaps this comes close to what you look at:

class MyClass

    attr_reader :method1

    def initialize
      @method1 = {  headers: { 'Content-Type' => 'application/json' } }
    end

    def merge_hash
      @method1.merge!(body: { params: 123 }
    end

end

Hence, if you have a

o = MyClass.new

the first o.method1 will return the initial hash, but after a

o.merge_hash

an o.method1 will return the modified hash.

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