rails: how do i access a method in my application controller? - ruby-on-rails

Noob scoping issue, I imagine. :\
class ApplicationController < ActionController::Base
protect_from_forgery
#locations = get_locations
def get_locations
Location.where(:active => true).order('name').all
end
end
Error:
undefined local variable or method `get_locations' for ApplicationController:Class
Two questions:
1) What's with the error? Am I calling the method incorrectly?
2) How do I access this method from a sub-classed controller?

You're calling get_locations within the class scope, but the method is an instance method, not a class method. If for example you used def self.get_locations then you would be providing a class method, one of which you can use within the class scope (after you have defined it, not before like you're doing).
The problem here is the logic, what is this method for? What do you intend to use #locations for? If it's to go inside your application view, then you should put this method into the ApplicationHelper module, and call it from inside the relevant action. If you'd like it in another view on another controller and you'd like to use #locations inside your locations method, perhaps your setup might look something like this:
PagesController
class PagesController < ActionController::Base
def locations
#locations = Location.where(:active => true).order('name').all
end
end
locations.html.erb
<% #locations.each do |location| %>
<%= # do something with 'location' %>
<% end %>
If you'd like to use this inside of your application.html.erb you can simplify it quite some..
ApplicationController
class ApplicationController < ActionController::Base
protect_from_forgery
def locations
Location.where(:active => true).order('name').all
end
end
application.html.erb
<% locations.each do |location| %>
<%= # do something with location %>
<% end %>
The answer boils down to logic, and to really figure out exactly what you're looking for, more details would probably be required.

You're calling it from the class scope, not from an instance scope. more likely what you want is the following:
class ApplicationController < ActionController::Base
protect_from_forgery
before_filter :setup_locations
private
def setup_locations
#locations = Location.where(:active => true).order('name').all
end
end
To make your original example work, you'd need to make #get_locations defined on self (which points to the class at definition), like so:
class ApplicationController < ActionController::Base
protect_from_forgery
#locations = get_locations
def self.get_locations
Location.where(:active => true).order('name').all
end
end
The problem with that code is that #locations will only be available from the class level as a class instance variable, which is comparable to a static variable in most other languages, and which probably isn't what you want.

I imagine that this line:
#locations = get_locations
... is trying to access the class level method get_locations and not the instance method.
The clue here is that the error message is showing that it can't find it on the class itself (ApplicationController:Class) and not an instance of that class. That means that you're in the class scope, not instance scope.
This would fix it:
def self.get_locations
Location.where(:active => true).order('name').all
end

Even the question is quite old, you can also call your controller action anywhere just by calling:
ApplicationController.new.get_locations

Related

Choosing a controller for a layout class instance variable in Rails

I have a DateTime class instance variable #current_year = DateTime.now.year, which I have set into a footer partial. This partial is rendered across several of my clientside pages (and across multiple controllers as <%= render 'layouts/page_footer' %> in the main body of the page - the layout/application.html.erb page is reserved for the site navigation, so the format will not accommodate it there. While I could declare it for every page method it appears on in the controller, I'd find something a little more DRY. Is there a single place I can define my time variable to call in my layout component?
You could add a set_year action in your ApplicationController, something like:
class ApplicationController < ActionController::Base
private
def set_year
#current_year = DateTime.now.year
end
end
And then call it in a before_action in your relevant controller actions. Something like:
class FooController < ApplicationController
before_action :set_year, only: [:some_action, :another_action]
end
Alternatively and riffing off MrYoshiji's comment, you could create a current_year action in ApplicationController, something like:
class ApplicationController < ActionController::Base
def current_year
#current_year ||= DateTime.now.year
end
end
In which case, you could use current_year in your partial instead of #current_year. And then, as MrYoshiji says, you could move that into a helper if that sort of things floats your boat. Something like:
module ApplicationHelper
def current_year
#current_year ||= DateTime.now.year
end
end
The upside, I suppose, of moving current_year into a helper is that it de-clutters your ApplicationController. The downside, I further suppose, is that it obsfucates (to some degree), the source of the current_year action. Again, you'll have to take your boat floating coefficient into consideration.
BTW, #current_year isn't a DateTime. It's a Fixnum.
you could create a method in application_helper.rb file
and use it anywhere you like.
def current_year
#current_year = DateTime.now.year
end

Rails, def or constant to symbol

In my application_controller.rb I have this code:
def current_resource
if admin_signed_in?
:admin
elsif partner_signed_in?
:partner
end
end
Now I want to pass this def to child controllers like this:
authorize_resource current_resource
However it throws me an error. undefined local variable or methodcurrent_resource'`
How I can pass this current_resource to its child controllers as symbol.
That is how I call it inside controller:
class PageController < ApplicationController
authorize_resource current_resource
end
current_resource is inside application_controller
You're attempted to invoke an instance method on the class. You cannot do this.
If you want to invoke the method without an instance, you need to declare it on self:
def self.current_resource
if admin_signed_in?
:admin
elsif partner_signed_in?
:partner
end
end
This will still likely not work, unless each of the methods used inside that method are also declared as class-level methods.
This code:
class PageController < ApplicationController
authorize_resource current_resource
end
will be executed during PageController class loading, not during request handling. So you can't call admin_signed_in? and partner_signed_in? then. Also I don't know why are you trying to call authorize_resource with argument, because it doesn't get arguments, check cancancan source.
I think you have misunderstood how cancan filters and abilities work. You shouldn't pass User model to the filter. User type should be checked in Ability class and based on that, proper permissions should be selected. In your controller (btw. it should be PagesController) you only load resources and authorize them, ie.:
class PagesController < ApplicationController
load_resource
authorize_resource
# or just load_and_authorize_resource
end
You can customize how resources will be loaded and authorized. Please read this about authorizing controller actions and those examples. And also please read this about defining abilities.

Access request object in rails helper

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

Can we call a Controller's method from a view (as we call from helper ideally)?

In Rails MVC, can you call a controller's method from a view (as a method could be called call from a helper)? If yes, how?
Here is the answer:
class MyController < ApplicationController
def my_method
# Lots of stuff
end
helper_method :my_method
end
Then, in your view, you can reference it in ERB exactly how you expect with <% or <%=:
<% my_method %>
You possibly want to declare your method as a "helper_method", or alternatively move it to a helper.
What do helper and helper_method do?
make your action helper method using helper_method :your_action_name
class ApplicationController < ActionController::Base
def foo
# your foo logic
end
helper_method :foo
def bar
# your bar logic
end
helper_method :bar
end
Or you can also make all actions as your helper method using: helper :all
class ApplicationController < ActionController::Base
helper :all
def foo
# your foo logic
end
def bar
# your bar logic
end
end
In both cases, you can access foo and bar from all controllers.
Haven't ever tried this, but calling public methods is similar to:
#controller.public_method
and private methods:
#controller.send("private_method", args)
See more details here

Identifying the caller of a method in ApplicationController (RoR)

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"

Resources