Render a collection of forms using partial - ruby-on-rails

Rails has this pretty way to render a collection using partial
<%= render partial: 'erb_partials/post', collection: #users, as: :user %>
How can I apply this in my loop of forms?
<%= profile_form.fields_for :item_groups, #item_groups do |item_form| %>
<%=render partial: 'item_groups/item_group', locals: {item_form: item_form}%>
<% end %>
<%=profile_form.submit%>

In your case you can't use the render partial: 'path', collection: #list method.
If you unfold your first example:
<%= render partial: 'erb_partials/post', collection: #users, as: :user %>
You get:
<% #users.each do |user| %>
<%= render 'erb_partials/post', user: user %>
<% end %>
The above is such a common action that the render method included the :partial option to wrap the render call in an each loop. render doesn't include any other iteration wrapper options at this moment.

Related

Rendering partial for nested object not processing object nor locals

An enumeration of objects, has nested objects. The goal is to render a partial for futher nested objects
<% groups.each do |group| %>
<% group.children.each do |child| %>
<% if child.lessons.size > 0 %>
<% render 'child_partial' %>
<% end %>
<% end %>
<% end %>
When the partial is defined as as per the Rails guides
<% render 'child_partial', locals: {child: child} %>
or
<% render 'child_partial', object: child %>
error undefined local variable or method 'child' for #<ActionView::Base is returned when the partial calls (for testing purposes) <%= child.class %>
How can I pass the object to the partial so that it may be processed properly?
You just need to follow the guides literally:
<%= render partial: 'child_partial', locals: {child: child} %> # or
<%= render 'child_partial', child: child %>
And it's better to render with collections for performance:
<% groups.each do |group| %>
<%= render partial: 'child_partial',
collections: group.children.select { |child| child.lessons.size > 0 },
as: :child %>
<% end %>
render will not accept additional local variables for the partial, you need to use render partial: as following for that:
<% render partial: 'child_partial', locals: {child: child} %>

Rails: How to use same partial file for one to many relationship?

