rails content_for does not get executed when doing render? - ruby-on-rails

So I have a content_for inside my view for logging in and in the sessions controller, I have render :new when the user does not enter valid credentials. However, when it does render :new, I get a black and white page without any css or js. This is how my content_for look like
<% content_for :head do %>
<%= stylesheet_link_tag "user_sessions/new" %>
<%= javascript_include_tag 'user_sessions/new.onready' %>
<% end %>
Is there a work around to make sure that the above code gets executed when I do render?

My guess would be that you're not including the content_for anywhere. In app/views/layouts/application.html.erb (or whichever layout you're using for this page) make sure you've got something like the following:
<head>
<!-- your regular head content goes here -->
<%= content_for :head %>
</head>
When you pass a block to content_for, the contents of the block are stored to be used elsewhere. The call to content_for without a block will then insert that stored content.
See the docs for content_for for more info.

<head><%= content_for :head %></head>
didn't work for me, but
<head><%= yield :head %></head>
worked, i guess this is the right to do
Just remembering: yield calls the content, and :head is the parameter for content_for that u put in your rendered view, so u can put pieces of code anywhere of the application.html u want

Related

content_for are not rendering in partial views

I have a rails app which uses a layout
The simplified version looks like this:
<html>
<head>
<%= render 'layouts/head' # renders the "layouts/_head.html.erb" partial correctly
# the most head (css/js) content gets implemented here %>
</head>
<body>
<%= yield # renders the current action %>
<!-- implement alls scripts which should be exectued on the bottom of the page -->
<%= content_for :scripts_bottom %>
</body>
</html>
in my `layouts/_head.html.erb' I use
<%= content_for :scripts_head %>
<!-- it seems `content_for` instead of `yield` appends content -->
In my partials I place the following snippets to append them :scripts_head. (some of my partials should put javaScripts
<% content_for :scripts_head do %>
<%= javascript_include_tag 'some_script' %>
<% end %>
The content_for in the `layouts/head' renders nothing
How can I resolve that?
It looks like that partials are not able to append their content_for content when the content_for :blah do is placed BEHIND the echoing content_for / yield tag.
If I try try content_for :scripts_bottom it will get rendered at the bottom of the page.
Thanks in advance
Rails 3.2.14
ruby 2.0.0p247
instead of provide, try <%= content_for :scripts_head %>
If you want to use content_for then you need to yield it in your head instead of render.
So your header would look like:
<%= yield :scripts_head %>
Alternatively you can remove the content_for in your partial and just have the JS by itself like this:
<%= javascript_include_tag 'some_script' %>
Then you wouldn't have to change your layout file.
In your layouts/head partial, use yield :scripts_head not content_for

Rails 3 nested layouts: how to add at the end?

Is it possible to manipulate the placeholders so that I can not only set their content, but also add/remove content in a particular order? For example:
layouts/base.html.erb (a base layout meant to be extended):
<!DOCTYPE html>
<html>
<head>
<title><%= yield :title %></title>
<%= yield :stylesheets %>
<%= yield :javascripts %>
<%= yield :csrf %>
</head>
<body>
<div class='container-fluid'>
<%= yield :header %>
<%= content_for?(:content) ? yield(:content) : yield %>
<%= yield :footer %>
</div>
</body>
</html>
layouts/application.html.erb (this is the layout I will be using for the most part of my app, it inherits from the base layout):
<% content_for :stylesheets do %>
<%= stylesheet_link_tag "application", :media => "all" %>
<% end %>
<% content_for :javascripts do %>
<%= javascript_include_tag "application" %>
<% end %>
<% content_for :csrf do %>
<%= csrf_meta_tags %>
<% end %>
<%= render :template => 'layouts/base' %>
Now I want a layout for a specific controller, which may need to add more javascript links, or maybe completely remove them. Let's say I want to add only one file after the other javascripts. So far I got this:
layouts/some_controller.html.erb (this is a layout for a particular controller, it should inherit from the application layout):
<% content_for :javascripts do %>
<script src="/assets/some_javascript_that_depends_on_jquery.js" type="text/javascript"></script>
<% end %>
<%= render :template => 'layouts/application' %>
This won't work, because it will place some_javascript_that_depends_on_jquery.js at the beginning of the :javascripts placeholder, and I need it at the end because it depends on jquery.
It would suck to have to extend the base layout directly, and keep track of any change made to the application layout to apply it to the controller-specific layout too.
What would be the recommended way to deal with this situation?
In application.html.erb, Keep the contents of content_for :javascripts in a partial
Here your partial will have
<%= javascript_include_tag "application" %>
Then, call the same partial in addition with other javascripts in other layout.
Another way,
You can call one helper which will have a hash like this:
js_files = {"application_controller" => ["js_file_1"], "some_controller" => ["js_file_1","js_file_2"]}
Now, fetch the js files and construct the javascript include tag in run time based on controller in your content for.
Hope this will be more flexible.
Sorry for not formatting.
Always keep one js file per controller.
<%= javascript_include_tag params[:controller] %>
lets take example of users controller then there will be users.js.coffee file.
If you want to have multiple js files for users controller then you can require those files inside users.js.coffee file
vi users.js.coffee
//= require 'a'
//= require 'b'
/* my extra js code will go here */
This can't be done as in other frameworks where you just extend layouts and then modify the inherited blocks at will.
Rails sort of forces you to keep it simple.

