Когда использовать себя в модели?

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

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

Ответ 1

Когда вы выполняете действие над экземпляром, вызывающим метод, вы используете self.

С помощью этого кода

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

Вы определяете новую локальную переменную с областью действия, называемую active_flag, устанавливая ее в переданное значение, она не связана ни с чем, поэтому она быстро отбрасывается, когда метод заканчивается, как никогда не существовал.

self.active_flag = val

Однако он сообщает экземпляру изменить свой собственный атрибут active_flag, а не новую новую переменную. Вот почему он работает.

Ответ 2

Это происходит из-за неопределенности. Когда вы находитесь внутри метода, и вы пытаетесь установить новую переменную следующим образом:

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.

  • Сначала он запрашивает: "существует ли active_flag в рамках whats_my_active_flag?
  • Он ищет и реализует ответ "nope", поэтому он перескакивает вверх на один уровень, в экземпляр SomeData​​li >
  • Он повторяет одно и то же: "существует ли active_flag в этой области?
  • Ответ "yup", и поэтому он говорит "Я получил что-то для ya", и он возвращает это!

Однако, если вы определяете active_flag внутри whats_my_active_flag, а затем запрашиваете его, он снова повторяет шаги:

  • Он спрашивает: "существует ли active_flag в рамках whats_my_active_flag?
  • Ответ "yup", поэтому он возвращает это значение

В любом случае он не будет изменить значение self.active_flag, если вы явно не сообщите об этом.

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

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

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

Ответ 3

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

Заметьте, что уже update_attributes!, хотя я понимаю стремление к абстрактному.

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

Ответ 4

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