It looks like you cannot use a helper in a controller even if both of them belong to the same class. For example: XYZHelper and XYZController...
I was under the impression that if the prefix is the same "XYZ" then the method in the helper can be used in the controller and in the view, but I think this is not the case.
So how do I remove some common functionality from a controller and place it in a helper. I want to place that piece of code in a helper because other controllers may be using it. What is the best way to approach this.
Thanks,
Jai.
There are a few ways you could share some code between controllers:
Application controller: If the code in question is an action/method which ought to be in a controller, but could be used by several controllers (or all of them), then this might be a place to put it.
the 'lib' directory. just a general purpose place to put code which should be shared.
Put it in the model. This may or may not be applicable, but its worth taking a good look at the code you're trying to move and thinking about whether it is something which makes sense on a model (instead of a controller or random class/module in lib).
Follow Pete's guidelines. If you still need to expose the methods then do the following:
Add the methods to ApplicationController class and register the methods as helper methods by calling helper_method.
class ApplicationController < ActionController::Base
helper_method :foo, :bar
private
def foo
"foo"
end
def bar
"bar"
end
end
Related
Actually, this is my problem. I have a rails app with a MainController, a HttpHelper and a ServiceHelper.
main_controller.rb
class MainController < ApplicationController
include ServiceHelper
def my_method
Service.make_stuff
end
end
service_helper.rb
module ServiceHelper
class Service
include HttpHelper
def self.make_stuff
http__foo
end
end
end
Service = ServiceHelper::Service
http_helper.rb
module HttpHelper
def http__foo
#stuff
params[:bar].nil?
end
end
If everything work well, this code should tell me if the :bar param exist, but I have a problem. Firstly, this code doesn't work, it tells me that http__foo is not defined, certainly because the include HttpHelper in Service doesn't work.
My second probleme is that if the include works, there will probably be a problem with the params variable. If I call this method (http__foo) in the controller, it will be fine, but I call this from a subclass, then I'm not sure it's be reliable.
make_stuff is a class method. http_foo is an instance method. Hence, when you call http__foo from your make_stuff, it is like calling Service.http_foo() which is not defined. What is defined is Service.new.http_foo().
I don't know what you want to do but in my humble opinion, by watching your code, it does not seem you are really familiar with Rails MVC concept and creating a MainController (why not use ApplicationController?), as well as the way you use your helpers is weird to me. It might be a good idea to restart from scratch.
oldergod is correct about the class vs. instance methods issue. Additionally, params is a method defined in ActionControllor, which is somewhere above the inheritance tree of all your controllers. The params method will NOT be available in the Service (which is where it ends up when you include HttpHelper in Service), unless you make it a subclass of ActionController or ApplicationController, which would be a little strange since it isn't a controller.
I am using Ruby on Rails 3 and I would like to include a controller (accounts_controller.rb) method explicitly in its related helper file (accounts_helper.rb) so that I can include that helper in another controller and use its methods. I need that because I can move out in helper the method code stated in accounts_controller.rb, but I need to use that method in others controllers.
Since this question is also related to this other question, I thinked to solve the latter this way:
(1) in accounts_controller.rb I state
def method_name
...
end
(2) in accounts_helper.rb I can include the method_name... how to do this?
(3) in posts_account.rb I can include accounts_helper.rb... how to do this?
Is it a good approach? If so, how can I code the steps 2 and 3?
If you want to use the method across controllers and views/helpers you can declare it as a helper_method
In your application_controller
helper_method :some_method
def some_method
// some common stuff
end
This will make the method available across controllers and views
One idea -- put the helper method in application_controller.rb then you can declare when to expose it to the view in a per controller basis - or globally in the application_controller.rb.
If you need to use the method in multiple controllers then I'd suggest it's reasonable to put it in application_controller.rb
I have a view helper file, app/helpers/analysis_helper.rb, whose toplevel methods I've been using in various view files. Works fine. I then defined an AnalysisSummary class inside analysis_helper.rb to package up some view-specific functionality.
However, when I try to instantiate an AnalysisSummary in a view file, I get the error:
uninitialized constant ActionView::CompiledTemplates::AnalysisSummary
Perhaps Rails is telling me that I shouldn't be defining a class inside a helper file? If so, where would you suggest parking AnalysisSummary? It's not a controller, it's not a model...
Thanks.
In Railscasts #213 (Revised) (subscribers only link, alas), Ryan Bates provides an example of how (and why) you might include a class within a helper. The basic gist is this:
# app/helpers/calendar_helper.rb
module CalendarHelper
def calendar(date = Date.today)
Calendar.new(self, date).render
end
class Calendar
def render
# Calendar, render thyself
end
# ... additional methods called by #render
end
end
To those opposed to classes within helpers, what do you make of Ryan's choice? Helpers are for generating markup, right? So if all the logic within class pertains to rendering (rather complicated) HTML, I would think that what it does (as opposed to what it is) makes it appropriate for inclusion in a helper.
Why does it need to be a class? Why not just a collection of methods? That's what a helper is: a collection of helpful methods. Business logic does not belong in helpers. You can place your code in a module within the helper file if you want to give some more structure and organization, though.
You can put classes in app/models without it having to be an ActiveRecord class, but you should seriously consider what the purpose of your class is before you place it there.
If it concerns only rendering the view, and not accessing data directly, it belongs in the view or a view helper.
You can call the class by explicitely mentioning the helper name
ApplicationHelper::AnalysisSummary.new
But I dont think it is a good idea to have classes in helpers.
It's a module then :) Definately do not define classes inside helpers. Jsut use a simple module to do the job.
I know there are ways to make helpers available to controllers, but that this is generally bad form. How should the following be re-worked to avoid this?
I have a Contacts helper called "fullname" that combines a contact's first and last names.
A layout partial called subheader is rendered in the application layout, and contains this code:
<section id="subheader"><%= #subheader %></section>
The controllers set the value of #subheader.
The issue is that I often want "fullname" in #subheader. But this means accessing the helper from the controller. Should this fullname method reside somewhere else?
With something like fullname I usually just define a method on the model itself.
If the fullname method did some type of HTML formatting then I would keep those parts inside a helper.
Since the title of your question might attract viewers looking for a different answer, I'm going to answer the question of "can I use rails helpers in my controllers"? There are legitimate uses for this, so here's the cleanest way to do so:
In the helpers file, wrap the code you want to access in a model like so:
module HelperModuleName
[helper code here]
end
Wrapping only the code you need to use in your controllers (as opposed to including all helpers using include ApplicationHelper) is a good idea because it reduces the possibility for method name clashes and forces you to be more deliberate about your choice to use helpers in controllers.
Now include the module in your application_controller.rb:
class ApplicationController < ActionController::Base
protect_from_forgery
include HelperModuleName
end
I want to share code not related to views between several controllers in my Rails app. Where in the directory structure should I place it?
EDIT: the code in question if something all controllers use to determine how they render the model data
If the code is something like modules with utility methods in these could be placed in the lib folder. Alternatively you could create a common superclass for some of your controllers if they share behaviour.
Please post an example of the kind of code you're thinking of.
If it's "something all controllers use", I would place it in a base class used by all controllers. The "application_controller" comes to mind.
I have been creating modules in lib to provide code to other classes.
Here's an abbreviated example module that defines values for views that can be instantiated from different controllers.
module ControllerDefaultValues
def default_value_for_some_controller()
#controller_name = "some_controller"
end
end
To use this, simply include the module in your class:
class SearchesController
include ControllerDefaultValues
#
def search_some_controller
default_value_for_some_controller()
render(:partial => "search_results")
end
end
The main benefit of this method is it keeps your controllers directory focused on controllers and your models directory focused on logic.
Personally i think its fine, if its controller related to put it in your controllers directory, but, labelled as a module, e.g. app/controllers/what_am_i_module.rb since it is specific to the application in development.
lib seems like a place to me where i would put framework/core enhancements or monkey patches which are non-specific to the application.
If it's going to be used by all your controllers, stick it in application_controller.rb
All your controllers inherit from ApplicationController, so they'll all have access to them.