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.
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.
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.
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:
- Make generic methods and act on their output in the controller. (The standard way of doing things)
- Make methods in your model that will be used only in specific controller controller. (Not very DRY)
- Pass the action as an argument to the method.
- 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