Method for Creating Methods: Easy Ruby Metaprogramming

I have a bunch of methods like this helle

def background "#e9eaec" end def footer_link_color "#836448" end 

I would like these methods to appear in the view, but I would prefer the helper to be a bit more concise. What is the best way to turn a hash into, say, methods (or something else)?

+4
source share
4 answers
 module MyHelper {:background => "#e9eaec", :footer_link_color => "#836448"}.each do |k,v| define_method(k) {v} end end 

Although I do not think that trading this brief conciseness for readability of your first approach is necessarily a good idea.

If you want to generalize this, you can add the following class to the module class:

 class Module def methods_from_hash(hash) hash.each do |k,v| define_method(k) {v} end end end 

And then in your helper call methods_from_hash(:background => ...) .

+3
source

If you create constants in the namespace, then you can easily crack accessors for these constants:

 class Foo module Values FOO = 1 BAR = 'bar' BAZ = :baz end include Values Values.constants.each do |name| define_method(name.downcase) do Values.const_get(name) end end end foo = Foo.new p foo.foo # => 1 p foo.bar # => "bar" p foo.baz # => :baz 

include Values mixes constants in Foo for the convenience of Foo's own methods. This template does not need to work.

+3
source

In fact, ruby ​​has something called OpenStruct , which is quite surprising and very useful when you want a hash but don't want to use it as one.

 require 'ostruct' colors = OpenStruct.new({:background => "0x00FF00", :color => "0xFF00FF"}) p colors.background #=> "0x00FF00" 
+2
source

Here is my remix on sepp2k. This is a bit more OO and works even in irb . Not sure if you need to schedule an Object or Hash .

 class Hash def keys_to_methods() each do |k,v| self.class.send(:define_method, k, Proc.new {v}); end length end end 

Test code

 hash = {:color_one=>"black", :color_two=>"green"} hash.keys_to_methods has.color_one # returns black 

OpenStruct : thanks sepp2k again! I did not know this one .

Here is another version using method_missing

 class Hash def method_missing(method_id) key = method_id.id2name if has_key?(key) return self[key] elsif has_key?(key.to_sym) return self[key.to_sym] else super.method_missing(method_id) end end end hash = {:color_one=>"black", :color_two=>"green"} hash.color_one 

I'm sure I can get the code more rigorous (if I knew how to do this).

0
source

Source: https://habr.com/ru/post/1310045/


All Articles