Here is a index.html.erb. How do I hide the table header, such as Remark, with a method when no records exists in remark attribute column? Preferably without using JavaScript.
index.html.erb
<table id = "kola" class="table listing text-center">
<% has_remark = collection_has_remark?(#aslani361s) %>
<thead>
<tr class="tr-head">
<td>Date</td>
<td>Description</td>
<td>Amount</td>
<td>Discount</td>
<td>Paid</td>
<td>Balance</td>
<td>DelnDel</td>
<% if has_remark %>
<td>Remark</td>
<% end %>
<td>Hide</td>
</tr>
</thead>
</table>
However I am able to hide the remark attribute values like as below ;
_aslani361.html.erb
<% if aslani361.remark.present? -%>
<td class="col-1"><%= aslani361.remark %></td>
<% end %>
aslani361s_helper.rb
module Aslani361sHelper
def collection_has_remark?(collection)
collection.each do |aslani361|
if aslani361.remark.present?
return true
end
end
end
end
aslani361.rb
class Aslani361 < ActiveRecord::Base
end
Any suggestions are most welcome.
Thank you in advance.
If you wish to hide the column because no records in your array has the remark value, you can do something like this:
Define a method in your helper module file for the controller:
def collection_has_remark?(collection)
collection.each do |record|
if record.remark.preset?
return true
end
end
end
Then use it in the view
<% has_remark = collection_has_remark?(#records) %>
<thead>
<tr class="tr-head">
<td>Date</td>
<td>Description</td>
<td>Amount</td>
<td>Discount</td>
<td>Paid</td>
<td>Balance</td>
<% if has_remark %>
<td>Remark</td>
<% end %>
</tr>
</thead>
Then use the same if statement inside your loop. Personally I think it's important to leave an empty column, so users know for sure it doesn't have one.
Related
In my Rails 7 app I've got data table which I want to decorate. The data comes from the API response so in fact it's an array of hashes. Like below:
# transactions_controller.rb
class TransactionsController < ApplicationController
def index
response = client.transactions.list(platform_id: current_user.platform_id, page: 1, per_page: 100)
#transactions = response.body['data']
end
private
def client
#client ||= TestAPI::Client.new
end
end
Now inside the transactions/index.html.erb I've got a table with #transactions data which I want to decorate:
#views/transactions/index.html.erb
<table class="table table-striped">
<thead>
<tr>
<b>
<tr>
<th>Date</th>
<th>Amount</th>
</tr>
</b>
</tr>
</thead>
<tbody>
<% #transactions.map do |transaction| %>
<tr>
<td>
<%= transaction['created_at'] %>
</td>
<td>
<%= transaction['amount_cents'] %>
</td>
</tr>
<% end %>
</tbody>
</table>
I know I could inject that logic inside of view file to be like:
(...)
<td>
<%= Date.parse(transaction['created_at']).strftime("%d.%m.%Y") %>
</td>
<td>
<%= "#{ transactions_data.last['amount_cents']/100}" "#{ transactions_data.last['currency']}" %>
</td>
(...)
But I want to get rid of that logic from the view since I'll have more and more logic in the future here.
Kudos for wanting to remove logic from the view.
You need a new object, it could be called TransactionPresenter or whatever you choose. It will implement the view logic. So in your TransactionsController:
def index
response = client.
transactions.
list(platform_id: current_user.platform_id, page: 1, per_page: 100).
map{|t| TransactionPresenter.new(t)}
#transactions = response.body['data']
end
and the TransactionPresenter model could be something like this:
class TransactionPresenter
def initialize(transaction)
# capture the fields of interest as variables
end
def amount
"$#{amount_cents.to_f/100}" # for example, whatever makes sense in your context
end
end
so all logic is removed from the view:
<table>
<% #transactions.each do |transaction| %>
<tr><%= transaction.amount %></tr>
<% end %>
</table>
For starters, this is the view I am trying to replicate:
This is the HTML from that layout (from the SAT portion anyway, you can extrapolate the rest):
<table class="table table-hover table-bordered">
<thead>
<td colspan="2" class="text-center">
<strong>SAT</strong>
</td>
<tr>
<th>Subject</th>
<th>Grade</th>
</tr>
</thead>
<tbody>
<tr>
<td>Reading</td>
<td>900</td>
</tr>
<tr>
<td>Math</td>
<td>700</td>
</tr>
<tr>
<td>Writing</td>
<td>800</td>
</tr>
<tr>
<td><strong>Total</strong></td>
<td><strong>2,400</strong></td>
</tr>
</tbody>
This is what my Grade.rb model looks like:
# == Schema Information
#
# Table name: grades
#
# id :integer not null, primary key
# subject :string
# result :string
# grade_type :integer
# profile_id :integer
# created_at :datetime not null
# updated_at :datetime not null
#
class Grade < ActiveRecord::Base
belongs_to :profile
enum grade_type: { csec: 0, cape: 1, sat: 2, g7: 3, g8: 4, g9: 5, g10: 6, g11: 7, g12: 8, g13: 9 }
end
This is what that table looks like currently, i.e. before using the lookup_context method in Rails:
<table class="table table-hover table-bordered">
<thead>
<td colspan="2" class="text-center">
<strong>SAT</strong>
</td>
<tr>
<th>Subject</th>
<th>Grade</th>
</tr>
</thead>
<tbody>
<% #sat_grades.each do |grade| %>
<tr>
<% if grade.subject.eql? "Total" %>
<td><strong><%= grade.subject %></strong></td>
<td><strong><%= grade.result %></strong></td>
<% else %>
<td><%= grade.subject %></td>
<td><%= grade.result %></td>
<% end %>
</tr>
<% end %>
</tbody>
Where #sat_grades is this: #sat_grades = #profile.grades.where(grade_type: :sat).
I want to use this lookup_context method, I was thinking like this:
<% #grades.each do |grade| %>
<% if lookup_context.template_exists?(grade.grade_type, "grades/grade_types", true) %>
<%= render partial: "grade/grade_types/#{grade.grade_type}", locals: {event: event, index: index} %>
<% end %>
<% end %>
The issue I am running into is that each grade_type has a different table. So grade_type: :sat belongs in the "SAT" table, the same for "CSEC", "g11", etc.
I can't think of a way to have each of those grade_types rendered specifically within their HTML table, without having lots of lookup_context.template_exists? calls within that view.
It almost defeats the purpose of doing it like that, if I have to have a lookup_context call for each grade_type.
What's the best way to approach this so I just have 1 lookup_context call (if possible), but it correctly renders and handles all the different grades correctly.
With the given fragment I would try the following:
# Render each grade
<%= render(partial: "grade/grade", collection: #grades, locals: {event: event, index: index}) || "There's grade to be displayed" %>
# Render Concated content
<%= content_for :all_grades %>
Within grade/_grade.html.erb:
# If a special grade template exists prepare the content to be shown
# but don't display it right now
<% if lookup_context.template_exists?(grade.grade_type, "grades/grade_types", true) %>
<%= render partial: "grade/grade_types/#{grade.grade_type}", locals: {event: event, index: index} %>
<% end %>
# Render the common stuff
...
# Display the special stuff stored for the grade
<%= content_for :grade_table %>
# Repeat previous steps
...
Within the grade template (for instance grade/grade_types/_g7.html.erb):
# remove content from previous grades
<% content_for :grade_table, flush: true do %>
...
<% end %>
<% content_for :xxx_xxx, flush: true do %>
...
<% end %>
...
# Concat content for all grades together (flush: false)
<% content_for :all_grades do %>
...
<% end %>
Another approach can be a presenter or maybe even Single Table Inheritance.
Lets say that I have a model with name of User. How can I add a virtual attributes to the final result of generated query ?
class User < ActiveRecord::Base
ATTRIBUTES = %w[name email balance]
scope :main_selection, -> { select('name,email,total_bought, total_deposit') }
def balance
(total_deposit - total_bought).round
end
end
and inside my controller I have
#user = User.main_selection
#attributes = User::ATTRIBUTES
Inside the View I would like to show it in a table
<table>
<thead>
<tr>
<% #attributes.each do |a| %>
<th><%= a %><th>
<% end %>
</tr>
</thead>
<tbody>
<% #user.each do |u| %>
<tr>
<% #attributes.each do |a| %>
<td><%= u[a] %><td>
<% end %>
</tr>
<% end %>
</tbody>
<table>
The only problem is that I need to add the balance attribute into the generated result, so that the loop with u[a] could work.
I need to mention that the balance can be called by #user.first.balance, but inside the loop does not work and it shows a nil value instead.
Try u.send(a) instead of u[a]
u[a] will only work on attributes. In your example, balance is not an attribute, it's a method.
I have a loop in one of my views to display a table like so:
Each category object has 5 attributes called: level_1, level_2, level_3, level_4, level_5.
There will be an array with all the category objects. so there could be any amount of categories and no necessarily 3.
what would the best way to draw this up be? i have something like this at the moment but dont know how to select the relevant category level attribute in the 5.times loop.
<table border="0">
<tr>
<th>Maturity</th>
<% for category in #categories %>
<th><%= category.category_title %></th>
<% end %>
</tr>
<% 5.times do |i|%>
<% level = 5 - i %>
<tr>
<td>Level <%= level %> Maturity</td>
<% for category in #categories %>
<td><%= category.level_ #put in the level value here so it selects the relevant attraibute %></td>
<% end %>
</tr>
<% end %>
</table>
you need to change the rendering of level with this:
<% for category in #categories %>
<td><%= category.send("level_#{level}") %></td>
<% end %>
send is used to call a method on an object so that you can compose your method at runtime.
If you categories as variable no. then you shouldn't make it columns, but rows. And then levels will be you columns e.g.
<table>
<tr>
<th>Level 1</th>
<th>Level 2</th>
<th>Level 3</th>
<th>Level 4</th>
<th>Level 5</th>
<tr>
<% #category.each do |c| %>
<tr>
<td>#category.level_1<td>
<td>#category.level_2<td>
<td>#category.level_3<td>
<td>#category.level_4<td>
<td>#category.level_5<td>
<th>
<% end %>
Now in above code you may replace hard coded level_#{no} with iterations.
Hi i have a table where i list different values. Now i want to add a total values to my table that counts the values from each column and adds it to a column with the total value. How do I do this? And is it possible to do this in a simple way in the view, or am I bound to do it in the model? Thanks for any help!
<div class="chart-data">
<table>
<caption>Data</caption>
<thead>
<tr>
<% statistic.column_titles.each do |column| %>
<th><%= column %></th>
<% end %>
<th>Total</th>
</tr>
</thead>
<tbody>
<% statistic.rows.each do |row| %>
<tr>
<th scope="row"><%= row.title %></th>
<% row.data.each do |column| %>
<td><%= column %></td>
<% end %>
</tr>
<------- Here i want to have the code that sums the values from the columns above to form the 'Total'
<% end %>
</tbody>
</table>
</div>
The simple solution would be to maintain a variable that sums up the column, then use it for the total at the end.
class Row < ActiveRecord::Base
def total_spent
sum(:data)
end
end
<tbody>
<% #rows.each do |row| %>
<tr>
<th scope="row"><%= row.title %></th>
<% row.data.each do |column| %>
<td><%= column %></td>
<% end %>
</tr>
<td><% row.total_spent %></td>
<% end %>
</tbody>
Assuming of course that row is a model you could move this logic inside the row model. You may cache the page as well if you like.
If your data is the result of an ActiveRecord query against a database you could ask the database to do the work of summing all the columns. It would be one additional query but would run very quickly as that's something databases are designed to do.