Search code examples
ruby-on-railsruby-on-rails-3controllers

Proper Usage of Rails After_Filter


In a small app I am building, I have a controller that creates an exchange. When a user creates an exchange they are simultaneously the organizer of the exchange and a participant in the exchange. Participants are tracked by a join table that joins a user_id and an exchange_id. Organizers are tracked by a foreign user_id key in the exchange table.

I am trying to figure out where to put the code that will automatically create a new membership record for the organizer of the exchange. Should I put this in the exchange_controller's create action itself, or in an after_filter triggered by the create action? Or maybe somewhere else? Part of the problem is that I could not find any good examples of proper after_filter use (guides.rubyonrails.org only had sparse mention of it), so any links pointing in the correct direction would be appreciated as well.

Here is relevant model code:

app/models/user.rb:
  # Returns array of exchanges user is participating in
  has_many :participations, 
           :through => :memberships,
           :source => :exchange

  # Returns array of exchanges user has organized
  has_many :organized_exchanges, 
           :foreign_key => :organizer_id, 
           :class_name => "Exchange"


app/models/membership.rb:
  class Membership < ActiveRecord::Base
    attr_accessible :exchange_id, :user_id, :role
    belongs_to :exchange
   belongs_to :user 
end


app/modles/exchange.rb:
  belongs_to :organizer, 
             :foreign_key => :organizer_id,
             :class_name => "User"

  has_many :memberships, :dependent => :destroy

  has_many :participants, 
           :through => :memberships, 
           :source => :user

And here is the relevant controller code:

app/controllers/exchanges_controller.rb:
  def create
    @exchange = Exchange.new(params[:exchange])
    @exchange.organizer_id = current_user.id
    if @exchange.save
      redirect_to exchange_path(@exchange.id)
    else
      render 'new'
    end
  end

Solution

  • after_filter is a completely different thing in this context. It is called when your view is completely processed and so you want to call some action to do something.

    You can use after_create callback that is triggered when a record is created in the database.

    In your case, a user is creating an exchange and so after the exchange is created, the after_create callback is triggered and you can apply your functionality over there to make the current user who created the exchange to be a participant.

    The way to write in a model is like this:

      after_create :do_something
    
      def do_something
        something.do!
      end
    

    Note: It is not good to use after_save here because it is triggered every time you save a record or even if you update a record.

    There is a nice SO post that clearly tells you the difference between the after_create and after_save.

    See this SO post for the difference between the two.

    More on the callbacks is here.