serving only controller+action specific css/javascript

Hi, input please!

I’m trying to dynamically serve js/css based on the active controller+action, e.g.:

In application_helper.rb, I’m using the following method to create the dynamic bits of the asset URLs:

def asset_path_fragment

#{controller.controller_name}/#{controller.action_name}

end

Then I realized a flaw in my logic:

def update

if @something_goes_wrong

render :edit # render the #edit’s view but erroneously serve the #update’s css/js

end

end

So … what should I do?

Well, I see I can do this, but it seems like a pretty bad idea.

def update

if @something_goes_wrong

  **self.acion_name = 'edit'**

render :edit

end

end

Anyone?

Sounds like a job for content_for. You need a snippet like this in your view template:

update.html.erb:

<% content_for :assets do %>

<%= stylesheet_link_tag “people/update” %>

<%= javascript_include_tag “people/update” %>

<% end %>

And in your layout:

<%= yield :assets $>

Hmm, maybe I’m confused. Even if I used your solution verbatim I think I’m still stuck with the problem as update.html.erb would not be used (edit.html.erb would).

To recap, what you’re suggesting is essentially what I’m doing – except instead of hard-coding “people/update” I’m using a helper method that uses controller.controller_name + “/” + controller.action_name to generate that part of the path.

So far so good, but when I use “render :edit” in the “update” action, I’ve got my problem (I’m requesting the wrong action’s assets).

No, in the solution I suggested the decision about which assets to use is made in the template and can’t depend on the controller name/action. There’s no way that I know of to determine the template name in the same way via a helper function.

The only other option that might be useful for you would be to have combined CSS/JS files for some actions where this type of thing can occur like with update/edit and set the ID or class of the tag based on the template rendered. You could then target selectors in your assets to ensure the correct behavior, but this might end up being more effort than a simpler solution.

Thanks. The 2nd option you’re suggesting (body IDs) is what I originally had in mind until this debate broke out against using the ID attribute on the body tag (which I kind of ended up liking).

But, for the sake of pragmatism, I might have to again revisit my approach thanks to this new twist.

Just to add my two cents, the body approach works well as long as you work with classes, not a single id, not with the id. Something like action_youractionname and controller_yourcontrollername. Modernizr has a similar approach to specify what features are available.

Cool, I’ll check it out - thanks again.

Here is my code:

%body{ :class => "controller_#{controller.controller_name} #{defined?(@page_cssclass) ? @page_cssclass : ''}" }

I am using a custom page_css class set in the controller action method here instead of an action name, but I would use an action name instead these days

This may look like a quick and dirty way to do this, but might work with minimal effort.

Also, this will work only in the scenario where create and update never have their own views - this would be the case most often, but just wanted to highlight it

def asset_path_fragment

css_action = case controller.action_name

when “create”

“new”

when “update”

“edit”

else

controller.action_name

end

“#{controller.controller_name}/#{css_action}”

end