Rails : Named yield not rendering wit partial - ruby-on-rails

I am trying to render a partial using a named yield. Here's my template
<%= render 'shared/remote_modal', modal_title: "bru" do %>
<%= content_for(:modal_content) do %>
<%= render #registrations, show_learner: true, show_product: false %>
<% end %>
<% end %>
and here's shared/remote_modal :
<div class="relative px-4 w-full max-w-6xl md:h-auto">
<!-- Modal content -->
<div class="relative bg-white rounded-lg shadow dark:bg-gray-700">
<!-- Modal header -->
<div class="w-full">
<div class="flex justify-between items-start p-5 rounded-t">
<div class="w-full-0">
<h3 class="text-lg font-semibold text-gray-900 dark:text-white">
<%= modal_title %>
</h3>
</div>
<i class="close-modal fas fa-times text-lg cursor-pointer"></i>
</div>
</div>
<!-- Modal body -->
<div class="px-6">
<div class="w-full">
<%= yield(:modal_content) %>
</div>
</div>
</div>
As you can see shared/remote_modal has yield(:modal_content) and my template uses content_for(:modal_content). However the block within content_for(:modal_content) is not rendering.
If I change it to a "simple" "unnamed" yield though, it will render properly. Are named yield not supported with partials ? Is there a workaround to this ?

