Rails Conditional Statements on Object Index Page - ruby-on-rails

In my rails app, I have an index of an object I'm calling Lessons. If a user marks the lesson as being completed, it gets recorded in a join table called Completions and the completed_step boolean gets set to true.
In the show action for the lesson, I'm able to insert a conditional statement to modify the button for "Complete Lesson."
That button logic works fine like this:
<% if current_user.completed_steps.include? #lesson %>
<%= button_to "This Lesson is Completed", #lesson.next, class: "btn btn-success btn-lg", :method => :get %>
<% else %>
<%= button_to "Mark this Lesson as Complete", complete_lesson_path, class: "btn btn-warning btn-lg" %>
<% end %>
My question is how do I incorporate this type of logic check on the index view?
I'd like the links to each Lesson to appear in a Bootstrap Panel and I want to change the color of the panel depending upon whether or not the user completed_step for each Lesson.
I tried wrapping the panel in the same statement and it doesn't work, it stays red even though the user has completed these lessons.
Here's what I attempted:
<% #lessons.each do |lesson| %>
<% if current_user.completed_steps.include? #lesson %>
<div class="panel panel-success">
<% else %>
<div class="panel panel-danger">
<% end %>
<div class="panel-heading">
<h3 class="panel-title">
<%= link_to(lesson) do %>
<strong><%= lesson.title %></strong>
<% end %>
</h3>
</div>
<div class="panel-body">
<td><%= lesson.summary %></td>
</div>
</div>
What am I doing wrong or why isn't this working?

Please change your script
<% #lessons.each do |lesson| %>
<% if current_user.completed_steps.include? lesson %>
<div class="panel panel-success">
<% else %>
<div class="panel panel-danger">
<% end %>
<div class="panel-heading">
<h3 class="panel-title">
<%= link_to(lesson) do %>
<strong><%= lesson.title %></strong>
<% end %>
</h3>
</div>
<div class="panel-body">
<td><%= lesson.summary %></td>
</div>
</div>

You need to pass same object as you given in in you for loop .
<% #lessons.each do |lesson| %>
<% if current_user.completed_steps.include? lesson %>
<div class="panel panel-success">
<% else %>

#Pramod Gupta is right. Also, look into using Presenters for this type of logic that is used for decorating the views.

Related

I'm trying to render two columns of information in my rails app

So, I have an app that is trying render 2 (or maybe more if needed) columns using a loop. It does one column and looks pretty good, but I want the option of 2 or even more. I know about "in_groups.of()", but I can't quite figure it out to work with my
<% #vendors.each do |vendor| %>
<%= link_to vendor do %>
<div class="row">
<div class="col-md-6">
<div class="card-container">
<div class="col-md-6">
<div class="card">
<%= image_tag attachment_url(vendor, :background_image), class: 'card-img-top' %>
<div class="card-block">
<h4 class="card-title"><%= vendor.Company %>. </h4>
<p class="card-text"><%= vendor.Description.html_safe.first(25) %></p>
<div class="card-standing"><strong><%= vendor.FinancialStanding %></strong></div>
</div>
</div>
</div>
</div>
</div>
</div>
<% end %>
<% end %>
Not sure why you needed this, because everything can be managed with css and html. But you can make changes like this:
<% #vendors.to_a.in_groups_of(2).each do |vendor| %> # #vendors.to_a cover AR to array
<% vendor.each do |v| %> # becuase vendor is array here.
..........your code..............
<% end %>
<% end %>

How to do a table association query to return all elements and perform further manipulation

I have a one to many association between Challenge (1) and Entry (many).
I would like to extract the last (as in date created) entry for each challenge and also the name of the challenge in one object.
I then use the result of the query in the view as follows:
<% #discovers.each do |discover| %>
<div id="box-3" class="box">
<%= link_to(image_tag(discover.picture.url), entries_path(challenge_id: discover.challenge_id),remote: true) if discover.picture? %>
<span class="caption simple-caption">
<p><%= discover.blob %></p>
<%= link_to "Join up", join_challenge_path(id: discover.challenge_id) %>
</span>
</div>
<% end %>
so far I have
#discovers = Challenge.all.map{|c| c.entries.last}
but I can't then access the name of a challenge, only the records in the Entry table. How can I access both in #discovers?
Update
Using #rob and #Pavan's code here is what I have
view
<% #discovers.each do |discover| %>
<% discover.each do |disc| %>
<div id="box-3" class="box">
<%= link_to(image_tag(disc.picture.url), entries_path(challenge_id: disc.challenge_id),remote: true) if disc.picture? %>
<span class="caption simple-caption">
<p><%= disc.rules %></p>
<%= link_to "Join up", join_challenge_path(id: disc.challenge_id) %>
</span>
</div>
<% end %>
<% end %>
controller
def index
#discovers = Challenge.includes(:entries).collect{|c| [c.name, c.entries.last] }
end

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.

Dynamically generate all products on a responsive view using Bootstrap's Grid system

I want to generate all my products and their information on a page using bootstrap's grid system. I tried to generate three products in a row at first and it worked using the following code:
<div class="container">
<h1 align="center">Listing products</h1>
<% #products.each do |product| %>
<% if #a%3 == 0 %>
<div class="row">
<% end %>
<div class="col-lg-4">
<%= image_tag(product.image_url, class: 'list_image', size: '260x320') %>
<%= product.title %> <br/>
<%= product.price %> <br/>
<%= link_to 'Show', product %><br/>
</div>
<% #a = #a+1 %>
<% if #a%3 == 0 %>
</div><hr/>
<% end %>
<% end %>
</div>
(#a is what I declared in the controller which is initially set to 0)
The code will not work anymore if I want to only display two or less products in a row using the grid system when the screen gets smaller.
Are there any better ideas to achieve this?
Seems like you are generating incorrect HTML markup. Try to use each_slice:
<div class="container">
<h1 align="center">Listing products</h1>
<% #products.each_slice(3) do |products| %>
<div class="row">
<% products.each do |product| %>
<div class="col-lg-4">
<%= image_tag(product.image_url, class: 'list_image', size: '260x320') %>
<%= product.title %> <br/>
<%= product.price %> <br/>
<%= link_to 'Show', product %><br/>
</div>
<% end %>
</div>
<hr/>
<% end %>
</div>

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>

Resources