Sorting views using data between two tables - ruby-on-rails

I am trying to sort data in my chatbox with data from two tables (kind of trying to make an events log place).
This is my chatbox:
Chatbox/Events Log
I want to sort the blue and green boxes based on date/time. Here's the code that I want to sort:
Code
Can you guide me on how to achieve this?
EDIT
Updated Code:
Updated Code 3rd April Image
stats.html.erb file
<%
#objects = (#solrs + #messages).sort_by &:created_at
%>
<% #objects.each do |obj| %>
<% if obj.is_a? Solr %>
<!-- Solrs Partial -->
<%= render 'messages/solr' %>
<% else %>
<!-- Messages Partial -->
<%= render #messages %>
<% end %>
<% end %>
Code Inside Solrs Partial
<% #solrs.each do |solr| %>
<div class="row msg_container base_receive">
<div class="col-xs-10 col-md-10">
<div class="messages msg_receive">
<p class="">
Disease <b><%= solr.disease %></b> has been created with synonyms <b> <%= solr.synonym %></b> by <b><%= solr.user.first_name %> <%= solr.user.last_name %></b><br>
</p>
<time> <%= solr.created_at.strftime("%d %b %4Y")%> • <%=solr.created_at.strftime("%I:%M%p")%></time>
</div>
</div>
</div>
<% end %>
Code Inside Messages Partial
<div class="row msg_container base_sent">
<div class="col-md-1 col-xs-1">
<p><em><%= message.user.first_name %>: </em></p>
</div>
<div class="col-md-10 col-xs-10">
<div class="messages msg_sent">
<p>
<%= message.body %>
</p>
<time> <%= message.created_at.strftime("%d %b %4Y")%> • <%=message.created_at.strftime("%I:%M%p")%></time>
</div>
</div>
</div>
solr_controller file
def stats
#messages = Message.custom_display
#message = Message.new
#solrs = Solr.all
#users = User.all
end

