How to use loops to create multiple tables from data query - ruby-on-rails

I have posts split into alphabetical groups like this.
A
B
C
E
Each letter needs 1 table.
Each row has 2 columns title and tags.
How do i add the table to the loop correctly so each letter has 1 table?
<table style=" width:100%; table-layout:fixed " >
</table>
index.html.erb
<% cur_letter = nil %>
<% #posts.each do |t| %>
<% title_letter = t.title[0].capitalize.match(/[A-Z]/) ? t.title[0].capitalize : "#" %>
<% if title_letter != cur_letter %>
<% cur_letter = title_letter %>
<%= cur_letter %>
<% end %>
<tr>
<td style="width:50%"><%= t.title %></td>
<td style="width:50%"><%= t.tags %></td>
</tr>
<% end %>

edit: I changed #post to #posts where stylistically appropriate
Rather than doing lots of gymnastics in your view, you could assemble the data how you want it before you pass it to the view:
#posts = Post.all.group_by {|post| post.title.downcase[0]}
# => {"a" => [<post....#array of post beginning with "A"], "b" => [post... #and so on... ]}
This will create a hash with a key representing each first letter with the value being all the Post objects whose title starts with that letter. Now with that passed to the view you could then iterate over them in a couple of ways.
In the interest of someone finding this later and running into the very real possibility that the field they are grouping by has a null value somewhere, I'll add this to cover all cases including nil values:
#posts = Post.all.group_by do |post|
if post.title == nil
post.title = ' '
end
post.title.downcase[0]
end
Now on to the view...
If you want just the letters that exist, i.e. if you don't have any posts that begin their title with "X", then you can just iterate through the keys
<% #posts.keys.sort.each do |key| %> #this is where the sorting a-z happens
<h2><%= key.upcase %></h2><br>
<table style=" width:100%; table-layout:fixed " >
<% #posts[key].each do |post| %>
<tr>
<td> <%= post.title %> </td>
<td> <%= post.tags %> </td>
</tr>
<% end %>
</table>
<% end %>
I've left out the styling details of your table as that is up to you.
If you want every letter listed, even if there are no Post titles beginning with that letter you can just do:
<% (('0'..'9').to_a + ('a'..'z').to_a).each do |letter| %>
#this generates ['0','1','2'....'z']
<h2><%= letter.upcase %></h2><br>
<table style=" width:100%; table-layout:fixed " >
<% #posts[letter].each do |post| %>
<tr>
<td> <%= post.title %> </td>
<td> <%= post.tags %> </td>
</tr>
<% end %>
</table>
<% end %>
This would give you:
A
A post beginning with "a" | some tags
Another post starting with "a" | some tags
B
C
D
Decidedly starts with "d" | some tags
Dis post starts with "d" ;-) | some tags
E
etc...
The problem with this style is that if you have any posts that start with a non-letter/non-number character, you won't see them unless you include all of those characters in your outer loop array. That is why I would do it the first way, as that represents the data that exists rather than guessing what data might exist.

I'm assuming your posts are already ordered alphabetically. You'll want to:
Open the first table.
Every time you hit a new letter, close the existing table and open a new one.
At the end, close the last table.
Code will look something like this:
<% cur_letter = nil %>
<table style=" width:100%; table-layout:fixed " >
<% #posts.each do |t| %>
<% title_letter = t.title[0].capitalize.match(/[A-Z]/) ? t.title[0].capitalize : "#" %>
<% if title_letter != cur_letter %>
<% cur_letter = title_letter %>
<%= cur_letter %>
<!-- You're switching letters here, so close the current table and start a new one. -->
</table>
<table style=" width:100%; table-layout:fixed " >
<% end %>
<tr>
<td style="width:50%"><%= t.title %></td>
<td style="width:50%"><%= t.tags %></td>
</tr>
<% end %>
</table>

Related

Rails class based on index value of in_groups_of

