Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does an around_action callback work? An explanation is needed

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.

like image 944
Dan Rubio Avatar asked Jan 13 '15 21:01

Dan Rubio


People also ask

What is controller callback in Rails?

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.

What does Before_action do in Rails?

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.

How should you use filters in controllers?

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.

What is the role of Rails controller?

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.


2 Answers

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
like image 78
Damon Yuan Avatar answered Oct 23 '22 00:10

Damon Yuan


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.

like image 43
Alejandro Babio Avatar answered Oct 22 '22 23:10

Alejandro Babio