rails helpers location - ruby-on-rails

I made a simple helper with one function and put it in the relevant controller_helper and I noticed that the function is valid from the whole application views.
Why is that? shouldn't the helper be valid only to his controller?

The process is the following:
If you're in a view belonging to controller foo and you call a helper called my_helper:
if defined in foo's helper, it's executed from here
if not defined in foo's helper but defined in another helper, say bar, it's executed from there
if not in foo nor in any bar, it's checked in application_helper. If it doesn't exist here, an error is raised.

That would make sense, but it's not the complete story. I have a controller MainController and a controller AlsoController, and defined a helper with the same name wherefrom in each of the helper modules ie MainHelper and AlsoHelper. But if I try to make use of wherefrom in the also view, it uses the helper defined in MainHelper instead of the one in AlsoHelper.

Related

Grails Custom Scaffolding get access to controller name

I am trying to write a custom src/templates/scaffolding/Controller.groovy and was wondering if there was any way to get access to the controller name? Right now it seems like you can only get the "model" class. The reason I need it is I am customizing the render to prefix the templates directory based on the controller.
For instance I have a controller named AuthorAdminController and I need to customize the list to use the /admin/user/** directory.
Let me know if you have any questions. I am getting ready to look into how to customize DefaultGrailsTemplateGenerator but I am not sure if that is the correct route to go.
Example:
class UserAdminController {
static scaffold = User
}
Currently in my Controller.groovy I get className='user' so I have no access to the controller.
I don't think you can, as the way scaffolding works your template will always be generating a class named DomainClassNameController (i.e. UserController in your example), which gets loaded into a new classloader and then the metaclass of the real controller (UserAdminController) gets new actions added to it which delegate to an instance of the generated UserController.
Now every controller has access to the controllerName property during execution of actions, so this may provide you with a workaround. I haven't tried it, but you could try putting a log.info("controller: \${controllerName}") into the template and see which name it gives you (the backslash to make it resolve at runtime rather than generation time).

Passing a URL to code in a helper method.

I created a Foo controller, and the Foo view allows users to enter and submit a URL. In my Foo helper I have a block of code which scrapes the URL entered by the user (Using nokogiri). How do I pass the url received from the user to the helper so that URL can be parsed and saved to the db? Should I set this up differently?
One way to archive this in Rails 3 is to call view_context inside the
controller to create a new ActionView instance for a controller, then
all helper methods will be available through this instance in the
controller.
view_context.scrape_url_method_in_helper
Or do this in FooController
include FooHelper
Also, read rik.vanmechelen's comment below.

Is it possible to utilize internal methods on controllers to reduce duplication?

in a partial view I have the following:
<%Html.RenderAction(MVC.User.GetComments(Model.UserGroupName)); %>
can I render a Controller's PartialViewResult in a View without going through routing so I can pass arguments directly from the model so that the arguments I'm passing to the controller never get sent to the user or seen by the user?
Currently the method I'm showing at the top throws an exception because no overload is public. I've got it marked as internal so that a user can not access it, only the rendering engine was my intent.
Slap a [ChildActionOnly] attribute on any action method if you want that method to be callable only by RenderAction() rather than the outside world. Or - if you have a whole controller of such methods - slap the attribute on the controller itself.

Guidelines for calling controller methods in helper modules?

Few questions:
Is it possible to call a controller method in a helper module (e.g., application helper)?
If so, how does the helper handle the rendering of views? Ignore it?
In what instances would you want to call a controller method from a helper? Is it bad practice?
Do you have any sample code where you're calling controller methods in helper?
You generally don't call controller-methods from helpers. That is: if you mean a method that collects data and then renders a view (any other method that needs to be called should probably not be in a controller).
It is definitely bad practice and breaks MVC.
It is, however, perfectly possible to make controller-methods available in the views, a great example is for instance the current_user method.
To make a controller method available in the views, as a helper method, just do
private
def current_user
# do something sensible here
#current_user ||= session[:user]
end
helper_method :current_user
Such a method is best defined in the private section, or it could be available as an action (if you a wildcard in your routing).
Declare your methods on the corresponding controller
private
def method_name1
...
end
def method_name2
...
end
In the head of the controller declare
helper_method :method_name1, :method_name2
You may want to declare those methods under private state
And that's it, now you can use your method on a helper
Calling a controller from a helper violates the MVC pattern. IMO if you need to call a controller from a Rails view helper (like application_helper) then there is something about the design that could be improved. The intention is that helpers "help" views, and therefore only talk to models.
I'm not going to defend MVC itself here (there are a ton of references on the web), but this SO thread about calling the controller from a view should get you started.
Calling controller from view? (note, this is an ASP.NET thread, so only the high level principles are relevant).

can I have a controller associated with a partial?

In rails, page templates have their own controller which is called before a page is rendered (I think?).
Likewise, can I have a controller associated with a partial that is called before the partial is rendered?
I know you can pass local variable into a partial, but I want to run a good few lines of code to assign those local variables, which if I wasn't using a partial I would have put in the controller.
This code that you want to run should be in a helper that can be called from the controller, or from the partial itself.

Resources