I am terribly confused about an around_action. How do they work? Can someone please provide me with an example/explanation of how they work?
This is a quote from my Agile Web Development 4 book:
Around callbacks wrap the execution of actions. You can write an around callback in two different styles. In the first, the callback is a single chunk of code. That code is called before the action is executed. If the callback code invokes yield, the action is executed. When the action completes, the callback code continues executing. Thus, the code before the yield is like a before action callback and the code after the yield is the after action callback. If the callback code never invokes yield. the action is not run-this is the same as having a before action callback return false.
I sort of get it when I read this. Here is an example from the Rails Guides
class ChangesController < ApplicationController
around_action :wrap_in_transaction, only: :show
private
def wrap_in_transaction
ActiveRecord::Base.transaction do
begin
yield
ensure
raise ActiveRecord::Rollback
end
end
end
end
So what is happening here? Does ActiveRecord::Base.transaction begin as the "before" part and raise ActiveRecord::Rollback as the "after" part? What is this method yielding to? Is it the show? Finally what would cause the yield method to fail causing the entire callback to fail? Would it be the rendering of the show action? I don't get it. Help please.
During the normal operation of a Rails application, objects may be created, updated, and destroyed. Active Record provides hooks (called callbacks) into this object life cycle so that you can control your application and its data. Callbacks allow you to trigger logic before or after an alteration of an object's state.
When writing controllers in Ruby on rails, using before_action (used to be called before_filter in earlier versions) is your bread-and-butter for structuring your business logic in a useful way. It's what you want to use to "prepare" the data necessary before the action executes.
Filters are inherited, so if you set a filter on ApplicationController , it will be run on every controller in your application. The method simply stores an error message in the flash and redirects to the login form if the user is not logged in. If a "before" filter renders or redirects, the action will not run.
The Rails controller is the logical center of your application. It coordinates the interaction between the user, the views, and the model. The controller is also a home to a number of important ancillary services. It is responsible for routing external requests to internal actions.
My understanding is as below:
begin
# Do before action...
logger.info 'I am the before action'
# Do the action, which is passed as a block to your "around filter"
# Note that if you were to delete this line, the action will never be called!
yield
# Do after action...
logger.info 'I am the after action'
ensure
raise ActiveRecord::Rollback
end
The key of the around_callback is yield
. In the case of the wrap_in_transaction
example: yield is replaced with the show
action. When show ends (rendering inclusive), wrap_in_transaction continues and performs the rollback.
At rails guides you can find:
For example, in a website where changes have an approval workflow an administrator could be able to preview them easily, just apply them within a transaction: ... Note that an around filter wraps also rendering. In particular, if in the example above the view itself reads from the database via a scope or whatever, it will do so within the transaction and thus present the data to preview."
That means the user at show
can see the information before the rollback (in this case show
must be doing a sort-of update which need a rollback because it is an information action).
You can think that an around_callback is a before callback and an after callback in only one method, using yield
to put the action in the middle.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With