This question already has answers here:
Where to put Ruby helper methods for Rails controllers?
(6 answers)
Closed 8 years ago.
I have a few helpful functions I want to use in my controller but I don't know where to put them. For instance I have a method to form a JSON structure which I need to use a few times.
I would probably end up putting it in some form of utilities class which would contain a bunch of useful functions. Is this the correct way to go about it?
The correct way to put helpers functions, is put them as private in the same controller or put in application controller if your helpers functions are used in most of your controllers.
EDITED
If your helpers functions have any function needed on the view, use helpers
Related
I am trying to convert my website from Wordpress/php to Ruby on Rails and am having trouble grasping the conceptual side of OOP/MVC in Ruby/Rails as it relates to passing variables between views. I have found many answers to how to do it, but I am still unclear exactly what is going on and I think it is because I have not grasped the concept of classes and methods in this particular context.
In PHP I can simply pass a variable to another page like this:
http://myurl.com/scores/?myteam=team1
To do this in Rails - pass one variable (myteam in the example previous) between views using a link - then:
what methods, classes and objects are involved (and I need to set up) and
at what point are they initialized?
Read this Controller's Rails guide, especially parameters section: http://guides.rubyonrails.org/action_controller_overview.html#parameters
Basically you will get access to this variable in controller using params hash, for this example it will be params[:myteam].
Simple question about best-practice. I'm using Kohana... is it okay to use helpers in views? For example, to use URL::site(). I could pass it from controller, you know. I assume it's okay, because there are helpers like HTML that is meant to be used in views, right?
The way you're currently doing it is ok, altough the whole practice of having any logics in views is questionable, but it's how Kohana is currently recommending.
When you get to use ViewModel pattern (with Kostache?), you'll separate all logics from templates. Until then, it's ok to use methods that don't do anything that should be done in the controller / model (echo, conditions and loops are "considered allowed").
i have a function that converts an array to a hash which i would like to use across all the model, controller and view files in the rails app.
Does this violate some core design principle, or am i missing something really obvious?
UPDATE: This is actually a software engineering question. I want to understand why some "convenient" things are not allowed in rails, and i suspect it is precisely because they do not want us to do it
This is likely actually a bad practice. It'd likely be better to instead always work with arrays and hashes in your controllers and models and if necessary convert them in the view to the alternative.
That is, if the data is natively represented as a array throughout your application work with it that way and if required to be a hash in the view either convert it first and assign it or convert it in the view using a helper.
View global helpers go in: helpers/application_helper.rb
If you must call a helper from a controller you can still define it there and I believe you can do:
def Something
....
hashData = #template.helper(arrayData)
end
Calling helpers in a model is REALLY not a good idea, there's no point.
As a final note, encapsulating this logic in a library would likely be ideal, your controllers can call a library & your view helpers can as well.
I think you are: views should not need that method. The controller ought to do it and pass it along to the view for display. The controller or, better yet, service layer might apply that method to a model object, but there's little reason for a model object to know about it.
I know that if I want to call a helper of another controller, I can do something like:
helper :other_controllers
But I was wondering why I can't do something like OtherControllersHelper.method inside the view?
Due to the way that Rails loads your modules, you cannot do this without modification.
Rails includes the associated helper models into the ActionView::Base instance used to render a template. ActionController::Helpers#helper (used in the example above) adds more helper modules to the list of those to be included. The helper methods that are used in views are written as instance methods. Modules in Ruby do not provide any good ways of getting at instance methods without using a constructor. Which is one of the big things that separates modules from classes.
To access your helpers from another controller with just OtherControllersHelper.method, you will need to redefine method as a class method. However, redefining those methods as class methods would make them inaccessible from your views.
You could duplicate all instance methods in your helpers as class methods, but that's definitely not a better solution that adding helper :other_controllers. There are ways to define wrappers pragmatically, but again, it's not the best way to handle the situation.
If you've got a lot of helpers that are likely to be used in multiple controllers/views maybe you're better off putting them somewhere else. Somewhere like app/helpers/application_helper.rb. Or another helper module that could be loaded only in the controllers that need it.
I have some controller methods I'd like to share. What is the best practice for doing this in ruby on rails? Should I create an abstract class that my controllers extend, or should I create module and add it in to each controller? Below are the controller methods I want to share:
def driving_directions
#address_to = params[:address_to]
#address_from = params[:address_from]
#map_center = params[:map_center_start]
# if we were not given a center point to start our map on
# let's create one.
if !#map_center && #address_to
#map_center = GeoKit::Geocoders::MultiGeocoder.geocode(#address_to).ll
elsif !#map_center && #address_from
#map_center = GeoKit::Geocoders::MultiGeocoder.geocode(#address_from).ll
end
end
def printer_friendly
starting_point = params[:starting_point].split(',').collect{|e|e.to_f}
ne = params[:ne].split(',').collect{|e|e.to_f}
sw = params[:sw].split(',').collect{|e|e.to_f}
size = params[:size].split(',').collect{|e|e.to_f}
address = params[:address]
#markers = retrieve_points(ne,sw,size,false)
#map = initialize_map([[sw[0],sw[1]],[ne[0],ne[1]]],[starting_point[0],starting_point[1]],false,#markers,true)
#address_string = address
end
In my opinion, normal OO design principles apply:
If the code is really a set of utilities that doesn't need access to object state, I would consider putting it in a module to be called separately. For instance, if the code is all mapping utilities, create a module Maps, and access the methods like: Maps::driving_directions.
If the code needs state and is used or could be used in every controller, put the code in ApplicationController.
If the code needs state and is used in a subset of all controllers that are closely and logically related (i.e. all about maps) then create a base class (class MapController < ApplicationController) and put the shared code there.
If the code needs state and is used in a subset of all controllers that are not very closely related, put it in a module and include it in necessary controllers.
In your case, the methods need state (params), so the choice depends on the logical relationship between the controllers that need it.
In addition:
Also:
Use partials when possible for repeated code and either place in a common 'partials' directory or include via a specific path.
Stick to a RESTful approach when possible (for methods) and if you find yourself creating a lot of non-RESTful methods consider extracting them to their own controller.
I know this question was asked 6 years ago. Just want to point out that in Rails 4, there're now Controller Concerns that're a more out of the box solution.
I actually think a module is the best way to share code amongst controllers. Helpers are good if you want to share code amongst views. Helpers are basically glorified modules, so if you don't need view level access, I suggest placing a module in your lib folder.
Once you create the module, you'll have to use the include statement to include it in the desired controllers.
http://www.rubyist.net/~slagell/ruby/modules.html
I agree with the module approach. Create a separate Ruby file in your lib directory and put the module in the new file.
The most obvious way would be to add the methods to your ApplicationController, but I am sure you know that already.
if you want to share codes between controller and helpers, then you should try creating a module in library. You can use #template and #controller for accessing method in controller and helper as well.
Check this for more details http://www.shanison.com/?p=305
Another possibility:
If your common code needs state and you want to share the behavior amongst controllers, you could put it in a plain old ruby class in either your model or lib directory. Remember that model classes don't have to be persistent even though all ActiveRecord classes are persistent. In other words, it's acceptable to have transient model classes.
I found that one effective way to share identical code across controllers is to have one controller inherit from the other (where the code lives). I used this approach to share identical methods defined in my controllers with another set of namespaced controllers.