A possible issue could be that you're using content_for inside the partial, which might not work as expected.
Instead, you can try a different approach (not sure if that's the same you already tried). Try passing the content as a block (without using content_for), and then render this block inside the partial using a simple yield:
<%= render 'shared/remote_modal', modal_title: "bru" do %>
<%= render #registrations, show_learner: true, show_product: false %>
<% end %>
Partial:
...
<!-- Modal body -->
<div class="px-6">
<div class="w-full">
<%= yield %>
</div>
</div>
...

Related

'nil' is not an ActiveModel-compatible object. It must implement :to_partial_path in rails 7

implementing a <%= render #booking_types %> partial in my home#dashboard view, Why is rails not looking into app/views/booking_types folder for a partial named _booking_type.html.erb and renders it as a looped instance?
app/views/home/dashboard.html.erb
<div class="flex items-center justify-between pb-6 border-b">
<h1 class="font-extrabold text-3xl">Dashboard</h1>
<%= link_to "Create booking type", new_booking_type_path, class: button_class(theme: "primary") %>
</div>
<div class="py-10 grid grid-cols-3 gap-6">
<%= render #booking_types %>
</div>
</div>
the partial
app/views/booking_types/_booking_type.html.erb
<div id="<%= dom_id booking_type %>">
<%= link_to edit_booking_type_path(booking_type), class: "p-6 border shadow-xl rounded-xl block hover:shadow-lg transition ease-in duration-300 relative overflow-hidden" do %>
<div class="h-1 w-full absolute top-0 left-0 right-0" style="background-color: <%= booking_type.color %>">
</div>
<h3 class="font-medium text-2xl"><%= booking_type.name %></h3>
<p class="text-gray-500">View booking page</p>
<p><%= duration(booking_type) %></p>
<% if booking_type.payment_required? %>
<div class="mt-3 pt-3 border-t">
<p>
<strong>Payment required</strong>
</p>
<p>
<strong>Price:</strong>
<%= number_to_currency(booking_type.price) %>
</p>
</div>
<% end %>
<% end %>
</div>
Error Output by better-errors gem after changing rendering partial from <%= render #booking_types %> to this way
<%= render "booking_types/booking_type" %>

How can I use ajax to display Bootstrap 4 modal in Rails 6 app?

Currently I have a modal rendering for each piece on the page. It works but I don't want to render a modal for each piece each time the page is loaded.
Here is the code where my modal is rendered now:
site/gallery.html.erb
<% #pieces.each_slice(3) do |pieces| %>
<div class="row">
<% pieces.each do |piece| %>
<div class="col-lg-4">
<%= image_tag (piece.images.joins(:blob).order('active_storage_blobs.filename ASC').first if piece.images.attached?), data: { toggle: "modal", target: "#modal#{piece.id}" }, class:"img-thumbnail mx-auto d-block img-size" %>
<p><%= piece.name %></p>
<p><%= piece.description %></p>
<%= render 'site/modal', piece: piece %>
</div>
<% end %>
</div>
<% end %>
Here is the modal partial:
site/_modal.html.erb
<div class="modal fade" id="modal<%=piece.id%>" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="modalLabel"><%= piece.name %></h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
//code involving video and images for the piece
</div>
<div class="modal-footer">
<% if piece.quantity == 1 %>
<%= button_to 'Purchase', checkout_create_path, method: :post, params: {id: piece.id}, remote: true, class:"btn btn-dark" %>
<% else %>
<p>SOLD</p>
<% end %>
</div>
</div>
</div>
</div>
What I believe I need to do is add remote: true and pass the piece.id through my image_tag link somehow. I think I would need a modal.js.erb with something along these lines in there
$('modal').html('<%= j render "site/modal", piece: #piece %>');
$('#modal<%=piece.id%>').modal('show');
And then render the modal at the top of the gallery.html.erb page. I'm not quite sure how to go about this though
EDIT
I've made some progress with trying to use AJAX to display the modals.
I've moved my modal into the pieces directory and created a javascript file to go with it.
_piece_modal.html.erb
<div class="modal fade" id="piece-modal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
//modal content here
</div>
</div>
</div>
piece_modal.js.erb
$('body').append('<%= j render "piece_modal", piece: #piece %>');
$('#piece-modal').modal('show');
In my pieces controller
def piece_modal
#piece = Piece.find_by(params[:piece])
end
In my routes
get 'piece_modal' => 'pieces#piece_modal'
And here is the loop I'm using images to link to my modals
<% #pieces.each_slice(3) do |pieces| %>
<div class="row">
<% pieces.each do |piece| %>
<div class="col-lg-4">
<%= link_to piece_modal_path(piece), remote: true do %>
<%= image_tag (piece.images.joins(:blob).order('active_storage_blobs.filename ASC').first if piece.images.attached?), class:"img-thumbnail mx-auto d-block img-size" %>
<% end %>
<p><%= piece.name %></p>
<p><%= piece.description %></p>
</div>
<% end %>
</div>
<% end %>
The modal displays now but it only displays images from the first piece in the loop. How can I get it to display the correct content when I click on different images?
Okay I found a way for the modal to load dynamically with some ajax.
I changed up my link_to like this
<%= link_to piece_modal_path(piece_id: piece.id), remote: true do %>
I made this change in the pieces controller
def piece_modal
#piece = Piece.find(params[:piece_id])
end
And I made this change to my piece_modal.js.erb
$('body').append('<%= j render "piece_modal", piece: #piece %>');
$('#piece-modal').modal('show');
$('#piece-modal').on('hidden.bs.modal', function () {
$(this).remove();
});
So now instead of each piece on the site rendering it's own modal, only one gets rendered when I click on the image of the piece. On hide though I have to remove it from the DOM or else the modal will stay rendered with the properties of the first piece I click on.
You have written your code like:
<%= image_tag (piece.images.joins(:blob).order('active_storage_blobs.filename ASC').first if piece.images.attached?), class:"img-thumbnail mx-auto d-block img-size" %>
But notice that you use .first which will always return the first property.
You could do something like this instead:
<% #pieces.each_slice(3) do |pieces| %>
<div class="row">
<% pieces.each_with_index do |piece, index| %>
<div class="col-lg-4">
<%= link_to piece_modal_path(piece), remote: true do %>
<%= image_tag (piece.images.joins(:blob).order('active_storage_blobs.filename ASC')[index] if piece.images.attached?), class:"img-thumbnail mx-auto d-block img-size" %>
<% end %>
<p><%= piece.name %></p>
<p><%= piece.description %></p>
</div>
<% end %>
</div>
<% end %>
p/s: I'm writing this on the fly and didn't actually test it.

How can I supply data to yield in my rails partial?

I'm trying to render a partial with a certain layout file. But be able to specify unique values for that specific partial. Below are the current files I have, but all that happens is the yield keywords both show the collection value. I'd like to pass a custom "title" and show the collection in the "body".
application/_news_article.html.erb
<!-- application/_news_article.html.erb -->
<% if news_article.report_text.present? %>
<div class="news_article_entry">
<div class="text-box">
<span><%= "#{news_article.published_date.strftime("%D")}" %></span> -
<%= "#{news_article.report_text}" %>
</div>
<% if news_article.impact_text.present? %>
<div class="impact-text" data-toggle="tooltip" data-placement="bottom"
title="<%= news_article.impact_text %>">Analysis</div>
<% end %>
</div>
<hr />
<% end %>
application/_news_articles.html.erb
<!-- application/_news_articles.html.erb -->
<%= render partial: "news_article", collection: articles %>
layouts/_panel_box_scrollable.html.erb
<!-- layouts/_panel_box_scrollable.html.erb -->
<div class="panel panel-default skill-evaluation-box">
<div class="skill-heading">
<div class="row">
<div class="col-xs-12">
<%= "#{yield :title}".upcase %>
</div>
</div>
</div>
<div class="skill-body scrollable">
<%= yield :body %>
</div>
</div>
schools/show.html.erb
<!-- schools/show.html.erb -->
<%= render partial: 'news_articles', layout: "layouts/panel_box_scrollable", locals: { articles: #articles } %>
Yield is where the partial will be rendered. If you want to render a title you need to pass in a title through locals or use a variable potentially on one of your models or set in the controller. In this case if you want to render a title do something like:
<%= render partial: 'news_articles', layout: "layouts/panel_box_scrollable", locals: { articles: #articles, title: 'My Title' } %>
Then in your layout do:
<div class="panel panel-default skill-evaluation-box">
<div class="skill-heading">
<div class="row">
<div class="col-xs-12">
<%= title.upcase %>
</div>
</div>
</div>
<div class="skill-body scrollable">
<%= yield %>
</div>
</div>

Rails 4 - Multiple yield blocks on a partial

Is it possible to have a partial using more than one yield block? I wanted to use it to implement bootstrap modal boxes on my project, kinda like this:
<div class="modal fade" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<%= yield :header %>
</div>
<div class="modal-body">
<%= yield :body %>
</div>
<div class="modal-footer">
<%= yield :footer %>
</div>
</div>
</div>
</div>
And this is more or less how I was thinking of using it
<%= render partial: "shared/modal" do %>
<% content_for :header do %>
...
<% end %> %>
<% content_for :body do %>
...
<% end %> %>
<% content_for :footer do %>
...
<% end %> %>
<% end %>
Is there a way to do this? Is this maybe a bad approach for some reason?
Through much trial and error, I think I solved this in Rails 5 but needed to insert a blank yield in my partial in order to get it to work:
_partial.html.erb
<div class="partial">
<%= yield %> <!--Does not do anything-->
<div class="header">
<%= yield :header %>
</div>
<div class="text">
<%= yield :text %>
</div>
</div>
Implemented as:
full_layout.html.erb
<%= render "partial" do %>
<% content_for :header do %>
<h1>Header content</h1>
<% end %>
<% content_for :text do %>
<p>Text content</p>
<% end %>
<% end %>
I think you have an issue with your render partial. Notice you have all of your content_for blocks within the render partial block.
<%= content_for :thing do %>
Some content
<% end %>
<%= render partial: "blah" %>
It's no problem to use multiple yield blocks in your partial. Only thing is to make sure that many is actually needed. For an example content_for sections are basically placeholders for content that could vary based on the logic of the application. So, it's totally fine to use multiple yields in one page.
You can also just run put an yield there withouth the output. This way you can also use the default block.
<div>
<% yield %>
<div class="mt-3">
<div class="text-2xl tracking-wide font-bold text-gray-900">
heading
<%= yield :heading %>
</div>
</div>
<div class="relative bg-white rounded-xl shadow-xl mb-8 min-h-28">
<%= yield %>
</div>
...

Your AdSense application status: Insufficient content

After posting my adsense code onto my Ruby on Rails app I received this message:
Insufficient content: To be approved for AdSense and show relevant ads on your site, your pages need to have enough text on them for our specialists to review and for our crawler to be able to determine what your pages are about.
The message also included these suggestions (which I think I meet with the possible exception of the 1st one and that's because it's an app not a blog):
Your content should contain complete sentences and paragraphs, not only headlines.
Ensure that your website is fully built and launched before you apply for AdSense - do not apply while your site’s still in a beta or
“under construction” phase or only consists of a website template.
Place the ad code on a live page of your website. It does not have to be the main page, but test pages that are empty except for the
AdSense ad code will not be approved.
Provide a clear navigation system for your visitors so that they can easily find all of the sections and pages of your website.
application.html.erb
<body>
<%= render 'layouts/header' %>
<div class="jumbotron">
<p class="text-center">
<%= yield :jumbotron %> <!-- this variable should be assigned in your controller action-->
</p>
</div>
<% flash.each do |name, msg| %>
<%= content_tag(:div, msg, class: "alert alert-info") %>
<% end %>
<div class="container-fluid">
<div class="container">
<div class="col-md-9">
<%= yield %> # includes pages/home (root route)
</div>
<div class="col-md-3">
<% if current_user.present? %>
<%= render 'layouts/sidebar' %> # includes _recommendations
<% end %>
</div>
</div>
</div>
</body>
_recommendations.html.erb
<div class="recommendations-padding">
<div class="ad">
<p>This is a test to see how the ads will fit here. This is a test to see how the ads will fit here. This is a test to see how the ads will fit here. This is a test to see how the ads will fit here. This is a test to see how the ads will fit here. This is a test to see how the ads will fit here. This is a test to see how the ads will fit here. This is a test to see how the ads will fit here.</p>
</div>
<div class="ad">
<script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<!-- Recommendation 1 -->
<ins class="adsbygoogle"
style="display:block"
data-ad-client="ca-pub-2458646218429910"
data-ad-slot="6447006986"
data-ad-format="auto"></ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>
</div>
<div class="ad">
<script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<!-- Recommendation #2 -->
<ins class="adsbygoogle"
style="display:block"
data-ad-client="ca-pub-2458646218429910"
data-ad-slot="3293344589"
data-ad-format="auto"></ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>
</div>
<div class="ad">
<script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<!-- Recommendation 3 -->
<ins class="adsbygoogle"
style="display:block"
data-ad-client="ca-pub-2458646218429910"
data-ad-slot="9400473387"
data-ad-format="auto"></ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>
</div>
</div>
home.html.erb
<% if logged_in? %>
<% if #user.habits.committed_for_today.any? %>
<div class="page-header">
<%= link_to habits_path(#habits) do %>
<h1><b>Habits</b></h1>
<% end %>
</div>
<div class="add-padding">
<%= render partial: 'habits', locals: {habits: #habits} %>
</div>
<% end %>
<% if #user.valuations.any? %>
<div class="page-header">
<%= link_to valuations_path(#valuations) do %>
<h1><b>Values</b></h1>
<% end %>
</div>
<div class="add-padding">
<%= render #valuations %>
</div>
<% end %>
<% if #user.goals.any? %>
<div class="page-header">
<%= link_to goals_path(#goals) do %>
<h1><b>Goals</b></h1>
<% end %>
</div>
<% end %>
<div class="add-padding">
<% if #user.goals.unaccomplished.any? %>
<%= render #unaccomplished_goals %>
<% end %>
<% if #user.goals.accomplished.any? %>
<div class="gold-standard">
<%= render #accomplished_goals %>
</div>
<% end %>
</div>
<% if #user.quantifieds.any? %>
<div class="page-header">
<%= link_to quantifieds_path(#quantifieds) do %>
<h1><b>Stats</b></h1>
<% end %>
</div>
<% end %>
<div class="add-padding">
<% if #user.quantifieds.averaged.any? %>
<h2><b>Averaged</b></h2>
<%= render #averaged_quantifieds %>
<% end %>
<% if #user.quantifieds.instance.any? %>
<h2><b>Instance</b></h2>
<%= render #instance_quantifieds %>
<% end %>
</div>
Do you have any suggestions on how I can get approved about Adsense?
Thank you!
I got approved to put up google ads via my blog. Once I got approved by google there they let you put ads on any site you own. Score!

Resources