我有一个user
表和一个{1-1}关系的setting
表。我想为新创建的用户插入一些默认设置。我想用after_create
回调用户。但是,我不确定这是否是交易性的。这种情况的最佳方法是什么?
答案 0 :(得分:2)
您可能会发现after_initialize
回调对于为setting
构建user
对象并分配默认setting
非常有用。例如:
class User < ActiveRecord::Base
has_one :setting
after_initialize :init_user_setting
private
def init_user_setting
# Assign default setting or build
self.setting = ...
end
end
通过此操作,您将拥有包含子user
的完整父级setting
。当您致电user.save
时,user
和setting
都会被保存,并且都会在交易中发生。
答案 1 :(得分:0)
您可以使用after_create
回调或观察者。两者都没问题。但是,您还应该在属性分配的initialize方法中为设置设置默认值。或者您也可以使用用户的create方法在保存调用后执行相同操作。但这不是一个好方法。所以更喜欢call_back或者观察者。
答案 2 :(得分:0)
- UPDATE -
当您开始为模型注册新的回调时,它们将排队等待执行。此队列将包括所有模型的验证,已注册的回调以及要执行的数据库操作。
整个回调链包含在一个事务中。如果在回调方法之前返回任何错误或引发异常,则执行链将停止并发出ROLLBACK;回调之后只能通过引发异常来实现。
在before_save回调结束时将属性设置为false后,我无法终身找出为什么对象永远不会保存!在回调之前必须返回truthy值或它将回滚。
- 上一页 -
你需要做这样的事情。这是我处理货币的默认方法。
class User < ActiveRecord::Base
has_one :setting
after_create :setup_user
private
def setup_user
user_settings = self.setting.new
user_settings.attr1 = foo1
user_settings.attr2 = foo2
user_settings.save
end
end
class Setting < ActiveRecord::Base
belongs_to :user
end
理想情况下,您可以对用户进行验证并使其成为如果用户有效,则设置也有效。但如果你不这样做,你需要使用
if !user_settings.save
self.destroy
end
对于放置默认值的位置,如果设置默认值取决于用户,请将它们粘贴在setup_user方法中。如果设置默认值并不关心用户,请将它们粘贴在设置的before_save或before_validation方法中。对于用户,您需要对用户未验证的情况使用after_create方法,您希望仅在成功创建用户时才触发这些回调。您不希望用户使用after_validation,因为用户不会被创建,并且如果该设置包含尚未创建的用户的外部ID,则数据库将立即变得不一致。
基于交易的方法
class User < ActiveRecord::Base
has_one :setting
after_commit :setup_user, on: [:create]
after_rollback :undo_user, on: [:create]
private
def setup_user
user_settings = self.setting.new
user_settings.attr1 = foo1
user_settings.attr2 = foo2
user_settings.save!
end
def undo_user
#The users settings didn't save so roll back the user
self.destroy
end
end
class Setting < ActiveRecord::Base
belongs_to :user
end
要将它放在同一个事务中,您需要使用after_commit和after_rollback。使用.save!将抛出异常并触发after_rollback。没有设置,您将没有用户。