【问题标题】:Disable autoincrementing id inside of ActiveRecord::Base.transaction在 ActiveRecord::Base.transaction 中禁用自动递增 id
【发布时间】:2015-09-11 17:23:35
【问题描述】:

我有一个 FormObject 用于注册,它在 create 方法中为他创建了一个用户和 很多 模型。

def create
  ActiveRecord::Base.transaction do
    @user = User.create(@params[:user])
    process_bonuses_for_user
    process_actions_for_user
    # et.c., giant amount of methods
  end

  @user.persisted? # to return the true of false to controller
end

我遇到了FormObject 的奇怪行为。即使它运行成功(创建很多模型)或不成功(不保存它们),User 模型的id 也是自动递增的。因此,每次尝试使用我的FormObject 保存某些内容时,都会为用户增加下一个id 的值。这是User创建成功的正常情况,但当用户在注册表单上出错时就不正常了。

如何禁用这种不可预测的行为?

附:我知道当我在create方法的开头写@user = User.new(@params[:user])和在结尾写@user.save时一切正常,但是有很多关联,我不想写很多autosaveinverse_of 在我的模型中。

附言我是postgresql-9.4用户

【问题讨论】:

    标签: ruby-on-rails ruby postgresql activerecord service-object


    【解决方案1】:

    您的交易无效,因为您使用的是create。您需要使用 bang 版本 (create!) 来引发触发回滚的失败异常。请注意,您需要自己 rescue InvalidRecord 例外。

    【讨论】:

    • 嗯...好像有点矫枉过正
    • 这是确保您的 transaction 正常工作的唯一方法。 :)
    【解决方案2】:

    在我看来,可能是这样的:

      def create
        @user = User.new(params[:user])
    
        respond_to do |format|
          if @user.save
             process_bonuses_for_user
             process_actions_for_user
             # et.c., giant amount of methods
             ...
             format.html { redirect_to ... }
          end
        end
    

    【讨论】:

    • 错了。如果用户有效,但process_actions_for_user 方法失败会怎样?
    • 所以,如果process_actions_for_userUser Model相关,则应放入验证区。如果它与其他模型有关,用户应该在它之前。是的?其他情况——你可以使用 before_action: 和 after_action: 过滤器...
    猜你喜欢
    • 1970-01-01
    • 2010-10-04
    • 2015-03-10
    • 1970-01-01
    • 2016-02-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-04
    相关资源
    最近更新 更多