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 Michael Schürig | Sentenced to making sense

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 Michael Schürig | Sentenced to making sense

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 Michael Schürig | Sentenced to making sense

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 Michael Schürig | Sentenced to making sense

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 Michael Schürig | Sentenced to making sense

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.

Allen Holub: Training/Consulting/Programming: Agile, Architecture, Swift, Java

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 Michael Schürig | Sentenced to making sense

Best,