Ruby on rails Rails:将数据保存在两个表中

Ruby on rails Rails:将数据保存在两个表中,ruby-on-rails,ruby-on-rails-4,transactions,Ruby On Rails,Ruby On Rails 4,Transactions,我有一个用户表和一个设置表,具有1-1关系。我想为新创建的用户插入一些默认设置。我想在创建用户回调后使用。但是,我不确定这是否是事务性的。对于这种情况,最好的方法是什么?您可以在创建回调后使用,也可以同时使用这两种方法。两个都会好的。但您还应该为属性分配的初始化方法中的设置设置默认值。或者,您也可以在保存调用后使用用户的create方法执行相同的操作。但这不是一个好办法。因此,您可以选择call_back或observer。您可能会发现初始化后的回调对于为用户构建设置对象以及指定默认设置非常有用

我有一个
用户
表和一个
设置
表,具有1-1关系。我想为新创建的用户插入一些默认设置。我想在创建用户回调后使用
。但是,我不确定这是否是事务性的。对于这种情况,最好的方法是什么?

您可以在创建回调后使用
,也可以同时使用这两种方法。两个都会好的。但您还应该为属性分配的初始化方法中的设置设置默认值。或者,您也可以在保存调用后使用用户的create方法执行相同的操作。但这不是一个好办法。因此,您可以选择call_back或observer。

您可能会发现初始化后的
回调对于为
用户
构建
设置
对象以及指定默认
设置
非常有用。例如:

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
class用户
有了它,您将拥有完整的家长
用户
,包括孩子
设置
。调用
user.save
时,
user
setting
都被保存,并且都发生在事务内部。

--更新--

当您开始为模型注册新回调时,它们将排队等待执行。此队列将包括所有模型的验证、注册的回调以及要执行的数据库操作

整个回调链包装在一个事务中。如果any before回调方法返回false或引发异常,则执行链将停止并发出回滚;after回调只能通过引发异常来完成

在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
对于放置默认值的位置,如果设置默认值取决于用户,请将其粘贴到setup_user方法中。如果设置默认值与用户无关,请将它们粘贴到设置的“保存前”或“验证前”方法中。对于用户,您需要使用after_create方法来处理用户未验证的情况,您希望只有在成功创建用户时才会触发这些回调。您不希望在\u验证后使用该用户,因为该用户不会被创建,并且如果该设置包含尚未创建的用户的外来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
class用户

要将它放在同一事务中,您需要在提交后和回滚后使用。使用。保存!将在\u回滚后引发异常和触发器。如果没有该设置,您将不会有用户。

但这将在单个事务中进行吗?我在这里查找它,因为我们正在讨论,这里显示您需要使用after_commit回调,而不是after_create。这确保了他们将在同一个事务中。这应该是有效的,这是他们在指南中所说的。这是您的提交和回滚。查看这里的事务部分,为什么要将用户和设置放在同一个事务中?至少你已经清醒过来,避免了严格的事务方法。在这个实现中,您需要注意不要每次实例化时都这样做,但是每次都会设置init_user_设置。首先检查模型是否为新模型,但此时您基本上是在创建后实现的。并且用户不应属于某个设置。@CleoR,谢谢您的评论。我不确定我是否完全理解了第一句话,请你在“至少你有了自己的感觉,避免了严格的交易方式”之后再补充一句。您是对的,
在初始化后被调用,不仅是在创建对象时,而且是用户的实现。另外,感谢您指出答案中的
属于
问题。根据您的建议,我已将其更改为“has\u one”
!对不起,这是为这次行动准备的!我想我对我们的谈话有点生气。他完全无视我说的话,但我想他改变了主意。抱歉搞混了。@CleoR,别担心。我只是想更多地了解“避免严格的事务性方法”。不要难过,保持冷静,伙计!:)@还是你生气了,所以你否决了这个问题?好极了!!顺便说一句,我是决定选择适合我问题的答案的人。除非答案是正确的,否则无论如何你都不能强迫接受答案。即使你的答案是正确的,但仅仅为了答案,似乎还有很多工作要做。
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