Вопрос по ruby-on-rails-3, ruby-on-rails – Когда использовать себя в модели?

65

Вопрос: когда мне нужно использовать self в моих моделях в Rails?

у меня есть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 не изменяется, скорее оно молча терпит неудачу. Может кто-нибудь объяснить?

Я не могу найти дубликаты, но если кто-то найдет тот, который тоже подходит.

возможный дубликатWhen to use 'self' in Ruby sepp2k

Ваш Ответ

4   ответа
0

При использованииactive_flag = val ruby думал, что вы определяете локальную переменную, лучший способself.active_flag = val, если вы получили это, надеюсь, вы знаете, чтоsend(:active_flag=, val) будет работать тоже.

1

Это необходимо для того, чтобы убедиться, что вы используете метод установки, а не определяете область видимости новой переменной. Это деталь использования Ruby и AR, которая часто вводит людей в заблуждение (другое - неправильное использование переменной экземпляра).

Обратите внимание, что это ужеupdate_attributes! хотя я понимаю желание абстрагироваться.

Там такжепереключения!, что может быть даже лучше, в зависимости от вашего интерфейса с флагом.

Error: User Rate Limit Exceeded
Error: User Rate Limit ExceededARError: User Rate Limit Exceeded
49

Это происходит из-за ограниченности. Когда вы находитесь внутри метода и пытаетесьset новая переменная, как это:

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

Вы создаете совершенно новую переменную, которая живет внутри set_active_flag. Как только это выполнено, оно уходит, не изменяяself.active_flag (фактическая переменная экземпляра) любым способом.

HOWEVER (это было источником путаницы для меня): когда вы пытаетесьread переменная экземпляра в ruby, например так:

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

Вы действительно получитеself.active_flag (фактическая переменная экземпляра) возвращается.


Here's why:

Ruby сделает все возможное, чтобы избежать возвращенияnil.

  1. It initially asks "does active_flag exist within the scope of whats_my_active_flag?
  2. It searches and realizes the answer is "nope", so it jumps up one level, to the instance of SomeData
  3. It asks the same thing again: "does active_flag exist within this scope?
  4. The answer is "yup" and so it says "I got something for ya" and it returns that!

Однако, если вы определитеactive_flag в пределахwhats_my_active_flag, а затем попросите об этом, он снова проходит через шаги:

  1. It asks "does active_flag exist within the scope of whats_my_active_flag?
  2. The answer is "yup", so it returns that value

В любом случае он не будетchange значениеself.active_flag если вы явно не скажете это.

Простой способ описать это поведение - «он не хочет вас разочаровывать»; и вернутьсяnil - поэтому он делает все возможное, чтобы найти все, что может.

В то же время "он не хочет портить данные, которые вы не намеревались изменить". поэтому он не изменяет саму переменную экземпляра.

Надеюсь это поможет!

Error: User Rate Limit ExceededreadError: User Rate Limit ExceededwriteError: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
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 вместо совершенно новой переменной. Вот почему это работает.

Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded varatis
Error: User Rate Limit Exceeded@var_name.
Error: User Rate Limit ExceededselfError: User Rate Limit ExceededselfError: User Rate Limit Exceeded
Error: User Rate Limit Exceededfoo = barError: User Rate Limit Exceededmethod_missingError: User Rate Limit Exceededself.foo = barError: User Rate Limit Exceededfoo=Error: User Rate Limit Exceeded

Похожие вопросы