The following is intended to distribute array items into two columns.
<% #entitiquestions.in_groups_of(2, false) do |entitiquestions| %>
<tr>
<% entitiquestions.each do |entitiquestion| %>
<td>
<span data-tooltip class="hint--bottom hint--info" data-hint="<%= entitiquestion.question.query %>">
However, there is a class that should be set based on the index of the array item (if it is in fact an index...)
Can a condition be set somehow based on this position?
You can get the index of the array item by using each_with_index, for example the following will give you a row_index variable which starts from 0 for the first row:
<% #entitiquestions.in_groups_of(2, false).each_with_index do |entitiquestions, row_index| %>
Likewise, you can get the column index with:
<% entitiquestions.each_with_index do |entitiquestion, column_index| %>
Now you have the exact position of the element within the table, so you can use a ternary operator to add a class. As an example, if you wanted to add the highlight class when the row is even you could do:
<span data-tooltip class="hint--bottom hint--info <%= 'highlight' if row_index.even? %>"
Here's a full example:
<table>
<% #entitiquestions.in_groups_of(2, false).each_with_index do |entitiquestions, row_index| %>
<tr>
<% entitiquestions.each_with_index do |entitiquestion, column_index| %>
<td>
<span data-tooltip class="hint--bottom hint--info <%= 'highlight' if column_index.even? %>" data-hint="<%= entitiquestion.question.query %>">
<%= entitiquestion.question.query %>
</span>
</td>
<% end %>
</tr>
<% end %>
</table>

trouble coding links which insert search values into ransack form

I've coded in a page in which data from a database is pulled and subsequently when I click on what is displayed it enters a corresponding value into the search function on the application and displays the results, the code can be seen below:
course view:
<!-- Index of all Courses -->
<% provide(:title, "Course") %>
<!--containers for design/layout -->
<div class = "signinstyle">
<div class = "row">
<!--Page information -->
<%= form_tag(degree_new_path, :method => "get", id: "search-data") do %>
<table border="1" class="table">
<thead>
<tr>
<th>Courses</th>
</tr>
</thead>
<tbody>
<% #ads.each do |degree| %>
<tr>
<td> <%= link_to degree.cname, keyword_search_path(search: degree.cname) %>
</td>
</tr>
<% end %>
</tbody>
</table>
<%= submit_tag "Select" %>
<% end %>
<!--closing the design/layout containers -->
</div>
</div>
degree controller (the above view is within this):
class Degree < ActiveRecord::Base
def Degree.search(search)
where("cname LIKE ? OR ucas LIKE ?", "%#{search}%", "%#{search}%")
end
end
search controller (as I use my keyword search in the view):
def keyword_search
#search = Degree.all.select(:uname, :cname, :ucas, :duration, :qualification, :entry).distinct.order(id: :ASC)
if params[:search]
#search_degree = Degree.search(params[:search]).order('cname ASC')
end
end
def course
#select = Degree.all.select(:uname, :cname, :ucas, :duration, :qualification, :entry).distinct.order(id: :ASC)
if params[:search]
#select_degree = Degree.search(params[:search])
end
end
I'm trying to replicate the above code so I can click on similar links which will enter data into the ransack search function I have but have been unable to do so, if anybody could help me out it would be appreciated. Below is the code I'm currently trying to get to work:
Searches controller:
def adsearch
#adsearch = Degree.ransack(params[:q])
#data = #adsearch.result
#adsearch.build_condition if #adsearch.conditions.empty?
#adsearch.build_sort if #adsearch.sorts.empty?
end
the view file:
<!-- Index of all Courses -->
<% provide(:title, "Course") %>
<!--containers for design/layout -->
<div class = "signinstyle">
<div class = "row">
<!--Page information -->
<%= form_tag(degree_new_path, :method => "get", id: "search-data") do %>
<table border="1" class="table">
<thead>
<tr>
<th>Courses</th>
</tr>
</thead>
<tbody>
<% #ads.each do |degree| %>
<tr>
<td> <%= link_to degree.subject_group, adsearch_path(name: ucas & value: degree.ucas_letter) %>
</td>
</tr>
<% end %>
</tbody>
</table>
<%= submit_tag "Select" %>
<% end %>
<!--closing the design/layout containers -->
</div>
</div>
With the last two exerts of code it displays what I'm asking it to display on the initial view but doesn't enter the value I wish it to enter into the ransack search and as such doesn't create a search when clicked upon like the first example does.

