How to pass an instance variable into a view partial? - ruby-on-rails

Right now I have a loop that contains code I do not wish to repeat for each instance variable. I wish to put this in a partial and reuse it by changing the #new_posts instance variable, so I can use the same template for #featured_posts and #recommended_posts that I have defined.
I'm thinking of something like this:
<%= render "posts", posts: #featured_posts %>
An example of a loop that I wish to store in a partial
<% #new_posts.each do |post| %>
<div class="col-sm-4">
<div class="thumbnail">
<img src="#">
<div class="caption">
<h4><%= link_to post.title, post %></h4>
<%= post.text.truncate_words(60, omission: '...') %>
Button
</div>
</div>
</div>
<% end %>
How should I approach this? Thanks for your help!

Assign whatever variable you want to posts
<%= render "posts", posts: #featured_posts %>
And now loop over posts in the partial. You will have #featured_posts in posts variable now
<% posts.each do |post| %>
<div class="col-sm-4">
<div class="thumbnail">
<img src="#">
<div class="caption">
<h4><%= link_to post.title, post %></h4>
<%= post.text.truncate_words(60, omission: '...') %>
Button
</div>
</div>
</div>
<% end %>
For #recommended_posts render the same partial but pass #recommended_posts to posts
<%= render "posts", posts: #recommended_posts %>

Related

How to group and dry common view code in Rails

I have two models Episode and Playlist with the following two views:
For Episode:
<div class="name">
<%= link_to episode.name, episode_path(episode) %>
</div>
<div class="description">
<%= link_to episode.description episode_path(episode) %>
</div>
For Playlist:
<div class="name">
<%= link_to playlist.name, playlist_path(playlist) %>
</div>
<div class="description">
<span>Some special span</span>
<%= raw(playlist.description) %>
</div>
The common things between this two views are the
<div class="name">. <div class="description">
but the content of this two divss is different for each view.
Question: How could I extract this two common divs into another view, called _section?
What have I tried:
Cells -> they give me a nice view model with properties, but I could not find a way to added additional HTML elements between the places where the properties will be put.
Yield and Content_for-> I have tried to create a separate _section layout with:
_section.html.erb
<div class="name">
<%= yield :name %>
</div>
<div class="description">
<%= yield :description %>
</div>
and then two views. The Episode view will render the following
<% render layout: "section" do %>
<% content_for :name do %>
<%= link_to episode.name, episode_path(episode) %>
<% end %>
<% content_for :description do %>
<%= link_to episode.description episode_path(episode) %>
<% end %>
<% end %>
This kind of works until you get to caching (they said content_for does not work with caching and I need to cache this) and the other problem I had was that you should include an additional empty not named yield.
I ended up with moving all the logic for playlist and episode views into a single view - called section that basically does the following:
<div class="name">
<%= link_to object.name, polymorphic_path(object) %>
</div>
<div class="description">
<% if is_episode? %>
<h1>Some special h1 for episode</h1>
<% elsif is_playlist? %>
<h2>Some special other html for playlist for episode</h2>
<% end %>
<%= raw(playlist.description) %>
</div>
Wow those "ifs" are ugly. I am not sure if I understood the problem correctly, but it is surprising I could not find a cleaner solution.

Ruby on Rails View Rendering DB Info On Page

I am working on a project and currently working on one of the views which is a page of different categories. Everything is rendering correctly however it's also putting the db info in the page.
Here is the code of my view
<div class="categories">
<div class="container blurbs">
<div class="cards row">
<%= #categories.each do |c| %>
<div class="card col-xs-4" %>
<%= image_tag c.image, :class => "cat" %>
<h4 class="title"><%= c.title %></h4>
</div>
<% end %>
</div>
</div>
</div>
Here is a link to a
screenshot of rendered page
Yes, fix is:
<div class="categories">
<div class="container blurbs">
<div class="cards row">
<% #categories.each do |c| %>
<div class="card col-xs-4" %>
<%= image_tag c.image, :class => "cat" %>
<h4 class="title"><%= c.title %></h4>
</div>
<% end %>
</div>
</div>
</div>
Look I removed = from this <%=.. In the below line :
<% #categories.each do |c| %>
#each method returns the collection after it completed its iterations. And due to this <%=, the return value of each which is #categories printed back. But if you use <%.. only, all above things will happen, but it wouldn't print back the object #categories.
when you use the tags <%= ... %> whatever is within the tags gets displayed on the page. In your current view you have
<%= #categories.each do |c| %>
<div class="card col-xs-4" %>
<%= image_tag c.image, :class => "cat" %>
<h4 class="title"><%= c.title %></h4>
</div>
<% end %>
Which displays the entirety of whatever the loop returns which is where you're getting the display. Change the tags to be <% #categories.each do |c| %> and you'll be good to go.

link_to tag not including all divs