For the normal situation. Different views can use the same partial like this
<h1>New zone</h1>
<%= render partial: "form", locals: {zones: #zones} %>
<h1>Editing zone</h1>
<%= render partial: "form", locals: {zones: #zones} %>
<% zones.each do |zone| %>
<%= zone.location%>
<% end %>
But my situation is a bit different, the origin code like this
one belongs_to two #one = One.all
one.html.erb
<%= render partial: "one",locals:{one: #one} %>
_one.html.erb
<% one.each do |n|%>
<%= n.location%>
<% end %>
two has_many one #two = Two.all
two.html.erb
<%= render partial: "two", #two %>
_two.html.erb
<% #two.each do |one|%>
<% one.each do |n|%>
<%= n.location %>
<% end %>
<% end %>
For this situation, how can I code render for two.html.erb if I want one.html.erb and two.html.erb use the same partial _one.html.erb ?
this one is definitely incorrect, but how to correct this?
two.html.erb
<%= render partial: "one/one", locals: {one: #two} %>
========================update============================
I think the basic of question is whether we can use the same partial for an object and at the same time for a collection.

Updating partial after submit

On my comments show page I am loading a partial called '_links' and the form to add a new link like this.
comments/show.html.erb
<%= render :partial => 'comments/newlink', locals: {question:question} %>
<%= render :partial => 'links/form', locals: {question:question} %>
comments/_newlink
<% question.links.each do |link| %>
<%= link.body %>
<% end %>
The form looks like this.
links/_form.html.erb
<%= simple_form_for [question, Link.new] do |f| %>
<%= f.input :body %>
<%= f.button :submit, class: "button" %>
<% end %>
I then have a file 'link.js.erb':
comments/link.js.erb
$('.button').append('<%= j (render :partial => 'comments/newlink') %>');
What I am trying to do is update the _links partial using jquery after someone clicks the submit button but it's not quite working. I believe the jquery is correct and it's a rails issue with where I placed the partials.
There are couple of things which you are missing
a. You need to submit your form by ajax so use remote: true option. Your form should be like this:
<%= simple_form_for [question, Link.new], remote: true do |f| %>
<%= f.input :body %>
<%= f.button :submit, class: "button" %>
<% end %>
b. Your form will send a request to create method in your links controller so your method should be like this:
def create
#link = Link.new(link_params)
#question = Question.find(params[:question_id])
respond_to do |format|
if #link.save
format.js # this will look for a file names create.js.erb in views/links directory
else
render "new"
end
end
c. Render your partial and pass locals to it in create.js.erb:
$('.button').append("<%= j (render :partial => 'comments/newlink', locals: {question: #question}) %>"); #notice using double qoutes not single
For details you should checkout Working with Javascript in Rails
Update:
<div id="link">
<%= render :partial => 'comments/newlink', locals: {question:question} %>
</div>
<div id="link-form">
<%= render :partial => 'links/form', locals: {question:question} %>
</div>
and then to update your partials use this js in create.js.erb
$('#link').html("<%= j (render :partial => 'comments/newlink', locals: {question: #question}) %>"); #notice using double qoutes not single
$('#link-form').html("<%= j (render :partial => 'links/form', locals: {question: #question}) %>"); #notice using double qoutes not single

passing variable to simple form symbol

this is my _form_item partial in which I used symbol :order_item
<%= simple_form_for :order_item do |f| %>
.....
<% end %>
here is my view in which I want to render that partial:
<%= content_tag_for :tr , #order.order_items do |i| %>
<div class="hide">
<%= render :partial => "form_item" %>
</div>
<% end %>
How can I pass "i" object to :order_item?
UPDATE:
I prefer to keep it ":order_item" instead of changing it to something like "foo".
You should have:
<%= render partial: 'form_item', locals: {order_item: i} %>
or a shorthand:
<%= render 'form_item', order_item: i %>
And in your form_item partial you should have:
<%= simple_form_for order_item do |f| %>
...
Just do
<%= simple_form_for item do |f| %>
.
.
<% end %>
and render the partial via
<%= render :partial => 'form_item', :locals => { :item => i } %>
You can pass i as a locals to the partial like follows:
<%= render :partial => "form_item", :i => i %>
and you'll have i available in the _form_item partial.
Update:
Local variables passed to partials are variables and not symbols. You could keep the name order_item like follows:
<%= render :partial => "form_item", :order_item => i %>
And update your order_item partial as follows:
<%= simple_form_for order_item do |f| %>
.....
<% end %>
I think I understand why you do not want to change :order_item to just order_item. I think you are going to have to update your other calls to pass in local variable order_item where ever you are making a call to this partial.

Pass a variable into a partial, rails 3?

I have a loop like such:
<% #posts.each do |post| %>
<% render middle %>
<% end %>
Then in my middle partial, how do I access the current post?
Try this:
<% #posts.each do |post| %>
<%= render 'middle', :post => post %>
<% end %>
Like this you'll have a local variable post available within the partial.
Give it to the partial as a local variable
<%= render :partial => 'middle', :locals => { :post => post } %>
Of course, rails also has a shortcut for rendering collections:
<%= render :partial => 'post', :collection => #posts %>
In this case it will call the partial post for every post with a local variable 'post'
You can even render a spacer template between each post:
<%= render :partial => 'post', :collection => #posts, :spacer_template => 'post_divider' %>
<% #posts.each do |post| %>
<% render middle, :post => post %>
<% end %>
You can now access post as the local variable post in the partial
Replace <%= render middle %> with <%= render middle, :post => post %>. Then in your middle partial, you can access the post variable.
You can replace the entire each block with this:
<%= render partial: "product", collection: #posts %>
Or even shorter:
<%= render #posts %>
Full documentation (section 3.2)
https://guides.rubyonrails.org/action_view_overview.html

Resources