user10119987
user10119987

Reputation:

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?

Upvotes: 0

Views: 178

Answers (3)

user1934428
user1934428

Reputation: 22366

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.

Upvotes: 0

Aetherus
Aetherus

Reputation: 8898

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).

Upvotes: 0

Yakov
Yakov

Reputation: 3201

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.

Upvotes: 3

Related Questions