#callback #ruby-on-rails-5 #activemodel
#обратный вызов #ruby-on-rails-5 #activemodel
Вопрос:
Учитывая модель, в которой вызывается обратный вызов throw(:abort)
, как можно определить, какой обратный вызов выполнил действие, не изменяя сами обратные вызовы?
Например, следующая модель…
class OddDuck < ApplicationRecord
before_save :random_abort_1
before_save :random_abort_2
private
def random_abort_1
if Random.rand(2) == 1
throw(:abort)
end
end
def random_abort_2
if Random.rand(2) == 1
throw(:abort)
end
end
end
… иногда не удается сохранить …
$ rails c
Running via Spring preloader in process 81303
Loading development environment (Rails 5.0.0.1)
irb(main):001:0> OddDuck.create!
(0.1ms) begin transaction
(0.1ms) rollback transaction
ActiveRecord::RecordNotSaved: Failed to save the record
from /Users/alice/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/activerecord-5.0.0.1/lib/active_record/persistence.rb:152:in `save!'
from /Users/alice/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/activerecord-5.0.0.1/lib/active_record/validations.rb:50:in `save!'
from /Users/alice/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/activerecord-5.0.0.1/lib/active_record/attribute_methods/dirty.rb:30:in `save!'
from /Users/alice/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/activerecord-5.0.0.1/lib/active_record/transactions.rb:324:in `block in save!'
from /Users/alice/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/activerecord-5.0.0.1/lib/active_record/transactions.rb:395:in `block in with_transaction_returning_status'
from /Users/alice/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/activerecord-5.0.0.1/lib/active_record/connection_adapters/abstract/database_statements.rb:232:in `block in transaction'
from /Users/alice/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/activerecord-5.0.0.1/lib/active_record/connection_adapters/abstract/transaction.rb:189:in `within_new_transaction'
from /Users/alice/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/activerecord-5.0.0.1/lib/active_record/connection_adapters/abstract/database_statements.rb:232:in `transaction'
from /Users/alice/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/activerecord-5.0.0.1/lib/active_record/transactions.rb:211:in `transaction'
from /Users/alice/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/activerecord-5.0.0.1/lib/active_record/transactions.rb:392:in `with_transaction_returning_status'
from /Users/alice/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/activerecord-5.0.0.1/lib/active_record/transactions.rb:324:in `save!'
from /Users/alice/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/activerecord-5.0.0.1/lib/active_record/suppressor.rb:45:in `save!'
from /Users/alice/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/activerecord-5.0.0.1/lib/active_record/persistence.rb:51:in `create!'
from (irb):1
from /Users/alice/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/railties-5.0.0.1/lib/rails/commands/console.rb:65:in `start'
from /Users/alice/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/railties-5.0.0.1/lib/rails/commands/console_helper.rb:9:in `start'
from /Users/alice/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/railties-5.0.0.1/lib/rails/commands/commands_tasks.rb:78:in `console'
from /Users/alice/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/railties-5.0.0.1/lib/rails/commands/commands_tasks.rb:49:in `run_command!'
from /Users/alice/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/railties-5.0.0.1/lib/rails/commands.rb:18:in `<top (required)>'
from /Users/alice/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/activesupport-5.0.0.1/lib/active_support/dependencies.rb:293:in `require'
from /Users/alice/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/activesupport-5.0.0.1/lib/active_support/dependencies.rb:293:in `block in require'
from /Users/alice/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/activesupport-5.0.0.1/lib/active_support/dependencies.rb:259:in `load_dependency'
from /Users/alice/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/activesupport-5.0.0.1/lib/active_support/dependencies.rb:293:in `require'
from /Users/alice/Desktop/site/bin/rails:9:in `<top (required)>'
from /Users/alice/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/activesupport-5.0.0.1/lib/active_support/dependencies.rb:287:in `load'
from /Users/alice/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/activesupport-5.0.0.1/lib/active_support/dependencies.rb:287:in `block in load'
from /Users/alice/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/activesupport-5.0.0.1/lib/active_support/dependencies.rb:259:in `load_dependency'
from /Users/alice/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/activesupport-5.0.0.1/lib/active_support/dependencies.rb:287:in `load'
from /Users/alice/.rbenv/versions/2.3.1/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in `require'
from /Users/alice/.rbenv/versions/2.3.1/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in `require'
from -e:1:in `<main>'
… но из обратной трассировки не совсем очевидно, какой обратный вызов вызвал прерывание.
Ответ №1:
throw также принимает необязательное возвращаемое значение, поэтому вы можете использовать его, если вам нужно знать обратный вызов, который вызвал throw
.
throw(tag [, obj])
Передает управление в конец активногоcatch
блока, ожидающегоtag
. ВозникаетUncaughtThrowError
, еслиcatch
дляtag
. Необязательный второй параметр предоставляет возвращаемое значение дляcatch
блока, которое в противном случае используется по умолчаниюnil
.
https://ruby-doc.org/core-2.4.1/Kernel.html#method-i-throw
Например:
def random_abort_1
if Random.rand(2) == 1
throw(:abort, __method__)
end
end
Вернется random_abort_1
.
Комментарии:
1. 1 за точный ответ на мой первоначальный вопрос. Увидев ваш ответ, я понял, что вопрос нуждается в уточнении. Я обновил вопрос.
2. @kkurian Я обновлю свой ответ, чтобы он сообщал вам, что
model_name#action_name
вызвало выброс. Это то, что вам нужно?3. Да, это было бы здорово.