I am building an html table that should include name, rating1, rating2, and rating3. rating 1-3 come from different models than name.
resources :names do
resource :rat1,:rat2,:rat3
end
Inside of my html table I'd like to include the ratings from within each of these tables but I would like to automatically skip over or ignore tables that are nil. This is because :names may only have a :rat1 and not a :rat2 or :rat3. My view should look something like this.
<table>
<thead>Name</thead>
<thead>Rating 1</thead>
<thead>Rating 2</thead>
<thead>Rating 3</thead>
<% #names.each do |name| %>
<tr>
<td><%= name.nametext %></td>
<td><%= name.rat1.rating %></td>
<td><%= name.rat2.rating %></td>
<td><%= name.rat3.rating %></td>
</tr>
<% end %>
</table>
Except that if name.rat1 is nil it will either a.) replace the value with N/A OR b.) it will leave this field blank and move on to the next.
What is the cleanest way to do this?
::UPDATE::
So my issue is that the name.rat1 is nil and the name.rat1.rating is an undefined method of a nil class so both of these options will throw the same undefined method of a nil class error regardless of the || or helper method. At least thats what my current tests are showing. Any other options? or different workarounds? I'd like to avoid having to put a validation loop like this for every rat1-3
<% unless name.rat1.nil? %>
<%= name.rat1.rating %>
<% end %>
There has to be a simpler way.
I would probably create a helper method in names_helper.rb
def show_rating(rating)
if rating.present?
rating
else
"default value"
end
end
Then use it in the view:
<%= show_rating name.rat1.rating %>
OFFTOPIC Your table structure is wrong. It should have <thead><tr><th>Name</th><th>Rating1</th>..so on..</tr></thead>
So, in your case you can use the condition while rendering the rating values as:
<table>
<thead>
<tr>
<th>Name</th>
<th>Rating 1</th>
<th>Rating 2</th>
<th>Rating 3</th>
</tr>
</thead>
<tbody>
<% #names.each do |name| %>
<tr>
<td><%= name.nametext %></td>
<td><%= name.rat1.rating || 'N/A' %></td>
<td><%= name.rat2.rating || 'N/A' %></td>
<td><%= name.rat3.rating || 'N/A' %></td>
</tr>
<% end %>
</tbody>
</table>
Related
I want this function, if the status of progress so that it changes on the done exactly at those IDs where the status is for the conditions, at the moment I get an error and secondly, if it worked without errors, then it would change everything, but I need if progress is finished and if you don’t, then on progress
I selected three records through the form using a checkbox ...
in the function, I want that if the status of the record from database is "done", then it should change to "progress", if the status is "progress" in the record, then it should be changed to "done". Now I click on "submit_tag" and I get an error and in any case this code will not work the way I want it, I want everything to be conditional.
I am completely in ruby, help please, maybe the problem is in the syntax
no implicit conversion from nil to integer
def update_me
#iteam = Iteam.find(params[:id])
if #iteam[params[:status]] == 'progress'
Iteam.where(params[:id]).update_all(status: 'DONE')
else
Iteam.where(params[:id]).update_all(status: 'progress')
end
end
index view
<%= form_tag update_me_iteams_path, :method =>'put' do %>
<table>
<tr>
<th>Title</th>
<th>Text</th>
<th>Status</th>
<th></th>
</tr>
<% #iteams.each do |iteam| %>
<tr>
<td><%= iteam.id %></td>
<td><%= iteam.title %></td>
<td><%= iteam.text %></td>
<td><%= iteam.status %></td>
<td><%= link_to 'Show', iteam_path(iteam) %></td>
<td>
<%= check_box_tag "id[]", iteam.id %>
</td>
</tr>
<% end %>
</table>
<%= submit_tag "Edit Checked" %>
<% end %>
Please Use following to find with id:
Iteam.where(id: params[:id])
or you can use the following
Iteam.find(params[:id])
Good afternoon. I am new to ruby and trying to build my first application.
I am using sqlite database and rails 5.0.
I have a model called Person that has the first name, last name and date of birth as attributes.
On the page where I list people I want to add the age of the people and obtain an average of the ages of the people
My controller looks like this:
before_action :set_persona, only: %i[ show edit update destroy ]
# GET /personas or /personas.json
def index
#persona = Persona.order("cast(strftime('%m', fecha_nacimiento) as integer)")
end
And my view like this
<table>
<thead>
<tr>
<th>Nombre</th>
<th>Apellido</th>
<th>Fecha nacimiento</th>
<th>Dni</th>
<th>Edad</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% #persona.each do |persona| %>
<tr>
<td><%= persona.nombre %></td>
<td><%= persona.apellido %></td>
<td><%= persona.fecha_nacimiento %></td>
<td><%= persona.dni %></td>
<td><%= Time.now.year - persona.fecha_nacimiento.year %></td>
<td><%= link_to 'Detail', persona %></td>
<td><%= link_to 'Edit', edit_persona_path(persona) %></td>
</tr>
<% end %>
</tbody>
</table>
<p>El promedio de edad de las personas es: </p>
Since I don't have a field in the database called "age" I can't understand how I can achieve the result.
The objective would be to iterate through each of the people and divide it by the length of it, or is there an easier way?
Please excuse my ignorance, thank you very much in advance.
What you want to do is select your calculated column and give it an alias:
def index
#persona = Persona.select(
Persona.arel_table[Arel.star], # personas.*
"cast(strftime('%m', fecha_nacimiento) as integer) as age"
)
.order(age: :desc)
end
Any columns you select will be available in the resulting model instances as attributes:
<table>
<thead>
<tr>
<th>Nombre</th>
<th>Apellido</th>
<th>Fecha nacimiento</th>
<th>Dni</th>
<th>Edad</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% #persona.each do |persona| %>
<tr>
<td><%= persona.nombre %></td>
<td><%= persona.apellido %></td>
<td><%= persona.fecha_nacimiento %></td>
<td><%= persona.dni %></td>
<td><%= persona.age %></td>
<td><%= link_to 'Detail', persona %></td>
<td><%= link_to 'Edit', edit_persona_path(persona) %></td>
</tr>
<% end %>
</tbody>
</table>
The easiest way to implement what you're asking is to do the operation within the view. This kind of breaks MVC but it's the fastest.
<% edades = 0 %>
<% #persona.each do |persona| %>
<% edades += Time.now.year - persona.fecha_nacimiento.year %>
<!-- ... the rest of the view code -->
<% end %>
<% average = edades.to_d / #persona.length # need to typecast to decimal so you can have fractionals %>
To do this in an MVC manner, you will have to do the computation in the controller.
def index
#persona = Persona.order("cast(strftime('%m', fecha_nacimiento) as integer)")
#average = #persona.collect { |p| Time.now.year - p.fecha_nacimiento.year }.sum / #persona.length.to_d
end
It would be easier to implement an age method in Person model so you can just call the method instead.
class Person
def edad
Time.now.year - fecha_nacimiento.year
end
end
and lastly, the computation for the age is more complex than just current year less birthday year. We use this function (taken from https://stackoverflow.com/a/2357790/365218) to calculate for the age.
def age(dob)
now = Time.now.utc.to_date
now.year - dob.year - ((now.month > dob.month || (now.month == dob.month && now.day >= dob.day)) ? 0 : 1)
end
I realize the heading is a little confusing but my problem is quite simple. I hae two models in my rails 5 app. User and Expense. Each expense belongs_to a user. I have an index page where all expenses are being listed. I can list the user IDs for each expense from the expenses table but I want to instead look up the name of the user (in column username) in the users table and display it with the expense instead. The view I have written is below. But it doesn't work.
<p id="notice"><%= notice %></p>
<h1>Teamjournals</h1>
<table style="padding: 2px; width: 50%" border="2px" align="center">
<thead>
<tr>
<td align="center"><%= link_to new_expense_path, :class =>"btn btn-success btn-wide" do%>Add New Expense<% end %></td>
</tr>
<tr>
<th>User</th>
<th>Expense Date</th>
<th>Currency</th>
<th>Expense Amount</th>
<th>Description</th>
<th colspan="1"></th>
</tr>
</thead>
<tbody>
<% #expenses.each do |expense| %>
<tr>
<td><%= User.joins(:expense).where('expense.user_id = ?', #user.id) %></td>
<td><%= expense.expense_date %></td>
<td><%= expense.currency.currency %></td>
<td align="right"><%= expense.expense %></td>
<td><%= expense.description %></td>
</tr>
<% end %>
</tbody>
</table>
Ok so in your iteration over #expenses you have this line:
<%= User.joins(:expense).where('expense.user_id = ?', #user.id) %>
you can change it to this:
<% user = expense.user %>
Note that I'm using <% not <%= because I'm just trying to assign a variable, not print the output to html.
Then after defining user you can say <%= user.name %>.
You should read a bit more about active record associations, but here's a few side comments about the query you've shown
User.joins(:expense).where('expense.user_id = ?', #user.id)
In this case, you should use the method generated by belongs_to instead of writing a query. But in situations where you do want to write a custom query, you should only be using where when you want to get an array. In this case you're looking for a single record so you could use find_by. Furthermore, the joins you're doing here is unnecessary
# any of these works
user = User.where('id = ?', expense.user_id).first
user = User.where(id: expense.user_id).first
user = user.find_by(id: expense.user_id)
In my application, I am grouping my objects by an ID. At the moment, I can only display the ID, but I would like to display the attribute value.
A Fixture belongs_to a tournament and a tournament has_many fixtures.
Controller
def index
#fixtures = Fixture.all
#tournament_fixture = #fixtures.group_by {|f| f.tournament_id}
end
View
<% #tournament_fixture.sort.each do |tourn_name, fixture| %>
<%= tourn_name %>
<% fixture.each do |f| %>
<td><%= f.home_team %></td>
<td><%= f.away_team %></td>
<td><%= f.kickoff_time %></td>
</tr>
<% end %>
<% end %>
How can I get
<%= tourn_name %>
to display its corresponding value that is in its :name column?
At the moment in my view for example i get this returned
<tbody>
2
<tr>
<td>Tournament Name</td>
<td>Team 1</td>
<td>Team 2</td>
<td>2000-01-01 14:00:00 UTC</td>
<td><a class="btn btn-success" href="/fixtures/1">view</a></td>
</tr>
</tbody>
The 2 needs to be the value in the :name column
I'd recommend grouping by tournament instead:
#tournament_fixture = #fixtures.group_by(&:tournament)
And then iterate using:
<% #tournament_fixture.sort.each do |tournament, fixture| %>
<%= tournament.name %>
...
<% end %>
You can access the whole object much like you can get the id like this:
def index
#fixtures = Fixture.includes(:tournaments).all
#tournament_fixture = #fixtures.group_by {|f| f.tournament.name}
end
The id is still available as either f.tournament_id or f.tournament.id, should you still need it but I just figured you'd rather group by its name directly. I simply added an includes statement to also load the referenced Tournament objects with your fixtures in one go. Otherwise, Rails would load the tournaments only when you access them one by one.
As an alternative, you could load the Tournaments, including all their the fixtures instead and iterate over the tournaments like this:
Controller
def index
#tournaments = Tournament.includes(:fixtures).all
end
View
<% #tournaments.each do |tournament| %>
<%= tournament.name %>
<% tournament.fixtures.each do |f| %>
<td><%= f.home_team %></td>
<td><%= f.away_team %></td>
<td><%= f.kickoff_time %></td>
</tr>
<% end %>
<% end %>
It seems a bit more natural to me and you don't need to iterate over all fixtures to map them by their tournament.
You can load the fixtures in the right order. There is no need to group then in memory. Remember to include the tournaments to avoid N+1 queries.
# controller
def index
#fixtures = Fixture.order(:tournament_id).includes(:tournaments).all
end
Loading in the right order in the controller makes the view simpler. For the tournament's name just use the association between Fixture and Tournament.
# view
<% #fixtures.each do |fixture| %>
<tr>
<td><%= fixture.tournament.name %></td>
<td><%= fixture.home_team %></td>
<td><%= fixture.away_team %></td>
<td><%= fixture.kickoff_time %></td>
</tr>
<% end %>
I am new to ruby and rails so thought I'd ask a question on conventions.
I have a view which produces a list of items in a table and I was asked to make a change and in doing so have added a case statement to the view which I don't think is the correct way of doing things so thought that I would double check.
The change I made was just to add a class to the tr depending on the value of the last table column.
list.rhtml
<table width="100%">
<tr>
<th style="width: 80px;">ID #</th>
<th>Organisation</th>
<th>Product</th>
<th>Carrier</th>
<th>Carrier Ref</th>
<th>Post Code</th>
<th>Status</th>
</tr>
<%= render :partial => 'circuit/list_item', :collection => #circuits %>
</table>
list_item.rhtml
<%
# code I have added
#tr_class = ''
case list_item.status
when 'Handover'
#tr_class = ''
when 'Unprocessed'
#tr_class = 'high_priority'
when 'Ceased'
#tr_class = 'low_priority'
else
#tr_class = ''
end
# end of newly added code
%>
<!-- the class part is new aswell -->
<tr class="<%= #tr_class %>">
<td><a href='/circuit/update/<%= list_item.id %>'><%= list_item.id_padded %></a></td>
<td><%= list_item.organisation.name if list_item.has_organisation? %></td>
<td><%= list_item.product_name %></td>
<td><%= list_item.carrier.name %></td>
<td><%= list_item.carrier_reference %></td>
<td><%= list_item.b_end_postcode %></td>
<td><%= list_item.status %></td>
</tr>
Is there a Rails pattern or convention that can get the case statement out of this view?
If understand properly your question, I think you should put the case statement inside a helper function:
app/helpers/list_helper.rb
module ListHelper
def tr_class_for_status(status)
case status
when 'Unprocessed'
'high_priority'
when 'Ceased'
'low_priority'
else
''
end
end
end
_list_item.rhtml
<tr class="<%= tr_class_for_status(list_item.status) %>">