我在rails应用程序中进行了以下设置:
class Song < ActiveRecord::Base
after_commit :update_singable_index
belongs_to :singable, polymorphic: true
def update_singable_index
singable.update_index if singable.respond_to? :update_index
end
end
我已经大量编辑了实际班级。如果需要更多信息,请告诉我。
但基本上Song模型与一堆模型有多态关联。他们中的一些人有弹性研究指数,其中一些人没有。因此,其中一些人会接受update_index
消息,而其他人会抛出NoMethodError: undefined method 'update_index'
唱歌工厂看起来像这样:
FactoryGirl.define do
factory :song do
album { create(:album) }
end
trait :for_updatable do
updatable_type 'Updatable'
association :singable, factory: :updatable
end
trait :for_unupdatable do
updatable_type 'Unupdatable'
association :singable, factory: :unupdatable
end
end
然后在测试中我有以下设置:
RSpec.describe Song, type: :model do
describe '.update_index_of_updatable' do
it 'updates Updatable\'s index' do
song = create(:song, :for_updatable)
updatable = song.singable
expect(updatable).to receive(:update_index)
song.save
end
it 'doesn\'t attempt to update an Unupdatable\'s index' do
song = create(:song, :for_unupdatable)
unupdatable = song.singable
expect(unupdatable).not_to receive(:update_index)
song.save
end
end
end
第一次测试确实通过了。另一方面,第二次测试失败
1) Song.update_singable_index doesn't attempt to update an Unupdatable's index
Failure/Error: update.save
(#<Unupdatable:0x0000000b39be98>).update_index(no args)
expected: 0 times with any arguments
received: 1 time
# ./app/models/song.rb:103:in `update_index_of_updatable'
# /usr/local/rvm/gems/ruby-2.2.3/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:430:in `block in make_lambda'
# /usr/local/rvm/gems/ruby-2.2.3/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:261:in `call'
# /usr/local/rvm/gems/ruby-2.2.3/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:261:in `block in simple'
# /usr/local/rvm/gems/ruby-2.2.3/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:504:in `call'
# /usr/local/rvm/gems/ruby-2.2.3/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:504:in `block in call'
# /usr/local/rvm/gems/ruby-2.2.3/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:504:in `each'
# /usr/local/rvm/gems/ruby-2.2.3/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:504:in `call'
# /usr/local/rvm/gems/ruby-2.2.3/gems/activesupport-4.2.3/lib/active_support/callbacks.rb:88:in `run_callbacks'
# /usr/local/rvm/gems/ruby-2.2.3/gems/bugsnag-2.8.12/lib/bugsnag/rails/active_record_rescue.rb:8:in `run_callbacks'
# /usr/local/rvm/gems/ruby-2.2.3/gems/activerecord-4.2.3/lib/active_record/transactions.rb:314:in `committed!'
# /usr/local/rvm/gems/ruby-2.2.3/gems/activerecord-4.2.3/lib/active_record/connection_adapters/abstract/transaction.rb:89:in `commit_records'
# /usr/local/rvm/gems/ruby-2.2.3/gems/test_after_commit-0.4.1/lib/test_after_commit.rb:47:in `test_commit_records'
# /usr/local/rvm/gems/ruby-2.2.3/gems/test_after_commit-0.4.1/lib/test_after_commit.rb:23:in `block in transaction_with_transactional_fixtures'
# /usr/local/rvm/gems/ruby-2.2.3/gems/activerecord-4.2.3/lib/active_record/connection_adapters/abstract/database_statements.rb:213:in `block in transaction'
# /usr/local/rvm/gems/ruby-2.2.3/gems/activerecord-4.2.3/lib/active_record/connection_adapters/abstract/transaction.rb:184:in `within_new_transaction'
# /usr/local/rvm/gems/ruby-2.2.3/gems/activerecord-4.2.3/lib/active_record/connection_adapters/abstract/database_statements.rb:213:in `transaction'
# /usr/local/rvm/gems/ruby-2.2.3/gems/test_after_commit-0.4.1/lib/test_after_commit.rb:9:in `transaction_with_transactional_fixtures'
# /usr/local/rvm/gems/ruby-2.2.3/gems/activerecord-4.2.3/lib/active_record/transactions.rb:220:in `transaction'
# /usr/local/rvm/gems/ruby-2.2.3/gems/activerecord-4.2.3/lib/active_record/transactions.rb:348:in `with_transaction_returning_status'
# /usr/local/rvm/gems/ruby-2.2.3/gems/activerecord-4.2.3/lib/active_record/transactions.rb:286:in `block in save'
# /usr/local/rvm/gems/ruby-2.2.3/gems/activerecord-4.2.3/lib/active_record/transactions.rb:301:in `rollback_active_record_state!'
# /usr/local/rvm/gems/ruby-2.2.3/gems/activerecord-4.2.3/lib/active_record/transactions.rb:285:in `save'
# ./spec/models/song_spec.rb:141:in `block (3 levels) in <top (required)>'
# ./spec/rails_helper.rb:417:in `block (2 levels) in <top (required)>'
# ./spec/rails_helper.rb:192:in `block (2 levels) in <top (required)>'
# /usr/local/rvm/gems/ruby-2.2.3/gems/rspec-retry-0.4.2/lib/rspec/retry.rb:52:in `block (3 levels) in apply'
# /usr/local/rvm/gems/ruby-2.2.3/gems/rspec-retry-0.4.2/lib/rspec/retry.rb:43:in `times'
# /usr/local/rvm/gems/ruby-2.2.3/gems/rspec-retry-0.4.2/lib/rspec/retry.rb:43:in `block (2 levels) in apply'
答案 0 :(得分:0)
你没有显示你的:for_unupdatable
特征,但它必须是这里有缺陷的部分(意思是,一首歌的singable
,这个特性仍然会响应update_index
)
所以,你应该解决这个问题。
或者,为不支持ES的模型提供该方法的虚拟实现。
class ElasticSearchSingable
# your regular update_index
end
class SimpleSingable
def update_index
# do nothing here,
# purpose of this empty method is conformance to common API
end
end