View Helper Scope

Hello, I just noticed something that has confused me. I have a number of
controllers, each with an associated helper file. If I have a helper
function, say "x" defined in all of the helpers it would appear that the
one in the lexicographically last helper file is the one that gets used,
regardless of which controller I am rendering a view for.

For example, I have helper method "x" defined in:

application_helper
a_helper
z_helper

I render a view for controller a and the helper method in file z_helper
gets used. I would expect the one in a_helper to be used.

I render a view for controller b (no helpers defined for b) and the file
in file z_helper gets used. I would expect the one in application_helper
to be used.

Is there something about scope that I misunderstand ? Or is my app
otherwise broken?

I'm very confused - this is not working how I thought it should!

Thanks.

Hello, I just noticed something that has confused me. I have a number of
controllers, each with an associated helper file. If I have a helper
function, say "x" defined in all of the helpers it would appear that the
one in the lexicographically last helper file is the one that gets used,
regardless of which controller I am rendering a view for.

For example, I have helper method "x" defined in:

application_helper
a_helper
z_helper

I render a view for controller a and the helper method in file z_helper
gets used. I would expect the one in a_helper to be used.

I render a view for controller b (no helpers defined for b) and the file
in file z_helper gets used. I would expect the one in application_helper
to be used.

Is there something about scope that I misunderstand ? Or is my app
otherwise broken?

By default all of your helpers are included in all of your views
( There should be something saying helper :all in
application_controller.rb). In practice what this means is that there
is an anonymous module somewhere, Rails includes all of your helpers
into that module and that module is then included into view objects.
This of course means that if multiple helpers have the same name then
the they will overwrite each other. If you remove the helper :all
statement then by default controller a will only get
application_helper and a_helper (you can always ask for extra helper
modules to be available for a specific controller (or indeed all
controllers))

Fred

Thank you this is exactly what is happening. I have done some more
reading and note that this is now the default behaviour. I am unclear on
why this would be desirable as default behaviour though. Regardless, I
now know to remove the "helper :all" from application_controller.rb.
Thanks!

I have a follow-on question.

If I have a helper method "x" in application_helper.rb and another
helper method "x" in mycontroller_helper.rb, how do I call
ApplicationHelper.x from MyController.x ?

I tried ApplicationHelper::x but it gave me an error

