Ruby-on-rails 什么时候在模型中使用 self ?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10805136/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 03:28:02  来源:igfitidea点击:

When to use self in Model?

ruby-on-railsruby-on-rails-3ruby-on-rails-3.1self

提问by varatis

Question: when do I need to use self in my models in Rails?

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

I have a setmethod in one of my models.

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

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

When I do this, everything works fine. However, when I do this:

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

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

The active_flag value doesn't change, rather it fails silently. Can someone explain?

active_flag 值不会改变,而是静默失败。有人可以解释一下吗?

I can't find any duplicates, but if someone finds one that's fine too.

我找不到任何重复项,但如果有人找到也没关系。

采纳答案by DVG

When you're doing an action on the instance that's calling the method, you use self.

当您对调用该方法的实例执行操作时,您可以使用 self.

With this code

有了这个代码

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

You are defining a brand new scoped local variable called active_flag, setting it to the passed in value, it's not associated with anything, so it's promptly thrown away when the method ends like it never existed.

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

self.active_flag = val

However tells the instance to modify its own attribute called active_flag, instead of a brand new variable. That's why it works.

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

回答by Yuval Karmi

This happens because of scoping. When you're inside of a method and you try to seta new variable like this:

这是因为范围界定。当你在一个方法中并尝试设置一个新变量时:

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

You are creating a brand new variable that lives inside of set_active_flag. As soon as that's done executing, it goes away, not altering self.active_flag(the actual instance variable) in any way.

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

HOWEVER(this was a source of confusion for me): when you try to readan instance variable in ruby, like this:

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

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

You'll actually get self.active_flag(the actual instance variable) returned.

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



Here's why:

原因如下:

Ruby will do what it can to avoid returning nil.

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

  1. It initially asks "does active_flagexist within the scope of whats_my_active_flag?
  2. It searches and realizes the answer is "nope", so it jumps upone level, to the instance of SomeData
  3. It asks the same thing again: "does active_flagexist within this scope?
  4. The answer is "yup" and so it says "I got something for ya" and it returns that!
  1. 它最初询问“是否active_flag存在于范围内whats_my_active_flag
  2. 它搜索并实现了答案是“不”,所以它跳一级,至SomeData实例
  3. 它再次问同样的问题:“active_flag在这个范围内是否存在?
  4. 答案是“是的”,所以它说“我有东西给你”,然后它返回!

However, if you define active_flagwithin the whats_my_active_flag, and then ask for it, it goes through the steps again:

但是,如果你定义active_flagwhats_my_active_flag,然后问它,它经历的步骤再次:

  1. It asks "does active_flagexist within the scope of whats_my_active_flag?
  2. The answer is "yup", so it returns that value
  1. 它询问“是否active_flag存在于范围内whats_my_active_flag
  2. 答案是“是的”,因此它返回该值

In either case, it won't changethe value of self.active_flagunless you explicitly tell it to.

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

An easy way to describe this behavior is "it doesn't want to disappoint you" and return nil-- so it does its best to find whatever it can.

描述这种行为的一个简单方法是“它不想让你失望”然后返回nil——所以它会尽最大努力找到它所能找到的。

At the same time, "it doesn't want to mess up data that you didn't intend to change" so it doesn't alter the instance variable itself.

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

Hope this helps!

希望这可以帮助!

回答by Dave Newton

It's to make sure you're using the setter method and not scoping a new variable. It's a Ruby and AR usage detail that often trips people up (the other being the (mis-)use of an instance variable).

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

Note there's already update_attributes!although I understand the desire to abstract.

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

There's also toggle!, which might be even nicer, depending on your interface to the flag.

还有切换!,这可能会更好,具体取决于您的标志界面。

回答by fangxing

When use active_flag = valruby 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.

当使用active_flag = valruby 时认为你定义了一个局部变量,最好的方法是self.active_flag = val,如果你得到了它,希望你知道它send(:active_flag=, val)也能起作用。