In appllication controller i have couple of methods that works with requested controller and action name.
To follow DRY principe, i want to define share variables with those params.
class ApplicationController < ActionController::Base
##requested_action = params[:action]
##requested_controller = params[:controller]
end
But i get error: undefined local variable or method "params" for ApplicationController:Class
Why i can't do this and how can i achieve my goal?
I believe you already have controller_name and action_name variables defined by Rails for this purpose.
If you want to do it by your way, you must define it as a before filter as params comes to existence only after the request is made. You can do something like this
class ApplicationController < ActionController::Base
before_filter :set_action_and_controller
def set_action_and_controller
#controller_name = params[:controller]
#action_name = params[:action]
end
end
You can access them as #controller_name and #action_name. But controller_name and action_name are already defined in Rails. You can use them directly.
Use instance methods instead:
class ApplicationController < ActionController::Base
def requested_action
params[:action] if params
end
end
You can use before_filter option.
class ApplicationController < ActionController::Base
before_filter :set_share_variable
protected
def set_share_variable
#requested_action = params[:action]
#requested_controller = params[:controller]
end
end
Related
I have a base URL common to all my controllers. I want to declare this as a variable in one place, and use it in all my controllers. That will make any future updates fast and simple. Is that possible? I'm declaring it in all my controllers like this:
#baseURL = "www.url.com/something/"
In your application controller.
before_action :set_variables
def set_variables
#baseURL = "www.url.com/something/"
end
This #baseURL instance variable will be accessible in all your actions and views as you make all controllers inherit the ApplicationController.
Typically, all your controllers will inherit from ApplicationController. You may then define the variable there, making it available to its descendants.
class ApplicationController < ActionController::Base
BASE_URL = "www.url.com/something/"
end
You could define a method inside ApplicationController and use that method like a helper_method to access it from the views.
class ApplicationController < ActionController::Base
helper_method :base_url
def base_url
#base_url ||= "www.url.com/something/"
end
end
I try to avoid before_actions to setup variables.
Inside your controllers and views you will able to call the base_url method.
It's the same to include this method in the application_helper.rb.
Rails controllers inherit from ApplicationController. Try putting it there:
def baseUrl
#baseURL = "www.url.com/something/"
end
You could define a class variable in your application controller:
class ApplicationController < ActionController::Base
##baseURL = "www.url.com/something/"
def self.baseURL
##baseURL
end
end
class SomeFrontendController < ApplicationController
end
Within all your controllers now you could access ##baseURL or call the class method:
SomeFrontendController.baseURL
# => "www.url.com/something/"
But this is dirty. Better use a constant:
class ApplicationController < ActionController::Base
BASE_URL = "www.url.com/something/"
end
class SomeFrontendController < ApplicationController
end
Within all your controllers now you could access BASE_URL or:
SomeFrontendController::BASE_URL
If it is only one variable and you are sure, that you need it only within controllers scope declaring a constant in ApplicationController should be enough:
class ApplicationController < ActionController::Base
BASE_URL = "www.url.com/something/"
end
class SomeOtherController < ApplicationController
def index
#base_url = BASE_URL
end
end
However usually custom URLs (and other things like email addresses) earlier or later are needed in other parts of an application so it is useful to have a single source of truth by using gem like https://github.com/settingslogic/settingslogic and store all such variables in one place (file).
In the class below, how do I get the current action name (i.e. email_confirmation, password_reset) in side the after_action callback add_mandril_headers?
class UserMailer < ActionMailer::Base
after_action :add_mandril_headers
def email_confirmation(user)
mail(..)
end
def password_reset(user)
mail(..)
end
private
# how to get the action name?
def add_mandrill_headers
headers['X-MC-Tags'] = [mailer_name, action_name].join('_');
end
end
Turns out action_name returns the current mailer action name. I tried it based on the fact that ActionController has a similar method.
Thanks #HarishShetty!
As you mentioned, the action_name is good for all Controllers, as it is inherited from ApplicationController.
For example, I was using public_activity and wanted some simplification in my controllers:
class SiteDetailsController < ApplicationController
after_action :track_activity, only: [:create, :update, :destroy]
# ...
private
def track_activity
#site_detail.create_activity action_name, owner: current_user
end
end
In my application_helper.rb file I have a function like this:
def find_subdomain
request.domain
end
undefined local variable or method `request'
And I am invoking this method in another helper. How can i get the domain in helper without passing any argument from controller.
I know this is old, but having stumbled across this myself recently I thought I'd chip in. You could add the method to your ApplicationController and specify it as a helper_method instead:
class ApplicationController < ActionController::Base
helper_method :find_subdomain
private
def find_subdomain
request.domain
end
end
As others have mentioned, the request object should be passed to your helper, which would let you pass it from the view (ERB) as follows,
<%= find_subdomain(request) %>
class ApplicationController < ActionController::Base
helper :all
end
In the application controller before filter.
class ApplicationController < ActionController::Base
before_filter :authenticate
def authenticate
# How do we know which controller and action was targetted?
end
end
class ApplicationController < ActionController::Base
before_filter :authenticate
def authenticate
# How do we know which controller and action was targetted?
params[:controller]
params[:action]
# OR
controller.controller_name
controller.action_name
end
end
In Rails 3.2 you no longer need to call controller.action_name explicitly instead just "action_name".
before_filter :check_if_locked
def check_if_locked
puts action_name
puts controller_name
end
You can get full url object using
url = Rails.application.routes.recognize_path(request.env['PATH_INFO'])
now you can get components as
url[:controller]
url[:action]
By default you can also use params[:controller] and params[:action] respectively during request/response life cycle.
request.parameters['controller']
request.parameters['action']
I have a method in my ApplicationController that is part of a before_filter. How do I identify which controller is calling that method and can I pass arguments to it?
Presumably worst case, I can create a new object where I use controller names and values, then call it directly in the before_filter method with NewObject.find(:first, :conditions => ['controller_name = ?', controller_name], but that smells very bad.
So I'm open to ideas. Thanks in advance.
psuedo-short-code:
class ApplicationController < ActionController::Base
before_filter :someMethod
....
def someMethod
Do stuff
end
class SomeController < ApplicationController
# presumably the before_filter runs here
#someValueIWantToPass = some.value
...
params[:controller] and params[:action] contain the controller and action requested, and are available from inside a filter.
Using self.class will tell you which controller has called the before_filter.
class HomeController < ApplicationController
before_filter :awesome
def index
render :text => #blah
end
def awesome
#blah = self.class
end
end
will render out "HomeController"