Rails class based on index value of in_groups_of - ruby-on-rails

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>

Related

How do I use check_box in a table form so that I can access the table attributes in an array?

I have a table inside of a form, with the following code:
<tbody>
<% #appointments.each do |appointment| %>
<td class="collapsing">
<div class="ui fitted slider checkbox">
<%= f.check_box appointment.id %><label></label>
</div>
</td>
<td><%= appointment.name %></td>
<% end %>
</tbody>
So a checkbox is generated, but if I'm selecting multiple checkboxes, I get
Parameters: {"utf8"=>"✓", "authenticity_token"=>"qCo02PG1F2wrSK4sxCQiQLzuhG4vZypgd9p5LzP9Sp7uZQFHs8tTTitLR++VXVK3f68P0qih+iQBlZt9anG01Q==", "cleaner"=>{"4"=>"1", "5"=>"0", "2"=>"0", "3"=>"0", "6"=>"0"}, "commit"=>"Request", "cleaner_id"=>"1"}
So to access the appointments, I would do parameters["cleaner"] and get <ActionController::Parameters {"4"=>"1", "5"=>"1", "2"=>"0", "3"=>"0", "6"=>"0"} permitted: false>
What I am looking to do is get an array instead of a hash.
The Hash class provides a keys method, which will return the keys of a hash as an array.
So parameters["cleaner"].keys is what you are (probably) looking for.
I guess you need to use some customization on the check boxes, something like:
<% #appointments.each do |appointment| %>
<td class="collapsing">
<div class="ui fitted slider checkbox">
<%= check_box_tag "cleaner[appointment_ids][]", appointment.id %><label></label>
</div>
</td>
<td><%= appointment.name %></td>
<% end %>
That way you should have something like params[cleaner][appointment_ids] to get the selected appointments

Pass selected value to Rails controller

I've got a method named 'statement' in a balances controller (balances_controller.rb) that returns information from a specific date (#latestDate) to a view (statement.html.rb)
#latestDate = the most recent date in the 'date' column in the 'balances' table
In the view, I've also got a dropdown list of all the dates and when a date is selected, I'd like to be able to update the information so that in effect, the statement method is called again but the #latestDate is set to the selected value from the dropdown list.
How can I do this?
UPDATE:
I've modified my code with brito's suggestions. When I press the Search button, the form passes the following params:
?utf8=✓&date_id=30%2F12%2F2015&commit=Search
However, if I select a date and click Search, the #latestDate gets set and the h1 tag gets displayed correctly, but the rest of the data doesn't get returned.
CODE:
balances_controller.rb
....
def statement
#dates = Balance.select("distinct(date)").order('date desc')
#Updated
if (params[:date_id].blank?)
#latestDate = Balance.order('date desc').first.date
else
#latestDate = params[:date_id]
end
#summaryBalances = Balance.joins(:account).order('accounts.credit').where('date = :abc', {abc: #latestDate})
end
....
balances/statement.html.rb
....
<h1>Statement at <%= #latestDate %></h1>
#UPDATED
<%= form_tag("/statement", method: "get") do %>
<%= select_tag "date_id", options_for_select( #dates.collect {|d| [ d.date, d.date ] }) %>
<%= submit_tag("Search") %>
<% end %>
<div class="table-responsive">
<table class="table">
<thead>
<tr>
<th>Account</th>
<th>Balance</th>
<th colspan="1"></th>
</tr>
</thead>
<tbody>
<% #summaryBalances.each do |balance| %>
<tr>
<td><%= balance.account.name %></td>
<td class='account-balance'><%= number_to_currency(balance.balance, unit: "£") %></td>
<td><%= link_to 'Edit', edit_balance_path(balance) %></td>
</tr>
<% end %>
</tbody>
</table>
</div>
....
A "dropdown" is a kind of input (HTML <select>).
<input>s and <select>s must be within a <form> HTML element.
Using pure HTML
Whatever is in the <form> will be accessible in the params hash. So if you have a dropdown list, it should be within a <form> like this:
<form accept-charset="UTF-8" action="/yourroute" method="get">
<select name="car">
<option value="volvo">Volvo</option>
<option value="saab">Saab</option>
<option value="opel">Opel</option>
<option value="audi">Audi</option>
</select>
</form>
In the example above, the selected value (e.g. "volvo") will be available in the controller within params["car"]. Note that you would still have to define /yourroute.
Using Rails' helper methods
Of course, Rails helps you generate forms and inputs. You can use Rails' form helpers for that. For example, the following generates a search form ("Search" label, text box for input and a button) that sends a GET to the /search route:
<%= form_tag("/search", method: "get") do %>
<%= label_tag(:q, "Search for:") %>
<%= text_field_tag(:q) %>
<%= submit_tag("Search") %>
<% end %>
EDIT
To check and set #latestDate = balance[date_id] if the balance[date_id] was selected:
#latestDate ||= params[:balance[date_id]] unless params[:balance].blank?

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!

How to use loops to create multiple tables from data query

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>

Create a sortable table on the client side using calculated data

I have a table that displays a name, and two values corresponding to each name that I have calculated using a loop and a progress bar for each value.
The code looks something like this,
<table>
<thead>
<th>Name</th>
<th>Value1</th>
<th>Value2</th>
</thead>
<tbody>
<% i=0 %>
<% j=0 %>
<% #department.members.each do |members| %>
<td><td><% members.name %><td>
<% members.evals.each do |evals| %>
<% i+=value1 * something %>
<% j+=value2 * something %>
<% end %>
<tr>
<td>
<div class="progress"><div class="bar" style="width: <%= (i*10).round() %>%;"></div></div>
<%= i %>
</td>
<td>
<div class="progress"><div class="bar" style="width: <%= (j*10).round() %>%;"></div></div>
<%= j %>
</td>
<% end %>
</tbody>
</table>
I wish to allow the user to click the heads and sort this information dynamically without changing the page on the client side, as well as create a drop-down menu above the table that allows the user to do the same. "Sort by value2" and "Sort by value1".
I am using bootstrap, so I don't want to use DataTables. Even their bootstrap theme doesn't look like boostrap. I just want a simple sort while preserving my current styling.
Datatable (http://datatables.net/release-datatables/examples/basic_init/zero_config.html)
You would need to sort the table with JavaScript, take a look at sortable table with jQuery.
You can always edit the CSS file to match your layout or to match with bootstrap's layout.

Resources