首页 > 解决方案 > ActiveRecord 异常未在服务对象中引发

问题描述

在构建服务对象RecordInvalid时,应该不会抛出异常。相反,else块中的代码每次都会运行。

# services/new_registration_service.rb
class NewRegistrationService

  ...  

  def perform    
    begin
      account_create
    rescue ActiveRecord::RecordInvalid => exception
      OpenStruct.new(success?: false, user: user, account: account, error: exception.message)
    else
      # this is running every time
      OpenStruct.new(success?: true, user: user, account: account, error: nil)
    end
  end

  private

    ...

    def account_create
      # this is NOT saving, which I believe should
      # throw the exception in the perform method
      post_account_setup if account.save
    end

    ...

end

这是我从规范中运行的,account: name需要的地方:

post :create, params: { account: FactoryBot.attributes_for(:account, { name: nil }) }

即使当我puts返回account.name值时,它也是nil......这应该是引发RecordInvalid异常的原因。

# models/account.rb
class Account < ApplicationRecord
  resourcify
  has_many :users
  validates :name, presence: true
end

有任何想法吗?

标签: ruby-on-railsruby

解决方案


def account_create
  # Instead of this:
  post_account_setup if account.save

  # Do this:
  account.save!
  post_account_setup
end

调用save而不是save!不会引发异常;它会回来false的。

或者,有些人会争辩说,像这样使用异常来控制流是不好的做法。因此,您可以执行以下操作:

def perform
  # ...
  if account.valid?
    account.save! # This should never fail!
    post_account_create
    OpenStruct.new(success?: true, user: user, account: account, error: nil)
  else
    OpenStruct.new(success?: false, user: user, account: account, error: account.errors)
  end
end

或者,类似地:

def perform
  # ...
  if account.save
    post_account_create
    OpenStruct.new(success?: true, user: user, account: account, error: nil)
  else
    OpenStruct.new(success?: false, user: user, account: account, error: account.errors)
  end
end

推荐阅读