Rails (6.0). View each block element not recognized inside nested partial? - ruby-on-rails

Rails beginner project
In a view that I want to show all results from two different models (MediaLink & MediaCollection)
I have successfully created a two dimensional array #ranked_media that holds
[0] is id from table
[2] is total_points
[5] is class name as a string.
Being that they are pulled from 2 different tables, the id can be repeated twice, but won't have the same class name if id are identical.
In my view (pages/media.html.erb) :
<div class="container">
<% #ranked_media.each do |media| %>
<% if media[5] == 'MediaCollection' %>
<%= render 'media_collection_show' %>
<% else %>
<%= render 'media_link_show' %>
<% end %>
<% end %>
</div>
partial _media_collection_show.html.erb :
<h2 class="text-center mt-4 text-white">
is a MEDIA COLLECTION of class :: <%= #media_collections.class %>
</h2>
partial _media_link_show.html.erb :
<h2 class="text-center mt-4 text-white">
is a MEDIA LINK of class :: <%= #media_links.class %>
</h2>
At this point all is fine. The block is being generated 5 times and applies the output according to the each block. The partials also outputs the class name to make sure they all work.
My Problem
However, I can add this to the view (3rd line is the change) :
<div class="container">
<% #ranked_media.each do |media| %>
<%= media %>
<% if media[5] == 'MediaCollection' %>
<%= render 'media_collection_show' %>
<% else %>
<%= render 'media_link_show' %>
<% end %>
<% end %>
</div>
And it outputs media object.
But if try that in any of the partials like this :
<h2 class="text-center mt-4 text-white">
is a MEDIA LINK of class :: <%= #media_links.class %>
<%= media %>
</h2>
I get NameError in Pages#media
undefined local variable or method `media'
How can I access the media block element inside these two partials?

By sending in local variables to the partials: <%= render 'media_link_show', media: media %>. In the partial you'd access it like so:
<h2 class="text-center mt-4 text-white">
is a MEDIA Object of class :: <%= media.class %>
</h2>
Note the lack of #; in general it's bad form to access instance
variables in partials.
Your third line (<%= media %>) also does nothing for the functionality, and can safely be removed.
Edit: When a controller does #items = ... in an action, it sets #items as an instance variable; any view rendered from that action has access to that value, which is why your #ranked_media can be looped over.
Partials are meant to be re-used, and not necessarily by the same view/controller, so if a partial accesses an instance variable, like your _media_collection_show.html.erb does, then any view/controller that uses that partial will need to set the #media_collections variable.
To avoid this (a controller action should strive to only set one instance variable), you can instead inject local variables into a partial: <%= render "partial_name", items: #items %>. Here, we're setting the local variable items to be the value of #items. By doing this, any view that uses the partial can send in their own items into the partial, without the need for the controller to set a "magical variable" #items. You could, for example, do: <%= render "partial_name", items: [1, 2, 3] %>. You've decoupled the partial from the controller.

Related

Passing a Rails controller defined local variable into a Turbo Frame Tag

I am a super newbie to rails but I am defining a local variable (a css class) and passing it to this partial
render(partial: 'calendar_inventory', locals:{klass: params[:select]})
Inside my partial I have a pagination occurring:
<div class="grid-container" data-calendar-target="grid" data-action= "scroll->calendar#populateHeader">
<%= turbo_frame_tag "paginate_page_#{#sub_orders.current_page}" do %>
<%#sub_orders.each do |sub| %>
<%="klass:"+klass%>
<%end%>
<% if #sub_orders.next_page %>
<%= turbo_frame_tag "paginate_page_#{#sub_orders.next_page}", src: filter_supplier_calendars_path(page: #sub_orders.next_page), loading: 'lazy' do %>
Loading...
<% end %>
<%end%>
</div>
<% end %>
<%end%>
Trying to paginate some orders here, the initial loading of the klass is found however when I paginate is does not keep the value of klass and therefore doesn't display anything.
I've tried adding locals:{klass: params[:select]} to where the next_page is being appended but it just adds a data-variable of locals="klass" inside the tag itself
Any ideas on how I can pass this klass variable into the turbo frame?

Strange output from rails each do

Rails each do method is acting strangely and I do not know why.
controller
def index
#fabric_guides = FabricGuide.with_attached_image.all.order(:name)
end
index.html.erb
<div class="guide-items">
<%= #fabric_guides.each do |fabric| %>
<div class="guide-container">
<%= link_to fabric_guide_path(slug: fabric.slug) do %>
<%= image_tag fabric.image if fabric.image.attached? %>
<% end %>
<div class="guide-info">
<p class="g-name">
<%= link_to fabric.name,
fabric_guide_path(slug: fabric.slug) %>
</p>
</div>
</div>
<% end %>
</div>
I have two FabricGuide records so I expect two "guide-container" but I get three. Or more precisely I get two guide containers and a third block of text containing all the content from the last FabricGuide record.
I have almost an identical setup for articles and have never encountered this problem. I'd happily share more information if needed. Thank you!
Please remove = equal sign from your each loop of view code
like below :-
<% #fabric_guides.each do |fabric| %>
...
...
<% end %>
you have used this <%= #fabric_guides.each do |fabric| %> in your view that's why it shows all record in DOM.
The expression for erb tags is <% %>
now if we want to print that tag too then we apply <%= %>

Rails: Rendering a partial in a loop results in undefined variable

I'm having trouble with attempting to render a partial within a loop. Essentially, I have an app where events are created, people join the event, and for each event, attendees have a list of items they will bring which they can select from their own inventory of items.
In my show.html.erb for Events:
<% #event.attendees.each do |user| %>
<div class="col-md-4">
<h4><%= user.first_name %> <%= user.last_name %></h4>
<% if user.event_items.any? %>
<div class="event-item-list">
<% user.event_items.each do |eventitem| %>
<div class="event-item-div" >
<p class="event-item-title"><%= eventitem.item.title %></p>
</div>
<% end %>
<% end %>
</div>
<% if user == current_user %>
<%= render 'event_items/form' %>
<% end %>
</div>
<% end %>
This works and shows the title of each event item that is added to the list.
However, if I want to move the content of the P tag to a partial, I get "undefined local variable or method `eventitem'". Which doesn't make sense to me since I would assume that whatever is passed in as a partial in that loop would be treated the same as if I just left that P tag content in there. At this point, all I have in the partial would be:
<p class="event-item-title><%= eventitem.item.title %><p>
Any insight would be appreciated.
Partials don't inherit local variables automagically, you have to define them. According to Rails Guides to pass local variables to a partial you need to set them in the locals hash
<%= render 'event_items/form', locals: {eventitem: eventitem} %>

