什么时候在Model中使用self?

时间:2012-05-29 19:06:09

标签: ruby-on-rails ruby-on-rails-3 ruby-on-rails-3.1 self

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

我的一个模特中有一个set方法。

class SomeData < ActiveRecord::Base
  def set_active_flag(val)
    self.active_flag = val
    self.save!
  end
end

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

class SomeData < ActiveRecord::Base
  def set_active_flag(val)
    active_flag = val
    save!
  end
end

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

我找不到任何重复项,但如果有人发现一个也没问题的话。

4 个答案:

答案 0 :(得分:59)

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

使用此代码

class SocialData < ActiveRecord::Base
  def set_active_flag(val)
    active_flag = val
    save!
  end
end

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

self.active_flag = val

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

答案 1 :(得分:51)

这是因为范围界定而发生的。如果您在某个方法中,并尝试设置这样的新变量:

class SomeData < ActiveRecord::Base
  def set_active_flag(val)
    active_flag = val
  end
end

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

HOWEVER (这让我感到困惑):当您尝试读取 ruby​​中的实例变量时,如下所示:

class SomeData < ActiveRecord::Base
  def whats_my_active_flag
    puts active_flag
  end
end

您实际上会返回self.active_flag(实际的实例变量)。


原因如下:

Ruby会尽其所能避免返回nil

  1. 它最初询问“active_flag
  2. 范围内是否存在”whats_my_active_flag
  3. 它搜索并意识到答案是“nope”,因此它会跳转向上一个级别,到SomeData的实例
  4. 它又问了同样的事情:“这个范围内是否存在active_flag
  5. 答案是“是”,所以它说“我得到了一些东西”,它就会回来!
  6. 但是,如果您在active_flag中定义whats_my_active_flag,然后要求它,则会再次执行这些步骤:

    1. 它询问“active_flag
    2. 范围内是否存在”whats_my_active_flag
    3. 答案是“是”,因此返回该值
    4. 在任何一种情况下,除非您明确说明,否则不会更改 self.active_flag的值。

      描述此行为的一种简单方法是“它不想让您失望”并返回nil - 所以它会尽力找到它所能做到的。

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

      希望这有帮助!

答案 2 :(得分:1)

确保您使用setter方法而不是确定新变量的范围。这是一个Ruby和AR使用细节,经常让人们吵架(另一个是(错误地)使用实例变量)。

请注意,虽然我理解抽象的愿望,但已经有update_attributes!

还有toggle!,它可能更好,取决于您与旗帜的接口。

答案 3 :(得分:0)

When use active_flag = val ruby thought your are define a local variable, the best way is self.active_flag = val, if you got it, hope you know that send(:active_flag=, val) will works too.