rails 3:我需要在before_save回调中返回true才能使object.save工作吗?

Kri*_*rma 21 ruby activerecord callback ruby-on-rails-3

Class User  
  before_save :set_searchable

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

>> u = User.last  
>> u.save  
false  
Run Code Online (Sandbox Code Playgroud)

u.save总是返回false.如果我删除before_save它也有效,如果我在before_save中返回true它是有效的

所以我需要在before_save中给出return语句吗?如果before_save返回false,ActiveRecord会保存一个对象吗?

我在哪里可以看到有关回调及其工作流程的完整文档.

提前致谢

noo*_*odl 32

来自:http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html

如果before_*回调返回false,则取消所有后续回调和相关操作.如果after_*回调返回false,则取消所有后续回调.回调通常按照定义的顺序运行,但回调定义为模型上的方法(最后调用).

所以,是的.

  • **重要**:请注意,在 Rails 5 中返回 `false` 不再起作用,请参阅下面 @mahemoff 的答案。 (3认同)
  • 在我的回答链接中. (2认同)
  • 在这里:http://guides.rubyonrails.org/active_record_validations_callbacks.html (2认同)

mah*_*off 20

不,您不需要从Rails回调中返回true.您可以根本不返回任何内容,或者返回true,或3.141592,它仍然会被保存.唯一重要的是如果你返回false,这只适用于Rails 5之前.返回false将取消Rails之前的保存5.返回true从未产生任何影响.

对于Rails 5+,阻止更新的新方法是抛出异常:throw(:abort)..这更直观,更不容易出错.除非您配置遗留行为,否则返回值对它是否将保存没有影响.

这是有效的 - 并且非常好的干练习 - 只是继续你的业务,而不是回报任何东西; 如果使用早期的Rails,请确保避免意外地返回false.例如:

# 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
Run Code Online (Sandbox Code Playgroud)

这里的问题是你可能会忘记一些"程序"类型函数会将布尔值作为一种状态代码返回,或者仅仅因为实现恰好以布尔值作为副作用而结束.你可能会认为你正在改变字符串或其他东西,但最终会不小心否决回调.因此,虽然我认为从回调中显式返回通常太嘈杂,但您需要注意隐式返回.人们主张回归真实的一个原因是要防范这种问题.