ruby:委托if对象响应方法

时间:2012-06-25 11:35:20

标签: ruby delegates activesupport

我想在Ruby中使用委托,但我不能保证目标对象响应我将调用的所有方法。我可以使用默认行为定义委派吗?

E.g。

class DummyPresenter
  delegate :name, :age, :to => :@content, :default => nil
  def initialize(content)
    @content = content
  end
end

class Student
  def name
    "name"
  end
end    

> DummyPresenter.new(Student.new).age # => nil
> DummyPresenter.new(Student.new).name # => "name"

现在,上面的例子会提出:

NoMethodError:
   undefined method `age' for #<Student:0xa121212>

4 个答案:

答案 0 :(得分:3)

def method_missing(method, *args)
  if @content.respond_to? method
    @content.send method, *args
  else
    #your default behaviour (or super)
  end 
end

你也可以使用DelegateClass它会做同样的伎俩。

答案 1 :(得分:2)

我发现将方法委托给原始对象的最简单方法是使用SimpleDelegator(在stdlib中提供)

class Presenter < SimpleDelegator

  def initialize model
    super model
  end

  def foo
    'bar'
  end
end

class Person
  def bam
    'baz'
  end
end

person = Person.new
presenter = Presenter.new Person

presenter.foo # => 'bar'
presenter.bam # => 'baz'

来自文档:

  

SimpleDelegator类提供委派所有支持的方法   方法调用传递给构造函数的对象

答案 2 :(得分:0)

如何不使用委托并像这样手动完成?

class DummyPresenter
  def initialize content; @content = content end
  def name; @content.respond_to?( :name ) ? @content.name : dflt_name end
  def age; @content.respond_to?( :age ) ? @content.age :dflt_age end
  def to; @content.respond_to?( :to ) ? @content.to :dflt_to end
  def dflt_name
    nil # or whathever code
  end
  def dflt_age; nil end
  def dflt_to; nil end
end

或者你必须重新编程委托方法,我认为......

答案 3 :(得分:0)

最后我使用define_method

来完成
class DummyPresenter

  @@delegated_methods = [:name, :age]
  @@delegated_methods.each do |method|
    define_method(method) do
      return @content.try(method) if @content.respond_to?(method)
      nil
    end
  end

 def initialize(content)
   @content = content
 end