ActiveRecord :: ReadOnlyRecord父级是只读时引发的异常

时间:2014-05-01 22:00:21

标签: ruby-on-rails activerecord ruby-on-rails-4.1

我有以下两种模式:

# app/models/customer.rb
class Customer < ActiveRecord::Base
  has_paper_trail

  serialize :mail_opt_out, Set

  before_create :generate_token

  has_many :wallets
  has_many :tickets, through: :wallets

  ...

  # We have a special seeded customer with id -1 that we don't want changing
  def readonly?
    persisted? && id < 0
  end
end


# app/models/ticket.rb
class Ticket < ActiveRecord::Base
  include SparkCast

  has_paper_trail

  belongs_to :price
  belongs_to :basket
  belongs_to :occurrence

  has_one :event,       through: :occurrence
  has_one :wallet,      through: :basket
  has_one :basket_type, through: :basket      
  has_one :customer,    through: :basket

  delegate :id, to: :customer, allow_nil: true

  ...

  def admit
    ensure_can_admit

    self.state = 'admitted'
    self.save!
  end
  cast_on :admit, room: :admittance

  def as_cast
    {
      id: id,
      customer_id: customer_id
    }
  end
end

相关协会有点令人费解,但客户是 - &gt;钱包 - &gt;篮子 - &gt;票。

当我在属于我们客户的故障单的实例上调用admit时,ID为-1(这是只读的)我得到ActiveRecord::ReadOnlyRecord例外。

我对导致这种情况的原因感到困惑,因为票证和客户都没有任何before_update回调。如果我改变

 has_one :customer, through: :basket

 delegate :customer, to: :basket
然后一切都很好。似乎有些事情要么试图更新客户,要么至少检查它是否是只读。

我已经使用byebug完成了一些步骤,但是找不到任何有用的东西。

如果相关模型是只读的,可能会检查什么,以及如何解决这个问题?在这里使用委托是最好的选择吗?

编辑添加:

还包括我之前省略的SparkCast。从我的故障单模型中删除cast_on方法正在解决问题。

# app/models/concerns/spark_cast.rb
module SparkCast
  extend ActiveSupport::Concern

  module ClassMethods
    def cast_on(*args)
      # Options are the last argument.
      options = args.pop

      room   = options[:room]

      args.each do |operation|
        class_eval do
          begin
            alias_method "#{operation}_without_cast", operation

            define_method operation do |*args|
              cast_hash = as_cast

              ...

              send("#{operation}_without_cast", *args)
              cast(room, operation, cast_hash)
            end
          rescue NameError => e
            raise "#{e.name} has not been defined yet. Include cast_on after method definition"
          end
        end
      end
    end
  end
end

回溯:

 - activerecord (4.1.0) lib/active_record/persistence.rb:481:in `create_or_update'
 - activerecord (4.1.0) lib/active_record/callbacks.rb:302:in `block in create_or_update'
 - activesupport (4.1.0) lib/active_support/callbacks.rb:113:in `call'
 - activesupport (4.1.0) lib/active_support/callbacks.rb:166:in `block in halting'
 - activesupport (4.1.0) lib/active_support/callbacks.rb:86:in `run_callbacks'
 - activerecord (4.1.0) lib/active_record/callbacks.rb:302:in `create_or_update'
 - activerecord (4.1.0) lib/active_record/persistence.rb:103:in `save'
 - activerecord (4.1.0) lib/active_record/validations.rb:51:in `save'
 - activerecord (4.1.0) lib/active_record/attribute_methods/dirty.rb:21:in `save'
 - activerecord (4.1.0) lib/active_record/transactions.rb:268:in `block (2 levels) in save'
 - activerecord (4.1.0) lib/active_record/transactions.rb:329:in `block in with_transaction_returning_status'
 - activerecord (4.1.0) lib/active_record/connection_adapters/abstract/database_statements.rb:209:in `transaction'
 - activerecord (4.1.0) lib/active_record/transactions.rb:208:in `transaction'
 - activerecord (4.1.0) lib/active_record/transactions.rb:326:in `with_transaction_returning_status'
 - activerecord (4.1.0) lib/active_record/transactions.rb:268:in `block in save'
 - activerecord (4.1.0) lib/active_record/transactions.rb:283:in `rollback_active_record_state!'
 - activerecord (4.1.0) lib/active_record/transactions.rb:267:in `save'
 - activerecord (4.1.0) lib/active_record/autosave_association.rb:393:in `save_has_one_association'
 - activerecord (4.1.0) lib/active_record/autosave_association.rb:188:in `block in add_autosave_association_callbacks'
 - activesupport (4.1.0) lib/active_support/callbacks.rb:424:in `block in make_lambda'
 - activesupport (4.1.0) lib/active_support/callbacks.rb:221:in `block in halting_and_conditional'
 - activesupport (4.1.0) lib/active_support/callbacks.rb:86:in `run_callbacks'
 - activerecord (4.1.0) lib/active_record/callbacks.rb:310:in `update_record'
 - activerecord (4.1.0) lib/active_record/timestamp.rb:70:in `update_record'
 - activerecord (4.1.0) lib/active_record/persistence.rb:482:in `create_or_update'
 - activerecord (4.1.0) lib/active_record/callbacks.rb:302:in `block in create_or_update'
 - activesupport (4.1.0) lib/active_support/callbacks.rb:113:in `call'
 - activesupport (4.1.0) lib/active_support/callbacks.rb:166:in `block in halting'
 - activesupport (4.1.0) lib/active_support/callbacks.rb:166:in `block in halting'
 - activesupport (4.1.0) lib/active_support/callbacks.rb:166:in `block in halting'
 - activesupport (4.1.0) lib/active_support/callbacks.rb:166:in `block in halting'
 - activesupport (4.1.0) lib/active_support/callbacks.rb:166:in `block in halting'
 - activesupport (4.1.0) lib/active_support/callbacks.rb:86:in `run_callbacks'
 - activerecord (4.1.0) lib/active_record/callbacks.rb:302:in `create_or_update'
 - activerecord (4.1.0) lib/active_record/persistence.rb:125:in `save!'
 - activerecord (4.1.0) lib/active_record/validations.rb:57:in `save!'
 - activerecord (4.1.0) lib/active_record/attribute_methods/dirty.rb:29:in `save!'
 - activerecord (4.1.0) lib/active_record/transactions.rb:273:in `block in save!'
 - activerecord (4.1.0) lib/active_record/transactions.rb:329:in `block in with_transaction_returning_status'
 - activerecord (4.1.0) lib/active_record/connection_adapters/abstract/database_statements.rb:211:in `block in transaction'
 - activerecord (4.1.0) lib/active_record/connection_adapters/abstract/database_statements.rb:219:in `within_new_transaction'
 - activerecord (4.1.0) lib/active_record/connection_adapters/abstract/database_statements.rb:211:in `transaction'
 - activerecord (4.1.0) lib/active_record/transactions.rb:208:in `transaction'
 - activerecord (4.1.0) lib/active_record/transactions.rb:326:in `with_transaction_returning_status'
 - activerecord (4.1.0) lib/active_record/transactions.rb:273:in `save!'
 -  () home/hayden/development/SparkSeat/api/app/models/ticket.rb:79:in `admit'

0 个答案:

没有答案