我有以下两种模式:
# 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'