Когда использовать себя в модели?
Вопрос: когда мне нужно использовать 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", поэтому он перескакивает вверх на один уровень, в экземпляр SomeDatali >
- Он повторяет одно и то же: "существует ли
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)
тоже будет работать.