views:

79

answers:

3

I found some information to get action_name within the controller, but I need to know what it is inside my model. I'm kind of second guessing myself and wondering if that's at all something you would need or could get from being within the model, but I'm not sure. Please let me know if there's a way to get something like action_name within my model.

+2  A: 

In the strict sense, your model should not have any visiblity about the controllers thats accessing it, i.e. it's bad practice.

In any case if you still want to access it you can pass the object 'controller' from the controllers to your model method name. It contains all the information you need.

controller.action_name

would give you the action name as well.

Rishav Rastogi
I agree, it is really bad practice.
ohdeargod
A: 

I don't know exactly what you're trying to do but I've had instances where I felt like I needed to reach into the controller from the model. Bad practice of course.

On the other hand there are times where the controller has data (such as the current user) that a model might need - say to send an email that an item has been edited. In this case you might want to email the creator of the item - but only if it's not the current user. No need to email myself if I'm the one editing, right?

The solution that I've used is to use a sweeper which does have access to the controller.

class BugSweeper < ActionController::Caching::Sweeper
    observe Bug

    def after_create(record)
     email_created(record)
    end

    def before_update(record)
     email_edited(record)
    end

    def email_created(record, user = controller.session[:user_id])
     editor = find_user(user)
     if record.is_assigned? 
      TaskMailer.deliver_assigned(record, editor) unless record.editor_is_assignee?(editor)
     end
    end
end

YMMV.

A: 

As others have pointed out this is very bad practice. You should never need to know what action your model is being used in. Code that depends on the action is usually very fragile. It also blurs the lines between Model View and Controller, by placing code in your models that belongs in your controllers.

However, if you're dead set on making it happen, here are a few more options for using the controller action in a model:

  1. Make generic methods and act on their output in the controller. (The standard way of doing things)
  2. Make methods in your model that will be used only in specific controller controller. (Not very DRY)
  3. Pass the action as an argument to the method.
  4. Set the action using attr_accessible generated methods.

Regardless, here are examples for each of my solutions.

Generic methods example

class MyModel < ActiveRecord::Base
  ...
  def do_stuff
   # things.
  end

  def suitable_for_use_in_action?
   # returns true if the model meets criteria for action 
  end
end

class MyModelsController < ApplicationController

  ...

  def index
    @myModel = MyModel.find(params[:id])
    @myModel.do_stuff if @myModel.suitable_for_use_in_action?
   end
end

Specific action example

class MyModel < ActiveRecord::Base
  ...
  def do_stuff_in_index 
   # things that should only be called if the action is index.
  end
end

class MyModelsController < ApplicationController

  ...

  def index
    @myModel = MyModel.find(params[:id])
    @myModel.do_stuff_in_index
  end
end

Passing the action as an argument example.

class MyModel < ActiveRecord::Base
  ...
  def do_stuff(action)
    if action == :index
      # things that should only be called if the action is index.
    else
      #things to be done when called from all other actions
    end
  end
end

class MyModelsController < ApplicationController

  ...

  def index
    @myModel = MyModel.find(params[:id])
    @myModel.do_stuff(:index)
  end
end

Setting the action with attr_accessible example

class MyModel < ActiveRecord::Base
  ...
  attr_accessible :action

  def do_stuff
    if @action == :index
      # things that should only be called if the action is index.
    else
      #things to be done when called from all other actions, or when called while @action is not set.
    end
  end
end

class MyModelsController < ApplicationController

  ...

  def index
    @myModel = MyModel.find(params[:id])
    @myModel.action = :index
    @myModel.do_stuff
  end
end
EmFi