Ruby setter=未调用的方法

Ruby setter=未调用的方法,ruby,ruby-on-rails-3,Ruby,Ruby On Rails 3,我发现的每个setter=语法示例都非常简单,即 def name=(value) @name = value end 你能用这个语法做一些更复杂的事情吗?特别是,您可以在没有相应实例变量的情况下使用它吗?可以是私人的吗?你能做些验证吗 我正在编写一个Rails控制器,可以对其进行扩展,为作为资源路由的模型提供基本的CRUD功能。它使用class_属性设置要控制的模型的名称,并基于模型的名称创建实例变量。它看起来像这样 class ResourceController class_at

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

def name=(value)
  @name = value
end
你能用这个语法做一些更复杂的事情吗?特别是,您可以在没有相应实例变量的情况下使用它吗?可以是私人的吗?你能做些验证吗

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

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
通过上面的代码结构,我在视图中得到了一个
NoMethodError
,因为视图有一个Nil实例变量。使用
logger.debug
我可以一直跟踪堆栈到
resource=…
,但是没有调用
resource=

如果我放下糖,使用
设置资源(值)
一切正常。我是对setter=语法要求太高了,还是缺少了其他问题?

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

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

  • 可以是私人的吗

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

  • 你能做些验证吗

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

=
结尾的方法有一定的特殊性,使它们特别适合设置者。这些是:

  • 他们期望有一个论点
  • 它们总是自动将此参数作为返回值返回

但并没有规定必须将它们用于二传手。如果一个人发现自己的行为有其他用途,那么可以将哪些代码放入其中就没有限制。

这很有意义。非常感谢。还有一个问题,您说
.send
是调用该方法的唯一方法,但是从同一类中的实例方法内部,为什么
self.resource=
不起作用?或者,假设方法是受保护的而不是私有的,为什么
super.resource=
不能在扩展类中工作?@BorisStitnicky我想你是对的。我错过了。在答案中添加了这一点。@user2754741我不明白您为什么要询问
self.resource=
。我以为你想让方法保密。如果它是受保护的,那么我认为
super.resource=
会起作用。我对private的理解是,只能从定义它的类中调用它,但根据您的回答,即使是从定义类中调用它,也需要显式的接收者。从类中的实例方法来看,
self
不是显式的接收者吗?当您在没有显式接收器的情况下调用方法时,
self
不是隐含接收器吗?“它需要显式接收器”=>不,它不能有显式接收器。要知道,一个明显的行为是将任何类设置为状态机。
def something=( arg )
  # do anything
end