Avoid shared helpers conflict within views

According to this article Rails helpers from a particular controller are
available to all views. But to me this looks kind of a dangerous
approach because as the project gets larger the developer can mistakenly
at some point use helper methods with the same name but with different
implementations. This architecture can cause conflicts and undesired
results in the long run. This problem actually happened one time and it
took me quite some time to figure out the problem. This is why I am kind
of worried with this issue.

What should I do to prevent this problem from occurring?
Why is the Rails helper scoped this way?
What is the reason for sharing helpers between views?
Does anyone had any problems with this approach?
Is there another recommended way to work?

Thank you

Rod

On Wednesday, February 5, 2014 4:46:12 PM UTC, Ruby-Forum.com User
wrote:

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

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 and therefore 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 setting this option to false:
config.action_controller.include_all_helpers =
false?

end

thanks

Frederick C. wrote in post #1135687:

On Wednesday, February 5, 2014 4:46:12 PM UTC, Ruby-Forum.com User
wrote:

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

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

On Wednesday, February 5, 2014 7:29:41 PM UTC, Ruby-Forum.com User
wrote:

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.

def blabla
end

Personally I’d rather write

helper :currency

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

Fred

On Thursday, February 6, 2014 12:58:35 AM UTC, Ruby-Forum.com User
wrote:

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

Frederick

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

Thanks
Rod

Frederick C. wrote in post #1135734:

On Wednesday, February 5, 2014 7:29:41 PM UTC, Ruby-Forum.com User
wrote:

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.

def blabla
end

Personally I’d rather write

helper :currency

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

Fred

On Wednesday, 5 February 2014 11:46:12 UTC-5, Ruby-Forum.com User wrote:

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

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 J.

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

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?

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

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