Find all entities in database and show them if they exist, gives error: no block given yield

How to make this code work?
<%= articles= Article.find_each
if articles
a.each do |a| %>
****some html****
<% end %>
<% end %>
right now it gives me an error:
no block given (yield)
It's hard to tell because your code is such a mess but i think you are trying to do this:
<% Article.all.each do |article| %>
<!-- some html - reference the local variable `article` in here, inside erb tags, eg -->
<div>
<%= article.name %>
</div>
<% end %>
EDIT: the above code will work fine (by which i mean happily generate no html at all) if there are no Article records in the db. Sometimes in this situation you might want to display some sort of extra info, like "You haven't created any Articles yet" or something. if this is the case you could do something like this:
<!-- typically this variable would be defined in the controller -->
<% #articles = Article.all %>
<% if #articles.blank? %>
<p>You haven't created any Articles yet</p>
<% else %>
<% Article.all.each do |article| %>
<!-- some html - reference the local variable `article` in here, inside erb tags, eg -->
<div>
<%= article.name %>
</div>
<% end %>
<% end %>

Rails - Passing an option variable in a partial

I'm building a header partial for a view. I call the partial as following:
<%= render :partial =>"project/header", :locals => {:right_header => 'BLAH BLAH'} %>
The header has a default right_header, but I'd like the option to overwrite it:
<div id="header">
<span class="right">
Standard Header here
</span>
</div>
The deal is when calling the partial, right_header won't always be defined, I'd like for it to be optional, but that's where I'm struggling and rails keeps erroring... In the partial I've been trying:
<% if right_header.empty? %>
default header....
<% else %>
<%= right_header %>
<% end %>
Suggestions? Am I passing this correctly to the partial with locals?
Thank you
use
if defined? right_header
another way is
right_header ||= 'default'
in the view. so if right_header is not passed in, its value will be default. You can pass in any value too, and later on just do things according to the value of right_header.

Resources