什么时候在Model中使用self?

var*_*tis 69 ruby-on-rails self ruby-on-rails-3 ruby-on-rails-3.1

问题:我什么时候需要在Rails的模型中使用self?

我的一个set模型中有一个方法.

class SomeData < ActiveRecord::Base
  def set_active_flag(val)
    self.active_flag = val
    self.save!
  end
end
Run Code Online (Sandbox Code Playgroud)

当我这样做,一切正常.但是,当我这样做时:

class SomeData < ActiveRecord::Base
  def set_active_flag(val)
    active_flag = val
    save!
  end
end
Run Code Online (Sandbox Code Playgroud)

active_flag值不会更改,而是静默失败.谁能解释一下?

我找不到任何副本,但如果有人发现一个也没关系.

DVG*_*DVG 64

当您在调用方法的实例上执行操作时,您使用self.

有了这段代码

class SocialData < ActiveRecord::Base
  def set_active_flag(val)
    active_flag = val
    save!
  end
end
Run Code Online (Sandbox Code Playgroud)

您正在定义一个名为active_flag的全新范围​​的局部变量,将其设置为传入的值,它与任何东西都没有关联,因此当方法结束时它会立即丢失,就像它从未存在过一样.

self.active_flag = val
Run Code Online (Sandbox Code Playgroud)

但是告诉实例修改自己的名为active_flag的属性,而不是一个全新的变量.这就是它的原因.

  • "当你在调用方法的实例上执行操作时,你会使用self." 那不太准确.在没有"self"的情况下,在当前对象上调用(非setter)方法就可以正常工作.设置实例变量(直接)也是如此 - 事实上你不能使用`self`(无论如何没有反射). (7认同)
  • @varatis:由于变量未在ruby中声明,因此创建变量的唯一方法是为其分配内容.Java可以判断`foo = bar`是分配给局部变量还是实例变量,因为它只能查看是否已声明具有该名称的局部变量.Ruby不能这样做,因为没有声明.你可以说"如果存在一个调用setter方法 - 否则创建一个局部变量",但是你会遇到`method_missing`的问题.另请注意,`self.foo = bar`调用名为`foo =`的方法,它不直接(直接)设置实例变量. (3认同)

Yuv*_*rmi 57

这是因为范围界定.当你在一个方法内,并尝试设置一个像这样的新变量:

class SomeData < ActiveRecord::Base
  def set_active_flag(val)
    active_flag = val
  end
end
Run Code Online (Sandbox Code Playgroud)

您正在创建一个存在于set_active_flag内的全新变量.一旦完成执行,它就会消失,而不self.active_flag是以任何方式改变(实际的实例变量).

但是(这对我来说是一个混乱的来源):当你尝试在ruby中读取一个实例变量时,如下所示:

class SomeData < ActiveRecord::Base
  def whats_my_active_flag
    puts active_flag
  end
end
Run Code Online (Sandbox Code Playgroud)

你实际上会得到self.active_flag(实际的实例变量).


原因如下:

Ruby会尽其所能避免返回nil.

  1. 它最初问"确实active_flag存在于whats_my_active_flag?范围内?
  2. 它搜索并实现了答案是"不",所以它跳一级,至SomeData实例
  3. 它又问了同样的事情:" active_flag这个范围内确实存在吗?
  4. 答案是"是",因此它说"我得到了一些东西",它就会回来!

但是,如果您active_flag在其中定义whats_my_active_flag,然后请求它,它将再次执行以下步骤:

  1. 它问"确实active_flag存在于whats_my_active_flag?范围内?
  2. 答案是"是",所以它返回该值

在任何一种情况下,除非您明确告诉它,否则它不会更改self.active_flag.

描述这种行为的一种简单方法是"它不想让你失望"并返回nil- 所以它尽力找到它能做到的一切.

同时,"它不想搞乱你不打算改变的数据",因此它不会改变实例变量本身.

希望这可以帮助!

  • 很棒的解释.我一直在寻找一个小时试图找出为什么我需要使用self来设置值,但是可以跳转到不同的方法并使用看似本地变量的读取而不使用self (3认同)