Using same partial but with different variable for loop Rails - ruby-on-rails

I want to use the same partial, but changing the main variable of the loop inside the partial so that the layout is the same, but different results show in each tab. I thought I could make this happen using locals, but I tried it with no luck. Any ideas?
<div class="tab-content" id="pills-tabContent">
<div class="tab-pane fade show active" id="pills-home" role="tabpanel" aria-labelledby="campaigns-active-tab">
<%= render partial: 'campaigns_list' %>
</div>
<div class="tab-pane fade" id="pills-profile" role="tabpanel" aria-labelledby="campaigns-inactive-tab">
<%= render partial: 'campaigns_list' %>
</div>
</div>
Controller:
#active_campaigns = #campaigns.where(status: 1).order(created_at: :desc)
#inactive_campaigns = #campaigns.where(status: 2).order(created_at: :desc)
Partial:
Here, the variable should change from active to inactive campaigns:
<% #campaigns.each do |campaign| %>
<tr scope="row d-flex align-items-center justify-content-center">

I thought I could make this happen with locals
Yes you can; however, the code you provided does not use locals.
Local usage would be:
<%= render partial: 'campaigns_list', locals: { campaigns: #active_campaigns } %>
And you can thus loop through campaigns within the partial.
Docs for locals

Related

Using layout with content_for/yield when rendering collection partial

I'm trying to reuse a card layout throughout my app for various collections. I was hoping I could do this with content_for and yield, as described in the rendering guide, and my exact use case is described here. But I'm not able to get the content from the partial inserted into the layout. Here's the setup for rendering a collection of 'entities':
The view (index.html.erb):
<%= render partial: 'entity', collection: #entities, layout: 'card' %>
The partial (_entity.html.erb):
<% content_for(:left_icon) do %>
<i class="fas fa-city fa-2x"></i>
<% end %>
The card layout (_card.html.erb) uses yield to retrieve content specific to the collection (like a certain left-icon as in this snippet)
<div class="card">
<div class="card-body d-flex">
<%= yield :left_icon %>
</div>
</div>
But only an empty line is rendered where the icon should be:
<div class="card">
<div class="card-body d-flex">
</div>
</div>
What do I need to do to be able to render the card with content?

(Ruby on Rails) Pass array in partial as collection

I have a function:
def self.get_component(component_name, properties{})
render :partial => component_name :collection => properties{}
end
That is meant to render a partial from the argument 'component_name' and then pass the array of properties for said component via a collection.
I have a class calling said method with
get_component('members_card/display', properties{member_name => "Jason"})
Which I haven't actually checked yet, but i've been told I don't actually have to explicitly set the data in the array. I finally have the partial:
<div class="members-card">
<div class="container">
<div class="card">
<img class="card__profile" alt="display name" src="">
<div class="card__details">
<h4 class="card__title"> <%= ??? %> </h4>
</div>
</div>
</div>
</div>
But I don't have a clue how to actually call the data in the array i've set as a collection for the partial, so that i could populate the name.
I see things such as #properties or properties.member_name, would one of these be the correct solution, and if so, why?
Use something like:
properties = ['a','b','c']
render partial: 'my_partial', locals: {
my_collection: properties
}
Then in my_partial.html.erb:
<% my_collection.each do |collection| %>
...
<% end %>

Rails - conditional display of html block

On my views I use 1 form that includes a block that renders comments. I do not want to run it when creating a new record. So, I tried conditions like so...
<% unless #annotation_id.nil? %>
<hr>
<div class="row">
<div class="col-md-8">
<h4>Comments</h4>
<%= render #annotation.comments %>
</div>
<div class="col-md-4">
<%= render 'comments/form' %>
</div>
</div>
<% end %>
This however results in never displaying the block - also when the annotation record exists. What am I doing wrong?
You don't show that you have actually set #annotation_id to something.
A simpler way might be to use the .new_record? method instead, like:
<% unless #annotation.new_record? %>
...
<% end %>
use if #annotation.persisted? or unless #annotation.new_record?

HTML Snippets that repeat in the Rails views

I am using a bootstrapping framework, that has the following snippet, which I use a lot:
<div class="panel panel-default">
<div class="panel-heading">...</div>
<div class="panel-body">
...
</div>
</div>
(The snippet will be actually bigger, but I want to start small)
So I thought I would build a partial and use it, something like this:
Partial
<div class="panel panel-default">
<div class="panel-heading"><%= title %></div>
<div class="panel-body">
<%= yield %>
</div>
</div>
Use example
<%= render partial: "panel", locals: { title: "Hello" } do %>
Testing
<% end %>
But this apparently is not working. I get the following error:
'nil' is not an ActiveModel-compatible object. It must implement :to_partial_path.
Am I doing something wrong here? Did I understood partials wrong?
In order for yield to work I think you need to use render :layout instead of/in addition to :partial:
<%= render layout: "panel", locals: { title: "Hello" } do %>
Testing
<% end %>
Have a read of the PartialRenderer examples for more information

Rendering across tabs

I am using Bootstrap in my rails app and in particular, I would like to extend Bootstrap's tabbable functionality in the following sense:
Each user of my site can have multiple profiles, namely model User has_many profiles, and I would like to display these profiles across tabs in their user/show page. Each profile has a name attribute which I want to display on the tab itself.
I was previously rendering these profiles using the typical conventions:
On user/show page:
<%= render 'shared/prof %>
shared/_prof:
<% if #prof_items.any? %>
<ol class="profiles">
<%= render partial: 'shared/prof_item', collection: #prof_items %>
</ol>
<%= will_paginate #prof_items %>
<% end %>
shared/_prof_items
<li id="<%= prof_item.id %>">
...content...
</li>
users_controller:
...
def show
#user = User.find(params[:id])
#profiles = #user.profiles.paginate(page: params[:page])
#profile = #user.profiles.build
#prof_items = #user.prof.paginate(page: params[:page])
...
end
...
So essentially I would like the outputted html to be like this:
<div class="tabbable" style="margin-bottom: 5px;">
<ul class="nav nav-tabs" id="tabHeaders">
<li class="active">
Name of first profile
</li>
<li>
Name of second profile
</li>
#and so on for each prof_item
</ul>
<div class="tab-content" id="tabContent">
<div class="tab-pane active id="<%=prof_item.id%>">
#render first profile item
</div>
<div class="tab-pane" id="<%=prof_item.id%>">
#render second profile item
</div>
</div>
However I'm not sure what code I need in user/show.html.erb, what code I need in shared/_prof_item.html.erb, and what code I need in shared/_prof.html.erb.
You can simplify your code by using rails facility to render collections:
<%= render partial: 'shared/prof_item', collection: #prof_items) %>
<%= render partial: 'shared/profile', collection: #profiles) %>
shared/_profile.html.erb: # use local variable profile
<div class="tab-pane active" id="<%=profile.id%>">
#render first profile
</div>
shared/_prof_item.html.erb # use local variable prof_item
<li>
Name of second profile item
</li>

Resources