I have a child object with an alternate partial form. Further to this question, I'm able to render the object using a partial form like this:
<%= render 'child_items/alternate_partial', :collection => parent_item.child_items %>
But I can't seem to access members of the collection in the partial. When I was using:
<%= render parent_item.child_items %>
the partial could just go <%= child_item.property %> and everything worked. But when I'm doing this the top way (and it seems that I have to, if I want to specify the partial), any reference to child_item throws a NameError. How do I get at the collection item inside the partial?
As mentioned on http://guides.rubyonrails.org/layouts_and_rendering.html#using-partials in 3.4.5 Rendering Collections:
When a partial is called with a pluralized collection, then the individual instances of the partial have access to the member of the collection being rendered via a variable named after the partial.
In this case, the partial is _alternate_partial, and within the _alternate_partial partial, you can refer to alternate_partial to get the instance that is being rendered.
Related
Per the information box on https://guides.rubyonrails.org/layouts_and_rendering.html#using-partials:
Rails also makes a counter variable available within a partial called
by the collection, named after the title of the partial followed by
_counter. For example, when rendering a collection #products the partial _product.html.erb can access the variable product_counter
which indexes the number of times it has been rendered within the
enclosing view.
However, I am getting and error when referencing the counter in my partial. Here is the parent view:
<%= render partial: 'comments/comment_template', collection: #post.comments, as: :c %>
Here is the relevant part of _comment_template.html.erb:
<%= comment_template_counter %>
And here is the error:
undefined local variable or method `comment_template_counter' for #<#<Class: [etc.]
What am I missing?
I believe the documentation is incorrect. As pointed out by pedroadame at https://coderwall.com/p/t0no0g/render-partial-with-collection-has-hidden-index, when using the :as option, I need to use the name of the variable rather than the name of the partial.
Furthermore, if elsewhere in my app I am only rendering the partial once instead of as a collection, I need to sidestep the (same) error message by checking whether the counter is defined.
So in my partial, this now works:
<%= c_counter if defined? c_counter %>
Is it possible to render a view with get parameters ?
For example, something like :
render "/projects/sheets?id=43"
It's because I need to render a view which uses url parameters to work properly.
I tried many ways, but it only creates parameters that I can get only in the controller and that are not available after.
It's because I want to have a view that contains the html code of many other views.
This is my current code :
allProjects.html.erb :
<% Project.where(productchief: user.id).order(:title).each do |project| %>
<%= render "/projects/sheets?id=#{project.id}" #This doesn't work. %>
<% end %>
It's because I want to have a view that contains the content of all the other views in my website to allow the users to print all this content in one time.
I don't think it's possible to do it in the way you are trying to do it. You will need to change /projects/sheets to be a partial and render that instead and pass through local variables.
So to clarify /projects/sheets.html.erb becomes /projects/_sheets.html.erb and you would then invoke as:
<%= render partial: "/projects/sheets", locals: { :project_id = project.id } %>
Then within the partial _sheets.html.erb you can make reference to project_id
Generally you should be able to access the params in a view but unless there's a very specific reason you can't, I suggested altering your routes. I may be missing some info from your original question, but let's say you have routes as:
get 'projects/sheets', to: "projects#index", as: :projects
get 'projects/sheets/:id', to: "projects#show", as: :project
That would change your urls a little but would still leave the params available. Using the routes above, for example and going to: localhost:3000/projects/sheets/5?something_fun=geeks_are_us will give the following params:
{"something_fun"=>"geeks_are_us", "controller"=>"projects", "action"=>"show", "id"=>"5"}
And if you're looking to render multiple items via a partial, you can pass the assigned variable for (in your case) 'project' to render the views but it is a partial as you appear to be rendering from a view already.
So something like:
<% #projects.each do |project| %>
<%= render partial: project, locals: {project: project} %>
<% end %>
This would try to render projects/_project.html.erb and sending project as a variable. If you need other variables in your view, just pass them in the locals hash.
Hope this is some help.
I have a partial: views/nodes/_node.html.erb, which I render on any view like so:
<%= render #nodes %>
When I render it like that, per the Rails Guides, I can use node_counter within the partial as a counter to keep track of various elements within the partial (or say assign an ID that increments every time the partial is rendered).
Now I want to use this same partial, but not rendered like that but rather like this:
<%= render partial: "nodes/node", locals: {node: event.eventable} %>
When I do that, I get this error:
undefined local variable or method `node_counter' for #<#<Class:0x007fa3b6ca9778>:0x007fa3b58a60c8>
That is because I never specified/passed node_counter as a local variable.
So how do I specify node_counter to start at 0 and always increment every time this partial is rendered - if I can't do it the Rails Way?
For reference, the Rails Guide says this:
Rails also makes a counter variable available within a partial called by the collection, named after the member of the collection followed by _counter. For example, if you're rendering #products, within the partial you can refer to product_counter to tell you how many times the partial has been rendered. This does not work in conjunction with the as: :value option.
In your calling view, you can use each_with_index:
<% #foo.each_with_index do |foo, index| %>
<%= render 'nodes/node', f:foo, node_counter:index %>
Then in your _nodes/node partial, node_counter will increment starting at 0.
The reason that node_counter is not available for you in your second call is that you are calling the partial with a member, not a collection.
In an ERB view, you can call
<%= render #cart.line_items %>
and, assuming you have a partial named _line_item.html.erb in the line_items directory, Rails will take care of the rest.
But I'm having some trouble converting this to something similarly succinct in Haml.
I can get something that works by explicitly calling .each on #cart.line_items or an equivalent local variable in the partial, but calling .each is exactly what I'm trying to avoid.
Here's the partial:
%tr
%td= item.product.title
%td= item.quantity
%td.item_price= number_to_currency(item.total_price)
From what I've read so far, this looks like it should produce the same behavior:
= render 'line_items/line_item', collection: #cart.line_items, as: :item
But it's still not working as expected. item isn't being passed as a local:
undefined local variable or method `item' for #<#<Class:0x007fb3c531aee0>:0x007fb3c3692160>
Does Haml have a comparably succinct way to render collections (relative to ERB)? If so, any thoughts as to what I might be missing? Or if there's a better way to do this altogether?
Thanks.
Try this(mention partial explicitly)
= render :partial => 'line_items/line_item', collection: #cart.line_items, as: :item
The render method and how it handles partials is part of Rails, and should work the same with Erb and Haml.
When using render to automatically render a collection, as in this case with render #cart.line_items, Rails will use the name of the class each entry of the collection to determine both the partial to use and the name of the local variable used in that partial.
In your Erb example Rails is using the partial _line_item.html.erb, which suggests that the objects are of type LineItem and so Rails will create a local named line_item. However in your Haml partial you are using the name item, which isn’t being defined hence the error.
Simply change all occurances of item to line_item in your partial, and you will be able to use
= render #cart.line_items
in your Haml, the same as in Erb.
I want to render some child items with something other than their default partial (i.e., app/views/child_items/_child_item.html.erb). The default one was scaffolded and it isn't great for public viewing of something, but I still want to keep it for back-end management purposes.
This is what I'm going for inside the view of the parent item, assuming a partial defined in app/views/child_items/_alternate_partial.html.erb:
<%= render containing_object.child_items, :partial => 'child_items/alternate_partial' %>
But the child items still render with their default partial.
Try this one:
<%= render 'child_items/alternate_partial', :collection => containing_object.child_items %>