To sort multiple models together, first create a collection of the two:
#objects = #solrs + #messages
then, use [sort_by](https://apidock.com/ruby/Enumerable/sort_by):
#objects.sort_by &:created_at -or- #objects.sort_by { |obj| obj.created_at }
Pretty sure you can wrap that in to one line like:
#objects = (#solrs + #messages).sort_by &:created_at
[is_a?](https://apidock.com/ruby/Object/is_a%3F) will let you treat each one individually, this SO question goes over this nicely
Example:
solr_controller.rb
def stats
#messages = Message.includes(:user).custom_display
#solrs = Solr.includes(:user).all
#objects = (#solrs + #messages).sort_by &:created_at
end
[.includes](https://apidock.com/rails/ActiveRecord/QueryMethods/includes) will let you access the associated user without querying the database again. Here's a good article on it.
assuming you're in /views/messages, adjust if your file structure is different
/messages/stats.html.erb
<% #objects.each do |obj| %>
<% if obj.is_a? Solr %>
<%= render partial: 'solr', locals: { solr: obj } %>
<% else %>
<%= render partial: 'message', locals: { message: obj } %>
<% end %>
<% end %>
/messages/_solr.html.erb
<div class="row msg_container base_receive">
<div class="col-xs-10 col-md-10">
<div class="messages msg_receive">
<p>
Disease <b> <%= solr.disease %> </b>
has been created with synonyms <b> <%= solr.synonym %> </b>
by <b> <%= solr.user.first_name %> <%= solr.user.last_name %> </b>
<br>
</p>
<time>
<%= solr.created_at.strftime("%d %b %4Y") %> •
<%= solr.created_at.strftime("%I:%M%p") %>
</time>
</div>
</div>
</div>
/messages/_message.html.erb
<div class="row msg_container base_sent">
<div class="col-md-1 col-xs-1">
<p> <em> <%= message.user.first_name %>: </em> </p>
</div>
<div class="col-md-10 col-xs-10">
<div class="messages msg_sent">
<p> <%= message.body %> </p>
<time>
<%= message.created_at.strftime("%d %b %4Y") %> •
<%= message.created_at.strftime("%I:%M%p") %>
</time>
</div>
</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" %>

Display last record in erb Rails with will_paginate

I am trying to display the last instanced record from my model Tribune with this layout :
Some random tribune
Some random tribune
Last
Last recorded tribune
I am using the gem will_paginate which allow me to display 10 tribunes / per page.
The issue is that the layout is working but applied to each page.
Every 10 tribunes, one is identified as "last". Obviously, I would like to have only one tribune identified as last.
Here is my code :
<div class="wrapping">
<% #tribunes.each do |tribune| %>
<div class="container">
<div class="mouse-out-container"></div>
<div class="row">
<% if tribune == #tribunes.last
%>
<h1>Last</h1>
<div class="col-xs-12 col-md-12">
<div class="card">
<div class="card-category">Popular</div>
<div class="card-description">
<h2><%= tribune.title %></h2>
<p><%= tribune.content.split[0...25].join(' ') %>...</p>
</div>
<img class="card-user" src="https://kitt.lewagon.com/placeholder/users/tgenaitay">
<%= link_to "", tribune, :class => "card-link" %>
</div>
<% else %>
<div class="col-xs-12 col-md-12">
<div class="card">
<div class="card-category">Popular</div>
<div class="card-description">
<h2><%= tribune.title %></h2>
<p><%= tribune.content.split[0...25].join(' ') %>...</p>
</div>
<img class="card-user" src="https://kitt.lewagon.com/placeholder/users/tgenaitay">
<%= link_to "", tribune, :class => "card-link" %>
</div>
</div>
<% end %>
<% end %>
</div>
<div class="center-paginate">
<%= will_paginate #tribunes, renderer: BootstrapPagination::Rails %>
</div>
</div>
</div>
When all Goole-fu fails, we have to dig in the source code. There we find some interesting methods:
# Any will_paginate-compatible collection should have these methods:
# current_page, per_page, offset, total_entries, total_pages
#
# It can also define some of these optional methods:
# out_of_bounds?, previous_page, next_page
From these, the method next_page looks interesting, as it seems to return nil if there are no more pages.
Now we can construct the loop:
<% #tribunes.each do |tribune| %>
<% if !#tribunes.next_page && tribune == #tribunes.last %>
<!-- We're on the last page and the last tribune of that page -->
Last tribune content
<% else %>
<!-- We still have tribunes to go -->
Normal tribune content
<% end %>
<% end %>

Rails partial view repeat display

Here is part of my index.html
<div class="col-md-8">
<% #books.each do |book| %>
<div class="row">
<div class="col-md-4">
<%= image_from_amazon(book.amazon_id) %>
</div>
<div class="col-md-8">
<h3 class = "text-info">
<%= book.title %>
</h3>
<br>
<em class ="text-muted">
written by <%= book.author %>
</em>
<br>
<br>
<p>
<%= book.description %>
</p>
<% book.genres.each do |genres| %>
<span class="label label-primary">
<%= genres.name %>
</span>
&nbsp
<% end %>
</div>
</div>
<% end %>
</div>
Basically, it will display 3 books, and it works fine.
Then, I move that code into _book.html.erb and edit above code into
<%= render #books %>
However, it repeat 3 times, that is, it display 9 books. And the sequence is [1st,2nd,3rd] [1st,2nd,3rd] [1st,2nd,3rd] like this picture.
Update
update index.html.erb
<div class="clearfix">
<div class="col-md-12">
<%= render #books %>
<div class="col-md-4">
<h3>Genre (Click to filter books)</h3>
<br>
<li>
<span class = 'label label-danger'>
<%= link_to "No filter" ,books_path, style: 'color:#FFFFFD' %>
</span>
<br>
<br>
</li>
<% #genres.each do |genres| %>
<li>
<span class = 'label label-primary' style="color:#FFFFFD">
<%= link_to genres.name ,books_path(filter: genres.name),style: 'color:#FFFFFD' %>
</span>
</li>
<br>
<% end %>
</div>
</div>
<!-- clearfix -->
</div>
Try the following:
<div class="col-md-8">
<%= render #books %>
</div>
And make sure <% #books.each do |book| %> and its <% end %> tag aren't in the partial.
Rendering Collections Docs
Edit
#index.html.erb
<div class="col-md-8">
<%= render #books %>
</div>
# _book.html.erb
<div class="row">
<div class="col-md-4">
<%= image_from_amazon(book.amazon_id) %>
</div>
<div class="col-md-8">
<h3 class = "text-info">
<%= book.title %>
</h3>
<br>
<em class ="text-muted">
written by <%= book.author %>
</em>
<br>
<br>
<p>
<%= book.description %>
</p>
<% book.genres.each do |genres| %>
<span class="label label-primary">
<%= genres.name %>
</span>
&nbsp
<% end %>
</div>
</div>

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