Ruby setter =没有被调用的方法

时间:2013-09-18 16:09:36

标签: ruby ruby-on-rails-3

我发现的setter =语法的每个例子都非常简单,即;

def name=(value)
  @name = value
end

使用这种语法可以做一些更复杂的事情吗?特别是,您可以在没有相应实例变量的情况下使用它吗?它可以是私人的吗?你能做某种验证吗?

我正在编写一个Rails控制器,可以对其进行扩展,以便为作为资源路由的模型提供基本的CRUD功能。它使用class_attribute来设置它将控制的Model的名称,并根据Model的名称创建一个实例变量。它看起来像这样;

class ResourceController
  class_attribute :model_class_name

  def new
    resource = self.model_class_name.new
  end

  protected
    def self.init_resource(options={})
      self.model_class_name = options[:model_class_name]
    end 

  private
    def resource
      instance_variable_get(resource_instance_var)
    end

    def resource=(value)
      instance_variable_set(resource_instance_var ,value)
    end

    def resource_instance_var 
      "@#{self.resource_class.name.underscore}".to_sym
    end
end

使用上面的代码结构,我在View中得到NoMethodError,因为View有一个Nil实例变量。使用logger.debug我可以跟踪堆栈一直到resource = ...,但resource=没有被调用。

如果我放糖并使用set_resource(value)一切正常。我是不是从setter =语法中问了太多,还是我还缺少其他一些问题?

2 个答案:

答案 0 :(得分:1)

  • 您可以在没有相应实例变量的情况下使用它吗?

    是。将其分配给具有任何名称的实例变量。

  • 可以私密吗?

    是和否。您可以定义foo=形式的私有方法。 ,但您永远无法以普通方式调用它(即,不使用send或添加括号)。当表达式在引用/赋值给局部变量和方法调用之间不明确时,它将被解释为对局部变量的引用/赋值。这种Setter方法总是需要一个明确的接收器。这也是你得到错误的原因。未调用setter方法,因为您没有显式写入接收器。

  • 你能做某种验证吗?

    是。在实例变量赋值之前放置任何验证代码。

答案 1 :(得分:0)

def something=( arg )
  # do anything
end

=结尾的方法具有某些细节,使它们特别适合setter。这些是:

  • 他们期待1个参数
  • 他们总是自动将此参数作为返回值返回。

但没有规则说他们必须用于制定者。如果有人发现他们的行为有其他用途,那么可以在其中放入什么代码没有限制。