RoR: How do I validate my pages when sometimes I have CSS links not in the HEAD?

I get this error when using the w3 validator: document type does not allow element "link" here
I mean, I know style links are suppossed to be in the head, but for an RoR project, it's more.. efficient? to only load what you need? cause, lets say, A stylesheet is loaded in a partial. and that partial is used on multiple pages. It makes sense, as far as DRYing things up goes, to include the stylesheet with the partial.
But it seems like DRYing things goes against W3C.
What do I do?
You shouldn't be putting <link> elements into your content like that. You can use ERB's blocks to yield the content into another part of your layout template, like this:
<% content_for :head do %>
<%= stylesheet_link_tag 'my_partial_styles' %>
<% end %>
<p>Your partial content...</p>
In your application layout, you can yield this content where it belongs:
<head>
<%= yield :head %>
</head>

Rails rendering content_for not working for partials

I am using a Rails 2.3.8 application. I have a layout file that contains
<%= yield :head %>
I called the following code in different parts of my application:
<% content_for :head do %>
<meta name="keywords" content="" />
<% end %>
I tried to add that code in a view file home it worked. I called it from patial _abc that is called from home it also worked as expected by adding the meta code in the head part. But when I added the code inside partial _def that is called from _abc which is called from home the meta tag did not show up!!!
I didnt usderstand what is going on... and how can bypass this problem
UPDATE: The case that did not work was:
home.html.erb:
<%= render :partial=>"_abc"%>
_abc.html.erb:
<%= render :partial=>"_def"%>
_def.html.erb:
<% content_for :head do %>
<meta name="keywords" content="" />
<% end %>
Thanks a lot
This is an old question, but I got here with a similar issue. Figured I'd post my issue/solution in case someone else lands here.
Which file is <%= yield :head %> in? I had this issue and it turned out my yield was in the "/layouts/application.html.erb" file... But the view being called was using a different layout file i.e. "/layouts/listings.html.erb". once I moved the yield into the correct file, everything worked fine, and I had pretty much the same setup you described.

How to include a css or javascript in an erb that is outside the layout?

Sorry for the slightly noobish question, as I am writing my first rails app.
I get the idea of the layout view, but if you are using them, is there any way to include a view specific js or css file? For example, I have layouts/products.html.erb, and for products/edit.html.erb I want products_edit.css, but I don't want that css for all product views, what is the best practice to accomplish that?
If you have a generic edit.css file, I would suggest an if in your layout
<%= stylesheet_link_tag 'edit' if params[:action] == 'edit' %>
Otherwise you can use content_for with a yield to add additional tags into the head.
layout.html.erb
<head>
...
<%= yield(:header) if #content_for_header %>
</head>
products/edit.html.erb
<% content_for :header do -%>
<%= stylesheet_link_tag 'edit_product' %>
<% end -%>
You can add a stylesheet tag inside the head tag of the layout by doing something like this:
layouts/products.html.erb:
<head>
...
<%= yield :css %>
...
</head>
products/edit.html.erb
<% content_for :css do
stylesheet_link_tag 'products_edit'
end %>
You can't if your </head> tag is in your layout.
You may want a different layout for that controller action. Like this on the render:
render :action => "index", :layout => "some_other_layout
Also you can set a different default layout for a whole controller with this line in the controller class:
layout "some_other_layout"
Check the API docs, there's some complex things you can do with conditionals on that layout method.

Resources