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


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

у меня есть 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 63

4 ответа:

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

этот код

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

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

self.active_flag = val

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

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

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

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

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

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

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


вот почему:

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

  1. он изначально спрашивает " делает в рамках whats_my_active_flag?
  2. он ищет и понимает, что ответ "нет", так он прыгает до на один уровень, к экземпляру Данных
  3. он снова спрашивает то же самое: "не active_flag существуют в этой области?
  4. ответ "да", и поэтому он говорит:" У меня есть что-то для вас", и он возвращает это!

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

  1. он спрашивает "Есть ли в рамках whats_my_active_flag?
  2. ответ "да", поэтому он возвращает, что значение

в любом случае, это не изменить значение self.active_flag Если вы явно не скажете ей об этом.

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

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

надеюсь, что это помогает!

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

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

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

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