Rails: Show each data with index

It's a simple question.
For example, I have 3 data
number name country
1 Jack US
2 Coda UK
3 Fredy TW
How do I display this number in rails dynamically.
here is part of code
<% #stay_times.each do |s| %>
<tr>
<td>
<%#= I don't know what to put here %>
</td>
<td>
<%= s.name %>
</td>
<td>
<%= s.nationality %>
</td>
<% end %>
Also you can use each_with_index method:
<% #stay_times.each_with_index do |s, index| %>
<tr>
<td>
<%= index + 1 %> <!-- index starts with zero -->
</td>
<td>
<%= s.name %>
</td>
<td>
<%= s.nationality %>
</td>
<% end %>
each_with_index(*args) public
Calls block with two arguments, the item and its index, for each item
in enum. Given arguments are passed through to #each().
If no block is given, an enumerator is returned instead.
hash = Hash.new
%w(cat dog wombat).each_with_index {|item, index|
hash[item] = index
}
hash #=> {"cat"=>0, "dog"=>1, "wombat"=>2}
It looks like you just need to use <%= s.number %> for the line where you have a comment. It depends on what the number field in the data table is called in your #stay_times variable. Hope this helps!

Put Value in a New Line Rails

I have a table and in my code on my html.erb file,
<td class="pstn-column"><%= a.lenders.pluck(:code).join(", ") %></td>
This returns the result in this format
Lender1, Lender2, Lender3
How do i make the result to look like this on the table
Lender1
Lender2
Lender3
I am using rails
Any help appreciated
<% a.lenders.pluck(:code).each do |lender| -%>
<td class="pstn-column"><%= lender %></td>
<% end -%>
I assumed that you need each element in a separate cell.
Just Try this
This code will add br tag after each element
<td class="pstn-column"><%= a.lenders.pluck(:code).join('<br />').html_safe %></td>
or, this will add newline character after each element
<td class="pstn-column"><%= a.lenders.pluck(:code).join("\n") %></td>
Create a new partial and pass the collection to the renderer.
_lender.html.erb
<tr><td><%= lender %></td></tr>
view.html.erb
<%= render #lenders %>
# Or
<%= render partial: 'lender', collection: #lenders %>
controller.rb
#lenders = a.lenders.pluck(:code)
I would make a list of lenders, since that seems to resemble the result you are trying to achieve
<td>
<ul>
<% a.lenders.pluck(:code).each do |lender_code| %>
<li><%= lender_code %></li>
<% end %>
</ul>
</td>
If you want to, the bullets can be removed trough CSS, using <ul style='list-style: none;'>

Where is this additional data coming from when calling an object's attributes?

In my html I have:
<table class="customers" summary="User customers">
<%= #customers.each do |customer| %>
<tr>
<td class="customer"><%= customer.mobile %></td>
<td class="timestamp">Added <%= time_ago_in_words(customer.created_at) %> ago.</td>
</tr>
<% end %>
</table>
The first row of data reads:
#<Customer:0x103061018>#<Customer:0x10304c910>#<Customer:0x10304c7a8>#<Customer:0x10304c668>
Before the expected:
5234567894 Added 1 day ago.
5234567893 Added 1 day ago.
5234567892 Added 1 day ago.
What is that first row of data and how do I get rid of it?
Instead of
<%= #customers.each do |customer| %>
try
<% #customers.each do |customer| %>
(so without the equal sign).
The equal sign is telling Rails to print out the result of what is between the '<%' and '%>'.

Resources