I currently have a link to tag which should wrap around all the content within it, but currently it's not doing that. It's wrapping around the code until it hits another div with a rails query inside it?
index.html.erb
<% #posts.each do |post| %>
<div class="widget" >
<%= link_to post do %>
<div class="image b-lazy" data-src="<%= post.image %>">
</div>
<div class="caption">
<h4><%= post.title %></h4>
<p>by <%= post.affiliate %></p>
</div>
<!-- LINK TO TAG ENDS HERE FOR SOME REASON -->
<div class="caption-top">
<% post.categories.each do |category| %>
<%= link_to category_path(category) do %>
<div class="tag <%= category.name %>"><%= category.name %></div>
<% end %>
<% end %>
</div>
<% end %>
</div>
Any help is appreciated!
Jonathan
Two things:
You are using link_to inside another call to link_to. That is probably not what you want.
The result of a block will be what you return from a block, normally the last line. Take a look at this question for a solution.

Reply to comment in the same page not in comments/new path, Rails 4

I have created commenting system to provide functions like creating comments and replying them.
I used http://www.sitepoint.com/nested-comments-rails/ guide. Worked just perfect. But in this example to reply to some comment it goes to other path, that is what I want to avoid.
Code so far:
Advertisement#show here I want to create reply to comment.
<%= comments_tree_for #comments %>
<h1>New comment</h1>
<%= render 'comments/form' %>
_comment.html.rb
<div class="well">
<h2><%= comment.title %></h2>
<p class="text-muted"><%= comment.root? ? "Started by" : "Replied by" %> <strong><%= comment.author %></strong> on
<%= l(comment.created_at, format: '%B, %d %Y %H:%M:%S') %></p>
<blockquote>
<p><%= comment.body %></p>
</blockquote>
<% from_reply_form ||= nil %>
<% unless from_reply_form %>
<% if comment.leaf? %>
<small class="text-muted">There are no replies yet - be the first one to reply!</small>
<% end %>
<p><%= link_to 'reply', new_comment_path(comment.id) %></p>
<% end %>
</div>
_form.html.erb
<%= form_for(#comment) do |f| %>
<% if #comment.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#comment.errors.count, "error") %> prohibited this comment from being saved:</h2>
<ul>
<% #comment.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<%= f.hidden_field :advertisement_id, :value => #advertisement.id%>
<%= f.hidden_field :user_id, :value => current_user.id%>
<%= f.hidden_field :parent_id %>
<div class="form-group">
<%= f.label :body %>
<%= f.text_area :body, class: 'form-control', required: true %>
</div>
<%= f.submit class: 'btn btn-primary' %>
<% end %>
Is there any trustworthy guide to help me ?
The link_to 'reply', new_comment_path(comment.id) line creates a hyperlink to new comment page and when clicked it takes you to next page to create the comment. Instead you can replace it with a div containing the form the toggles and submits new convo from the same page. Bootstrap comes handy here.
A Mock up of the idea: http://jsfiddle.net/bpya4fce/1/
You can build up using this idea. Hope this helps :)
P.S: Make sure that you fetch the variables required for the form in the action of view where you embed the form, i.e if you're embedding the form in show.html.erb, ensure the necessary variables are fetched in the show action/method of controller. In the earlier scenario, it'll be fetched in the new action of the CommentsController.
<div class="container">
<blockquote>
<h2>Posted Comment</h2>
Lorem Ipsum. You can reply to this below.
</blockquote>
<div class="panel-group" id="accordion">
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion"
href="#collapseOne">
Click to reply
</a>
</h4>
</div>
<div id="collapseOne" class="panel-collapse collapse">
<div class="panel-body">
### The comment form comes here ###<br/>
### render :partial => 'comment/form'
</div>
</div>
</div>
</div>
Not sure if this is what you wanted. Hope this example code gives you some idea.
Be sure to complete the code and test it :)
_comment.html.rb
<% from_reply_form ||= nil %>
<% unless from_reply_form %>
<% if comment.leaf? %>
<small class="text-muted">There are no replies yet - be the first one to reply!</small>
<% end %>
<!-- HERE adding a hidden DIV that contains a form. -->
<div class='hidden-reply-form-<%= comment.id%>'>
<%= render partial: 'comments/form', locals: {comment: Comment.new} %>
</div>
<p><%= link_to 'reply', new_comment_path(comment.id), class: 'reply', id: comment.id %></p>
<% end %>
</div>
<script>
// HERE use reply link to toggle the hidden div.
$(function(){
$(".reply").click(function(){
// toggle replying div.
// .....
});
})
</script>

How can I declare a data-attribute using ERB?

This is the HTML I am trying to replicate:
<div id="links">
<a href="images/banana.jpg" title="Banana" data-gallery>
<img src="images/thumbnails/banana.jpg" alt="Banana">
</a>
</div>
I'm not sure how to do the data-gallery bit. How would I write such a thing with ERB?
Here's what I have so far:
<div id="links">
<% for photo in #photos %>
<%= link_to (image_tag photo.image.url(:medium))%>
<% end %>
</div>
<div id="links">
<% #photos.each do |photo| %>
<%= link_to (image_tag photo.image.url(:medium)), 'data-gallery' => true%>
<% end %>
</div>
Notice the more Rubyish way of iterating through an array of objects with each.
Add "data_gallery" => "value" to your link_to in HTML block.

Resources