Render partials inside loop in Rails 5 - ruby-on-rails

Question: How do I make a partial (that has to be generic) loop through different variables?
I have a tabbed page where I want to use a partial to avoid duplicating my HTML. The tabs are "Videos" and "Articles". It's the exact same HTML but I want to iterate through #videos for videos and #articles for articles.
The idea was to make the product partial completely generic and then somehow pass in #videos or #articles that I want to iterate through.
Partial: _product.html.slim
.col-md-5
.thumbnail
.thumb.spacer-sm
- if product.image.blank?
iframe allowfullscreen="" frameborder="0" mozallowfullscreen="" src="https://player.vimeo.com/product/#{product.vimeo_id}" webkitallowfullscreen=""
- elsif product.vimeo_id.blank?
= image_tag(product.image.url,
class: 'img img-responsive img-rounded')
.caption
.content-group-sm.media
.media-body
h6.text-semibold.no-margin
= product.name
small.text-muted
| by
= product.user.name
- unless product.price.blank?
h6.text-success.media-right.no-margin-bottom.text-semibold
| $
= product.price
= product.description
.panel-footer.panel-footer-transparent
.heading-elements
ul.list-inline.list-inline-separate.heading-text
li
= link_to 'Delete', product_path(product), method: :delete
li
= link_to 'Edit', edit_product_path(product)
HTML view rendering the partial:
.page-container.spacer-minus
.page-content
.row
.col-md-4
.sidebar-default.sidebar-separate
.sidebar-content
.content-group
.panel.no-border-radius-top
ul.navigation
li.navigation-header Navigation
li.active
a data-toggle="tab" href="#videos"
i.icon-video-camera2
| Videos
li
a data-toggle="tab" href="#articles"
i.icon-graduation
| Articles
.col-md-8
.tab-content
#videos.tab-pane.fade.in.active
.row
- #videos.each do |product|
= render 'shared/product'
#articles.tab-pane.fade
.row
- #articles.each do |product|
= render 'shared/product'
I just need my loop to understand what variable I want to iterate through. I cannot include #video or #article in the partial since that will defeat the purpose of having a generic partial.
With this implementation, I get the error:
undefined local variable or method `product' for #<#<Class:0x007fc58053ae60>:0x007fc58884ea68>

Try this code:
#videos.tab-pane.fade.in.active .row -
#videos.each do |video|
= render 'shared/product', product: video
#articles.tab-pane.fade .row -
#articles.each do |article|
= render 'shared/product', product: article

Hi this is pretty stuff if you want articles to come after the videos then try this.
= render partial: "product", collection: #videos
= render partial: "product", collection: #articles
this will remove the loop from your main view but in your case you are not using locals try this
.row
- #videos.each do |video|
= render 'shared/product', locals: {product: video}
.row
- #articles.each do |article|
= render 'shared/product' , locals: {product: article}
It will work.

Related

Rails partial rendering twice on changing the URL

I m new to RoR and i recently figured out that if I change the part of URL from the address bar it is just rendering the partial twice below I m illustrating the same.
So my url is localhost:3000/admin/exp_app/10 so if i refresh this page it gets rendered one time but if i change the url to localhost:3000/admin/exp_app/11 the same request gets twice to controller and it is rendering the partial two times .
Can someone help me?
Below i m attaching the part of code.
exp_controller.rb
def show
authorize! :sales, current_user
#filter = params[:filter] || 'all'
#filter_by = params[:filter_by] || 'all'
#analytics_filter = params[:analytics_filter] || 'all'
#uw = params[:uw_id]
#entity = params[:entity]
#leo_no_brc = params[:leo_no_brc].present?
#exporter_application = User.exp_leads_applications.find(params[:id]) rescue nil
user = User.find(params[:id]) if #exporter_application.nil? || can?(:mexico_sales, current_user)
#total_ltm = #exporter_application.shipment_volume_last_year(nil, false).to_i
#exp_clients = #exporter_application.clients
#exp_applications_clients = #exp_clients.where(status: Client::CLIENT_STATUS_ORDER).group_by(&:status)
#exp_task_instances = #exporter_application.task_instances.where(client_id: nil)
#exporter_application = User.exp_leads_applications.includes(:iec, :contacts,
interactions: [:replies],
task_instances: { interactions: [:replies] },
application: { exporter_user: [:iec] })
end
show.html.erb
<% if params[:_tpl] %>
<div class="admin-section tabpanel row">
<%= render partial: params[:_tpl], locals: { instance: #exporter_application } %>
</div>
<% else %>
<%= render 'admin/header' %>
<%= render partial: 'admin/exporter_applications/show' %>
<%= render 'admin/footer' %>
<% end %>
It is guranteed that this url is not called in partial again admin/exporter_applications/show
Thanks in advance!

Rails Locals - Passing Connected Model Data

My model structure is pretty solid. I have MarketingDeliverySystem has_many MarketingSections. MarketingSections has_many MarketingVideos.
I have another segment: GroupDevelopment has_many GroupSections. GroupSections has_many GroupVideos.
I'm trying to use a partial to pass the variables, thus DRYing it all up.
I have the following that I'm trying to pass to the partial:
= render partial: '/sales_presentations/sales_presentation',
locals: { marketing_delivery_system: #marketing_delivery_system,
first_video: first_marketing_video(#marketing_delivery_system),
sales_presentation: #marketing_delivery_system}
Then in the partial I have the following:
.rounded-box-header.blue-bg #{sales_presentation.title}
ul
- sales_presentation.sections.ordered.each_with_index do |section, index|
- list_class = 'section show'
- list_class = 'section hide' if index != 0
li
= link_to section.title, '#', class: 'section', data: { id: section.id }
ul class="#{list_class}" data-section-id="#{section.id}"
- section.videos.ordered.each do |video|
li.video
= link_to video.title, '#',
class: 'video video-link',
data: { video: video.youtube_link,
sales_presentation: sales_presentation.title.parameterize }
.seven.columns
.row
div id="#{sales_presentation.title.parameterize}-container"
video {
id="#{sales_presentation.title.parameterize}-video-player"
class="video-js vjs-default-skin videos"
height=400
poster=""
controls preload='none'
data-default-url="#{first_video(sales_presentation)&.youtube_link}"
I previously had issues with sales_presentation.title at the top until I updated the locals.
My question/issue is how do I pass in through the locals to use for sales_presentation.sections instead to use #marketing_delivery_system.marketing.sections?
I thought I could just put that in through locals:
sales_presentation.sections: #marketing_delivery_system.marketing_sections but I end up with a massive syntax error.
I've also tried creating a partial view for these two and then changed sales_presentation throughout the view to mod. Then changed mod.sections to mod_section and setting that in the locals to mod_section: #marketing_delivery_system.marketing_section. The problem then gets into that I end up needing to hit video later in the iteration. So then that has the same issue.
You misunderstand the meaning of locals in partials.
Says we have
<%= render partial: 'image', locals: {size: #image.size, extension: #image.extension} %>
It means that in image partial now we can use local variable size and extension (keys) as #image.size and #image.extension (values).
Put in locals: {} all local variables you want.
So you can't write in locals sales_presentation.sections: #marketing_delivery_system.marketing.sections
But you can sales_presentation_sections: #marketing_delivery_system.marketing.section
Also you have problem with this code:
locals: { marketing_delivery_system: #marketing_delivery_system,
first_video: first_marketing_video(#marketing_delivery_system),
sales_presentation: #marketing_delivery_system }
marketing_delivery_system and sales_presentation will be with the same value.

Nested render partials in Rails3 with HAML

I am attempting the following
A HAML template with
#whitepanelMID
#groups_view_scroller
= render 'show' do
= render 'short_field', locals: {label: 'Name:', value: #group.name}
= render 'short_field', locals: {label: 'Description:', value: #group.description}
And the partials are _show.html.haml (note the use of yield)
%table#vert_table.no_borders{ cellpadding: '0', cellspacing: '0'}
%tbody
%tr
%td{ cols: 2 } My table
= yield
and _short_field.html.haml
%tr
%th.vert_table_heads= label
%td= value
The issue is that yield does not seem to work.
What's the proper way to use block in render in HAML?
Update
I found a workaround, which I don't like.
In the HAML template capture the output like
#whitepanelMID
#groups_view_scroller
- rows = capture_haml do
= render partial: 'short_field', locals: {field_label: 'Name:', value: #group.name}
= render partial: 'short_field', locals: {field_label: 'Site:', value: #group.site.description}
= render partial: 'show', locals:{ content: rows}
%br/
with the modified partial _show.html.haml with a content variable instead of yield
%table#vert_table.no_borders{ cellpadding: '0', cellspacing: '0'}
%tbody
%tr
%td{ cols: 2 } My table
!= content
Happy to hear a better approach!
Just because the link provided by #vidaca is ERB, I want to post an equivalent for HAML.
Use layout: when using the wrapper template
#whitepanelMID
#groups_view_scroller
= render layout: 'show', locals:{ table_title: 'My table'}
= render partial: 'short_field', locals: {field_label: 'Name:', value: #group.name}
= render partial: 'short_field', locals: {field_label: 'Site:', value: #group.site.desccription }
%br/
and _show.html.haml partial (wrapper) like
%table#vert_table.no_borders{ cellpadding: '0', cellspacing: '0'}
%tbody
%tr
%td{ cols: 2 }= table_title
= yield
the wrapped partials (short_field in this case) work as-is.
Hope helps someone.

Rails: passing an instance variable to different controller through a partial

In Category view I have:
<ul>
<% #category.subcategories.each do |subcategory| %>
<li>
<h6>
<%if subcategory.has_topic_headings? %>
<%= link_to subcategory.name, { controller: 'subcategories',
action: 'show_topic_headings',
category_id: subcategory.category_id,
id: subcategory.id
}, data: 'topic_heading_link',
remote: true %>
<% else %>
<%= link_to subcategory.name, subcategory %>
<% end %>
</h6>
<hr>
</li>
<% end %>
</ul>
In application.js:
/* slides in the subcategory menu or the content */
$('.category-menu a').on(
'click',
function(e) {
if ($(this).attr('data')) {
/* make submenu visible */
$('.stretched.nav.row > .slider').animate({left:'-62.5em'});
e.preventDefault();
}
else {
/* make content visible */
$('.stretched.main.row > .slider').animate({left:'-62.5em'});
e.preventDefault();
}
}
);
In subcategories_controller.rb
def show_topic_headings
respond_to :js
#subcategory = Subcategory.find(params[:id])
end
And in subcategories/show_topic_heading I have:
$('.subcategory-menu').html( "<%= escape_javascript( render( partial: "layouts/topic_headings", locals: { subcategory: #subcategory} ) ) %>" );
Clicking on the active link, .subcategory-menu should be populated with the correct content and the div containing should slide in. But the content only appears if it's static (for example, if I put a string instead of a reference to #subcategory). Please note that the view in which I am inserting the subcategory partial is a category view.
The problem lies in the subcategories_controller:
respond_to, not the function itself, generates the partial. Therefore the instance variable needs to be declared before calling respond_to
def show_topic_headings
#subcategory = Subcategory.find(params[:id])
respond_to :js
end

Pass variable to a Fancybox in Rails with Content

I have this link in Rails:
<%= link_to "Add to Journal", add_post_journal_path(post), :method => :put %>
However I want transform this link to show a fancybox with the content listing my content to choose. First, I use this code:
<%= link_to "fancy", "#add_post", :class=>"fancybox" %>
but I have errors, because I want pass the actual post to fancybox, so I'm using this code: in add_post.html.erb:
<h1>Escolha o Jornal que deseja adicionar:</h1>
<ul>
<% current_user.journals.each do |journal| %>
<li><%= link_to journal.name,add_post_complete_journal_path(journal),:remote=>true %> </li>
<% end %>
</ul>
and my controller is:
def add_post
#journal_post = JournalsPosts.new
session[:post_add] = params[:id]
end
def add_post_complete
#journal_post = JournalsPosts.create(:post_id => session[:post_add],:journal_id => params[:id])
respond_with #journal_post
end
How can I transform this code to use my content in my fancybox?
Add on your action add_post the next respond with js:
def add_post
#journal_post = JournalsPosts.new
session[:post_add] = params[:id]
respond_to do |format|
format.js
end
end
Add on a file on your views add_post.js.erb with the next content:
$.fancybox('<%= escape_javascript(render(:partial => 'path_to/add_post'))%>',
{
openEffect: "fade",
closeEffect: "fade",
autoSize: true,
minWidth: 480,
scrolling: 'auto',
});
For example, you have add a partial _add_post.html.erb on your views. Now inside this partial you can write your code view:
#code for your view inside partial `add_post.html.erb`
<%= #journal_post %>
<h1>Escolha o Jornal que deseja adicionar:</h1>
<ul>
.
.
Regards!

Resources