Rails shared helpers within views conflict

According to this article Rails helpers from all controllers are available to all views. But to me this looks kind of a dangerous approach because I might at some point use helper methods with the same name but with different implementations that can cause conflicts and undesired results. This actually happened one time and it took me quite some time to figure out the problem.

Why is the Rails helper scope this way? What is the reason for sharing? Does anyone had any problems with this approach? Is there another recommended way to work?

Thank you

Rod

The reason is to encourage people to split out their helpers rather than just dumping everything in application_helper.rb (because with this you can do that without having to add lots of helper :blah lines to your controllers). Personally I think it’s a really bad idea for the reason you mention and always set config.action_controller.include_all_helpers = false to stop this happening

It’s also worth looking at gems just as draper - a lot of the helpers I used to write secretly wanted to be decorators

Fred

Frederick,

Thanks. I am glad you agree with me. By the way, do you recommend setting this option to false as good practice on every fresh project? Looks like your idea solves the issue, but of course, will force you to dump stuff like you said, in application.rb.

I researched a little bit and I found a way to reference common code in application without bloating it out making you suggestion a good practice.

For instance, instead of placing Currency code in application code you just reference it with an include and it will be available in all views. This is better approach than the promiscuous helper architecture

module ApplicationHelper   include CurrencyModule

def blabla end

Is there any other reason for not doing this: config.action_controller.include_all_helpers = false?

end

thanks

Frederick Cheung wrote in post #1135687:

Does anyone had any problems with this approach? Is there another recommended way to work?

Frederick,

Thanks. I am glad you agree with me. By the way, do you recommend setting this option to false as good practice on every fresh project? Looks like your idea solves the issue, but of course, will force you to dump stuff like you said, in application.rb.

I always do. It doesn’t force you to dump stuff in application_helper.rb, it just makes that the path of least resistance.

I researched a little bit and I found a way to reference common code in application without bloating it out making you suggestion a good practice.

For instance, instead of placing Currency code in application code you just reference it with an include and it will be available in all views. This is better approach than the promiscuous helper architecture

module ApplicationHelper

include CurrencyModule

def blabla

end

Personally I’d rather write

helper :currency

in application controller (or whatever is the appropriate subset of controllers).

Fred

Frederick

Could you please elaborate "helper :currency?" Can you give an example?

Thanks Rod

Frederick Cheung wrote in post #1135734:

Frederick

Could you please elaborate “helper :currency?” Can you give an example?

class FooController < ApplicationController

helper :currency # ← CurrencyHelper module is included in views rendered by this controller

end

Fred

I got it. There is also another way, which is to define the helper method as an instance of the helper class using "self". This way:

def self.format_currency(price) ... end

Then in the view this this <%= Admin::currencyHelper.format_currency(price)%>

But the drawback is that you have to manually use the full namespace in your views and the code might get ugly. But, I know it is bad but it is an option.

I kind of like you last suggestion, and I wish I had learned this trick before. Just to clarify your last suggestion, in the case of the Currency, do you create a stand-alone helper, I mean, a helper separated from a controller and place it into the helpers folder?

Thank you

Depends on who you ask - I’m of the opinion that if you have two functions with the same name but mixed into different controllers you’ve just made your code harder to navigate. At that point, the result of rendering a template is dependent on which controller is rendering it (since the controller picks which helpers are available).

–Matt Jones

There is 2 more things about helpers:

  • First your helpers should be something really small, if you need too many functions, your doing something wrong, either you need to pass something to the models or build decorators.

  • Another thing is: can you give me an example of a helper you need to set the same name for? I mean is that gonna happen that often?

There it goes the example. Sorry, I did not know how to format.

def self.get_order_assets(od_id)    return OrderAsset.select("assets.file_name,    order_assets.*").joins("INNER JOIN assets ON assets.id =    order_assets.asset_id ").where("order_detail_id=#{od_id}") end

def get_order_assets(od_id)     oa =OrderAsset.select("order_assets.*").where("order_detail_id =    #{od_id}")    return oa end

Is this 2 methods inside of which files?

To start I dont see the point of the select here:

oa =OrderAsset.select(“order_assets.*”).where(“order_detail_id = #{od_id}”)

this is the same as

oa =OrderAsset.where(“order_detail_id = #{od_id}”)

Second thing, you should use a scope for this on the model!

Third:

The way you should call them are completly wrong! one returns a collection of assets the other one returns an asset.

I also dont understand why you are defining class methods for an helper(maybe you have a good reason).

So the first one that returns a collection you should actually giving a name to it like:

(you should use scopes again but now I just wanna give you a naming example)

def get_order_assets_from_detail

and the other one:

def get_order_asset_from_detail

you see the difference on the s?

I hope you understand what I mean, but I think you need to look more into scopes and how to create decorators! It will give you an insight of what you should put in a decorator, a model and in a helper!

all the best,

Andre