рельсы 3: нужно ли возвращать true в обратном вызове before_save для object.save для работы? - PullRequest
21 голосов
/ 19 января 2011
Class User  
  before_save :set_searchable

  def set_searchable  
    self.searchable = true if self.status == :active  
  end  
end  

>> u = User.last  
>> u.save  
false  

u.save всегда возвращает false.Если я удаляю before_save, он работает также, если я возвращаю true в before_save, он работает

, так что мне нужно давать операторы return в before_save?Будет ли ActiveRecord сохранять объект, если before_save возвращает false?

Где я могу увидеть полную документацию относительно обратных вызовов и рабочего процесса.

Заранее спасибо

Ответы [ 4 ]

32 голосов
/ 19 января 2011

От: http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html

Если обратный вызов before_ * возвращает false, все последующие обратные вызовы и связанное с ними действие отменяются. Если обратный вызов after_ * возвращает false, все последующие обратные вызовы отменяются. Обратные вызовы обычно выполняются в порядке, в котором они определены, за исключением обратных вызовов, определенных как методы в модели, которые называются последними.

Итак, да.

20 голосов
/ 24 июня 2014

Нет, вам не нужно возвращать true из обратных вызовов Rails.Вы можете вообще ничего не вернуть, или true, или 3.141592, и он все равно будет сохранен.Единственное, что имеет значение, это если вы вернете false, и это применимо только до Rails 5. Возвращение false отменит сохранение до Rails 5. Возвращение true никогда не оказывало никакого эффекта.

Для Rails 5+, новый способ заблокировать обновление - вызвать исключение: throw(:abort). .Это более интуитивно понятно и менее подвержено ошибкам.Возвращаемое значение не влияет на то, будет ли оно сохранено, если вы не сконфигурируете устаревшее поведение.

Это допустимо - и, как мне кажется, хорошая СУХАЯ практика - просто продолжать свой бизнес и ничего не возвращать;просто убедитесь, что случайно не возвращаете false неявно, если используете более ранние Rails.Например:

# This is fine, record will be saved
def before_save
  self.foo = 'bar' # Implicitly returns 'bar'
end

# This is an accidental veto, record will not be saved
def before_save
  Rails.logger.info 'user requested save'
  self.fresh = false # Oops! Implicitly returns false
end

# One way to rectify the above example (another would be to re-order if it's possible)
def before_save
  Rails.logger.info 'user requested save'
  self.fresh = false
  return # Implicitly returns nil. Could also do `return true`
end

Гвоздика здесь в том, что вы можете забыть, что некоторые функции «процедурного» типа возвращают логическое значение в качестве кода состояния или просто потому, что реализация заканчивается логическим значением в качестве стороныэффект.Вы можете подумать, что мутируете строку или что-то в этом роде, но в итоге случайно наложите вето на обратный вызов.Поэтому, хотя я думаю, что обычно слишком шумно для явного возврата из обратных вызовов, вам нужно позаботиться о неявных возвратах.Одна из причин, по которой люди выступали за возвращение истины, заключалась в том, чтобы защититься от этой ошибки.

1 голос
/ 09 ноября 2017

Другой более понятный способ установки логических столбцов без return - использовать tap

  def set_searchable
    self.tap{|u| u.searchable = status.eql?(:active) }
  end
0 голосов
/ 07 октября 2013

В документации сказано

Если обратный вызов before_ * возвращает false, все последующие обратные вызовы и связанные действия отменены. Если обратный вызов after_ * возвращает false, все последующие обратные вызовы отменяются. Обратные вызовы обычно выполняются в порядок, в котором они определены, за исключением обратных вызовов, определенных как методы в модели, которые называются последними.

НО

вы можете проверить это из (я сам это проверил и проблема на 100% достоверна)

Плюс также есть ошибка, связанная с before_save, о которой вы могли бы знать, проверьте комментарий по здесь

enter image description here

Как сказано в комментарии, это иногда наблюдается.

Что бы вы ни делали, просто знайте, что есть некоторые проблемы с обратным вызовом rails. Это сэкономит ваше время, когда вы столкнетесь с одним из этих

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...