undefined method `x' for ApplicationHelper:Module

(I probably just don't understand Ruby scope resolution)

Thanks in advance.

In my opinion it is not desirable at all. It may be useful when starting
a simple project as everything is automatically there. When the project
grows, however, it bars the way to scoping helpers sensibly, as you have
already noticed.

Helpers are procedural by nature. helper :all drives out the last bit of
polymorphism there was.

Michael

Michael Schuerig wrote:
[...]

Helpers are procedural by nature. helper :all drives out the last bit of
polymorphism there was.

Why do you say that? I don't understand, except to the extent that
Rails views are sort of procedural.

Michael

--
Michael Schuerig
mailto:michael@schuerig.de
http://www.schuerig.de/michael/

Best,

You could only do that if x was a module method on the module (but if
that's the case then including the module doesn't add it as an
instance method).

You can either include the helper module into your controller or put
the method in the controller and then do helper_method :method_name

Fred

If you only include specific helper modules, you can have multiple
methods with the same name, but different implementations. This can be
useful in order to avoid inadvertently stepping on another method with
the same name in an overcrowded helper namespace. More interestingly,
you can have generically named helper methods with implementations
appropriate for different model classes.

Michael

Michael Schuerig wrote:

Michael Schuerig wrote:
[...]

> Helpers are procedural by nature. helper :all drives out the last
> bit of polymorphism there was.

Why do you say that? I don't understand, except to the extent that
Rails views are sort of procedural.

If you only include specific helper modules, you can have multiple
methods with the same name, but different implementations. This can be
useful in order to avoid inadvertently stepping on another method with
the same name in an overcrowded helper namespace.

Of course. No argument there. I just don't understand your
"procedural" claim.

More interestingly,
you can have generically named helper methods with implementations
appropriate for different model classes.

But then wouldn't those be better as model methods, not helper methods?

Michael

--
Michael Schuerig
mailto:michael@schuerig.de
http://www.schuerig.de/michael/

Best,

Michael Schuerig wrote:
>> Michael Schuerig wrote:
>> [...]
>>
>> > Helpers are procedural by nature. helper :all drives out the
>> > last bit of polymorphism there was.
>>
>> Why do you say that? I don't understand, except to the extent
>> that Rails views are sort of procedural.
>
> If you only include specific helper modules, you can have multiple
> methods with the same name, but different implementations. This can
> be useful in order to avoid inadvertently stepping on another
> method with the same name in an overcrowded helper namespace.

Of course. No argument there. I just don't understand your
"procedural" claim.

Well, helper methods *are* procedural. Only by judiciously including
helper modules you can manually achieve the illusion of polymorphism
(one method name, multiple implementations).

> More interestingly,
> you can have generically named helper methods with implementations
> appropriate for different model classes.

But then wouldn't those be better as model methods, not helper
methods?

Formatting (e.g.) doesn't belong in the model, does it?

Michael

Michael Schuerig wrote:

>
> If you only include specific helper modules, you can have multiple
> methods with the same name, but different implementations. This can
> be useful in order to avoid inadvertently stepping on another
> method with the same name in an overcrowded helper namespace.

Of course. No argument there. I just don't understand your
"procedural" claim.

Well, helper methods *are* procedural.

All methods are procedural.

Only by judiciously including
helper modules you can manually achieve the illusion of polymorphism
(one method name, multiple implementations).

What's the point of helper "polymorphism"? I'm having trouble coming up
with a good use case for it.

> More interestingly,
> you can have generically named helper methods with implementations
> appropriate for different model classes.

But then wouldn't those be better as model methods, not helper
methods?

Formatting (e.g.) doesn't belong in the model, does it?

I think simple formatting does -- for example, I like to have a
meaningful to_s. Complex helpers should probably be made into partials.
There's a fairly narrow band in between where helpers are really the
best solution.

Or maybe I don't understand what helpers are good for. Can you give me
an example of what you think an appropriate helper method is?

Michael

--
Michael Schuerig
mailto:michael@schuerig.de
http://www.schuerig.de/michael/

Best,

Michael Schuerig wrote:
>> > If you only include specific helper modules, you can have
>> > multiple methods with the same name, but different
>> > implementations. This can be useful in order to avoid
>> > inadvertently stepping on another method with the same name in
>> > an overcrowded helper namespace.
>>
>> Of course. No argument there. I just don't understand your
>> "procedural" claim.
>
> Well, helper methods *are* procedural.

All methods are procedural.

No. Strictly speaking, helper methods ought to be called helper
functions as they are not attached to specific objects. Methods in the
object-oriented sense are not procedural, however, they mostly are
implemented procedurally.

> Only by judiciously including
> helper modules you can manually achieve the illusion of
> polymorphism (one method name, multiple implementations).

What's the point of helper "polymorphism"? I'm having trouble coming
up with a good use case for it.

format_value, cancel_link are just two examples where generic names are
perfectly understandable within a context, although they may need to do
different things depending on context.

>> > More interestingly,
>> > you can have generically named helper methods with
>> > implementations appropriate for different model classes.
>>
>> But then wouldn't those be better as model methods, not helper
>> methods?
>
> Formatting (e.g.) doesn't belong in the model, does it?

I think simple formatting does -- for example, I like to have a
meaningful to_s. Complex helpers should probably be made into
partials. There's a fairly narrow band in between where helpers are
really the best solution.

Or maybe I don't understand what helpers are good for. Can you give
me an example of what you think an appropriate helper method is?

Say you an overview page where you want to consistently display numeric
or monetary values with a specific precision (or format in general).
Instead of sprinkling the view with

  <%= number_to_currency foo.amount, :precision => 0 %>
  <%= number_to_currency bar.amount, :precision => 0 %>
  ...

you'd better define a suitable helper method:

  <%= format_money foo.amount %>
  <%= format_money bar.amount %>
  ...

Then, in case you change your mind about how things ought to look,
there's only one place to change. And, besides, the helper methods name
can be used to convey some semantics.

Now consider you have a more detailed view of similar information where
values are shown with full precision. There you could still use
format_money, but with a suitable implementation.

Before you ask, I don't like things like format_foo_bar_baz_money at
all. I don't want this kind of forced disambiguation, because I don't
want to be overly specific. It's up to the context what format_money is
supposed to mean. Nicely, this even works with partials as they use just
those helper methods which are available in the given context.

Michael

No, helper methods are indeed methods. They are defined in modules,
and those modules are included into views by the controllers, and can
be explicitly included by other classes.

If this were not the case then the helpers couldn't reference
view/controller instance variables, which they can.

The OPs question was why duplicated method names weren't resolved
according to some perceived inheritance hierarchy. The resolution
just follows standard ruby semantics.

1. First look for a singleton method in the receiver object.
2. If that fails look for an instance method defined by any modules
which the object extends, in the reverse chronological order of
extension.
3, If that fails set the class to examine to the class of the object
4. look for an instance method in the class to examine
5. If that fails look for an instance method defined by any modules
which the class to examine includes, in the reverse chronological
order of inclusion.
6. If that fails and the class to be examine has a superclass, set the
class to examine to that superclass and go to step 4, otherwise send a
method_missing to the receiver object.

Now normally, a controller will include the helper(s) associated with
it's superclass (usually ApplicationController and therefore
ApplicationHelper), and the helper associated with itself in that
order. But this default can be change using the
ActionController::Base#helper method (which in Rails 2.x is actually
defined in the module ActionController::Helpers.

It's not uncommon for a Rails app to invoke

helper :all

in its ApplicationController which includes all helpers in the
app/helpers directory and it's subdirectories in the order they are
enumerated by Dir.[] with a recursive glob argument.

In this case whichever helper method with the name in question was
defined by the last included module will win.

Aren't all 'functions' technically methods in ruby ?

Fred

Of course. My point is that helpers are REALLY methods of the
instance of view, have access to it's state, and all the other rights
and privileges of an instance method.

Yes, ruby 'functions' are really private instance methods which get
defined in the Object class, and module functions (as in
Module.module_function) are methods of an instance of Module, but
helpers are not 'functions' in either of those senses.

Michael Schuerig wrote:
[...]

What's the point of helper "polymorphism"? I'm having trouble coming
up with a good use case for it.

format_value, cancel_link are just two examples where generic names are
perfectly understandable within a context, although they may need to do
different things depending on context.

Does cancel_link need to do different things depending on context? If
so, what?

meaningful to_s. Complex helpers should probably be made into
partials. There's a fairly narrow band in between where helpers are
really the best solution.

Or maybe I don't understand what helpers are good for. Can you give
me an example of what you think an appropriate helper method is?

Say you an overview page where you want to consistently display numeric
or monetary values with a specific precision (or format in general).
Instead of sprinkling the view with

  <%= number_to_currency foo.amount, :precision => 0 %>
  <%= number_to_currency bar.amount, :precision => 0 %>
  ...

you'd better define a suitable helper method:

  <%= format_money foo.amount %>
  <%= format_money bar.amount %>
  ...

Then, in case you change your mind about how things ought to look,
there's only one place to change. And, besides, the helper methods name
can be used to convey some semantics.

Now consider you have a more detailed view of similar information where
values are shown with full precision. There you could still use
format_money, but with a suitable implementation.

I agree that the second option is better than the first, but I think
they're both kind of bad. This is putting too much logic in the view
IMHO (although I admit I sometimes do it anyway, until I refactor. :slight_smile: ).

What I would do instead is make foo.amount and bar.amount Money objects
(using composed_of if ActiveRecord is involved). Then define
Money#to_s, and the view will simply be

<%= foo.amount %>
<%= bar.amount %>

I don't see any need for a helper here. Am I missing something?

Before you ask, I don't like things like format_foo_bar_baz_money at
all. I don't want this kind of forced disambiguation, because I don't
want to be overly specific. It's up to the context what format_money is
supposed to mean.

I'm not sure what that technique would even be, so don't worry -- I
wasn't thinking of it! :slight_smile:

Nicely, this even works with partials as they use just
those helper methods which are available in the given context.

True. But that's only an issue if partials are shared between
controllers. In my applications, I find that that does not happen
often, but YMMV.

Michael

--
Michael Schuerig
mailto:michael@schuerig.de
http://www.schuerig.de/michael/

Best,

Michael Schuerig wrote:
[...]

>> What's the point of helper "polymorphism"? I'm having trouble
>> coming up with a good use case for it.
>
> format_value, cancel_link are just two examples where generic names
> are perfectly understandable within a context, although they may
> need to do different things depending on context.

Does cancel_link need to do different things depending on context?
If so, what?

Let's say that, in an edit view, you want cancel_link to generate a link
back to the corresponding list view. But you might want it to do
something else. At any rate, I want a common name, but possibly
different concrete functionality.

[...]

> <%= format_money foo.amount %>
> <%= format_money bar.amount %>

[...]

What I would do instead is make foo.amount and bar.amount Money
objects (using composed_of if ActiveRecord is involved). Then
define Money#to_s, and the view will simply be

<%= foo.amount %>
<%= bar.amount %>

I don't see any need for a helper here. Am I missing something?

Assuming foo and bar are model instances, how would you differentiate
that sometimes you'd like to display only whole units, or even
"kilobucks" (k$), and at others everything to the last cent. In one case
with, in another without currency unit. And let's not forget about
decimal and thousand separators.

These are strictly UI-issues that don't belong in the model. Now, if foo
and bar were presenter instances, things would look different.

Michael

Michael Schuerig wrote:

Does cancel_link need to do different things depending on context?
If so, what?

Let's say that, in an edit view, you want cancel_link to generate a link
back to the corresponding list view.

I think you could just leave the controller name out of link_to.

But you might want it to do
something else. At any rate, I want a common name, but possibly
different concrete functionality.

I am hard put to come up with a use case for this is a helper. I don't
find your example particularly convincing.

[...]

> <%= format_money foo.amount %>
> <%= format_money bar.amount %>

[...]

What I would do instead is make foo.amount and bar.amount Money
objects (using composed_of if ActiveRecord is involved). Then
define Money#to_s, and the view will simply be

<%= foo.amount %>
<%= bar.amount %>

I don't see any need for a helper here. Am I missing something?

Assuming foo and bar are model instances, how would you differentiate
that sometimes you'd like to display only whole units, or even
"kilobucks" (k$), and at others everything to the last cent.

Probably by having to_s take an optional parameter.

In one case
with, in another without currency unit. And let's not forget about
decimal and thousand separators.

Same answer.

These are strictly UI-issues that don't belong in the model.

No they're not. I tend to think models should know how to display
themselves. Otherwise, you wind up with poor view code like your
earlier example and inappropriate coupling with the model's internals.

I'm not saying models should generate their own HTML formatting, but I
don't think it's unreasonable to have them responsible for their own
string representation. Then the views can consume those strings.

Now, if foo
and bar were presenter instances, things would look different.

That's too simple an example to need a presenter. Or, I think, a
helper.

Michael

--
Michael Schuerig
mailto:michael@schuerig.de
http://www.schuerig.de/michael/

Best,

Let's just leave it at that and acknowledge that our views differ.

If you don't already know them for a long time, you might enjoy Allen
Holub's old JavaWorld articles on UI construction.

http://holub.com/publications/articles/index.html#javaworld

Michael

Michael Schuerig wrote:

strings.

Let's just leave it at that and acknowledge that our views differ.

I really would rather not leave it there. If I'm doing things the wrong
way, I don't want to keep doing what I'm doing.

If you don't already know them for a long time, you might enjoy Allen
Holub's old JavaWorld articles on UI construction.

http://holub.com/publications/articles/index.html#javaworld

Yes. I generally don't agree that much with Holub, but it was in fact
trying to incorporate some of his ideas that led me to the views that
I've been explaining in this thread.

Michael

--
Michael Schuerig
mailto:michael@schuerig.de
http://www.schuerig.de/michael/

Best,