Home > Net >  Dynamic method creation from block parameter
Dynamic method creation from block parameter

Time:10-19

I have the following structure of data

array_of_hashes = [{"key"=>"2020-10-01",
  "foo"=>"100",
  "bar"=>38,
  "baz"=>19,
  "losem"=>19,
  "ipsum"=>0,
  ...},
...
]
state =  {["", nil, nil, nil, nil]=>
          #<MySimpleObject:0x0000557fb9fe4708
          @foo=0.0,
          @bar=0.0,
          @baz=0.0,
          @lorem=0.0,
          @ipsum=0.0,
          ...}

array_of_hashes.each_with_object(state) do |stats, memo|
  state = memo['key']

  state.foo = stats['foo'].to_d
  state.bar = stats['bar'].to_d
  state.baz = stats['baz'].to_d
  state.lorem = stats['lorem'].to_d
  state.ipsum = stats['ipsum'].to_d
  ...
end

How may I follow dry in this case? I need smth to generate and execute methods in runtime like:

query.each_with_object(shared_state) do |stats, memo|
  state = memo['key']

  columns = %w[foo bar baz lorem ipsum ...]
  columns.each { |attribute|
    define_method attribute do #??????
      state.attribute = stats[attribute.to_s].to_d
    end
  }
end

As I got it define_method is not suitable for this situation.

CodePudding user response:

Short answer, don't! This will make your code incredible hard to read. What you have in your first example is perfectly fine in my opinion. Not everything needs to be DRY.

If you really really want to do it, you can use send

query.each_with_object(shared_state) do |stats, memo|
  state = memo['key']

  columns = %w[foo bar baz lorem ipsum ...]
  columns.each do |attribute|
    state.send("#{attribute}=", stats[attribute].to_d) 
  end
end

https://apidock.com/ruby/Object/send

  • Related