如何在 ruby 中动态创建带参数的方法?

How to dynamically create methods with parameter in ruby?

如何使用 ruby 元编程动态创建这样的方法?

class CommentBridge < Bridge

  def id(comment)
    comment.id
  end

  def message(comment)
    comment.message
  end

  def votes_count(comment)
    comment.votes_count
  end

end

我试过了,但没用。

  ['id', 'message', 'votes_count'].each do |method|
    define_method "#{method}" do |parameter|
      method(parameter.method)
    end
  end

您应该使用 public_send 根据名称调用方法:

  ['id', 'message', 'votes_count'].each do |method|
    define_method "#{method}" do |parameter|
      parameter.public_send(method)
    end
  end

我不认为你每次都需要不同的评论(可能你需要)。所以我建议简单地摆脱这个 comment 论点。 有选项。

使用 RubyOnRails(我看到你的问题是这样标记的)你可以使用 delegate(@SimpleLime 已经评论过)

class CommentBridge < Bridge
  attr_reader :comment
  def initialize(comment_)
    @comment = comment_)
  end
  delegate :id, :message, :votes_count, to: :comment
end

在纯Ruby2的情况下使用Forwardable:

class CommentBridge
  extend Forwardable
  attr_reader :comment
  def initialize(comment_)
    @comment = comment_)
  end
  def_delegators :comment, :id, :message, :votes_count
end 

如果您想在评论对象之上提供其他方法并转发所有其余方法,请使用 SimpleDelegator(假设 namgin 中的这个 Brigde 意味着您的 class 只是一个包装器) :

class CommentDecorator < SimpleDelegator
  def hello
    'hello'
  end
end

comment = Commend.find(params[:id])
decorated_comment = CommentDecorator.new(comment)

你也可以定义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

最后,您可以在 define_method 之上创建自己的 delegation-DSL,但我认为在这种情况下这是额外的。

我认为 method_missingdefine_method 内部循环虽然有效,但并不整洁。