Reputation: 1332
How can I dynamically create methods like this using ruby metaprogramming ?
class CommentBridge < Bridge
def id(comment)
comment.id
end
def message(comment)
comment.message
end
def votes_count(comment)
comment.votes_count
end
end
I tried this but it is not working.
['id', 'message', 'votes_count'].each do |method|
define_method "#{method}" do |parameter|
method(parameter.method)
end
end
Upvotes: 2
Views: 696
Reputation: 4230
I do not think that you need different comment every time (probably you do). So I'd recommend to simply get rid of this comment
argument.
There are the options.
Using RubyOnRails (I see you question is tagged so) you can use delegate
(as @SimpleLime has already commented)
class CommentBridge < Bridge
attr_reader :comment
def initialize(comment_)
@comment = comment_)
end
delegate :id, :message, :votes_count, to: :comment
end
In case of pure Ruby 2 use Forwardable
:
class CommentBridge
extend Forwardable
attr_reader :comment
def initialize(comment_)
@comment = comment_)
end
def_delegators :comment, :id, :message, :votes_count
end
If you want to provide additional methods on top of you comment object and forward all the rest methods use SimpleDelegator
(assuming that this Brigde in namgin means that your class is just a wrapper):
class CommentDecorator < SimpleDelegator
def hello
'hello'
end
end
comment = Commend.find(params[:id])
decorated_comment = CommentDecorator.new(comment)
You can also define method missing
:
class CommentBridge < Bridge
attr_reader :comment
def initialize(comment_)
@comment = comment_)
end
def method_missing(m, *args)
if [:id, :message, :comment].include?(m)
comment.public_send(method, *args)
else
super
end
end
end
Finally, you can create your own delegation-DSL on top of define_method
, but I think this is the extra in that case.
I don't think that method_missing
or define_method
inside loop is neat although it works.
Upvotes: 0
Reputation: 23307
You should use public_send
to call methods based on their name:
['id', 'message', 'votes_count'].each do |method|
define_method "#{method}" do |parameter|
parameter.public_send(method)
end
end
Upvotes: 3