How can I display values from relationship on column array? - ruby-on-rails

I have 2 tables (users and meetings).
I'm trying to displaying the name of the user on table index view
users
|id| |name|
1 DEMO 1
2 DEMO 2
3 DEMO 3
meetings
|id| |user_id|
1 ["1", "2"]
2 ["2"]
3 ["2", "3"]
The Controller /app/controllers/meetings_controller.erb
def index
#meetings = Meeting.all
end
Models
#meeting.rb
class Meeting < ApplicationRecord
belongs_to :users
end
#user.rb
class User < ApplicationRecord
has_many :meetings
end
The View /app/views/meetings/index.html.erb
<table>
<thead>
<tr>
<td>id</td>
<td>User Names</td>
</tr>
</thead>
<tbody>
<% #meetings.each do |meeting| %>
<tr>
<td><%= meeting.id %></td>
<td><%= meeting.user_id %></td>
</tr>
<% end %>
</tbody>
</table>
I'm trying to display the user_id on array relationship and i tried this code:
I got the following error using the following code
undefined method `each' for "[\"1\", \"2\"]":String
<% meeting.user_id do |array|%>
<%= array.user.name %>
<% end %>
I got the following error using the following code
undefined method `each' for "[\"1\", \"2\"]":String
<% meeting.user_id do |array|%>
<%= array %>
<% end %>
I cannot display the value relationship because of column array.
Can you please help me with this issue?
Thanks in advance.

While there is nothing wrong with your approach, one comes to understand that the path of least resistance (= least pain) is to follow "The Rails Way".
So instead of answering your question, let me suggest that the relationship between your models should be:
# user.rb
class User < ActiveRecord::Base
has_and_belongs_to_many :meetings
end
# meeting.rb
class Meeting < ActiveRecord::Base
has_and_belongs_to_many :users
end
# you will also need to create a join table with a migration:
def change
create_join_table :meetings, :users
end
Then the view will include:
<% #meetings.each do |meeting| %>
<tr>
<td><%= meeting.id %></td>
<td><%= meeting.users.map(&:name).join(', ') %></td>
</tr>
<% end %>

I assume that you have a has_many relation between Meeting and User. That means that meeting.users will return the list of the users for the current meeting.
The following will return a comma-separated string with the names.
<table>
<thead>
<tr>
<td>id</td>
<td>User Names</td>
</tr>
</thead>
<tbody>
<% #meetings.each do |meeting| %>
<tr>
<td><%= meeting.id %></td>
<td><%= meeting.users.map(&:name).join(', ') %></td>
</tr>
<% end %>
</tbody>
</table>

Related

Trying to display records from chained models on Rails 5.2

Following on from this question
class CoffeeRoast < ApplicationRecord
has_many :coffee_blends
has_many :coffee_beans, through: :coffee_blends
has_one :country, through: :coffee_beans
end
class CoffeeBean < ApplicationRecord
has_many :coffee_blends
has_many :coffee_roasts, through: :coffee_blends
belongs_to :country
end
class Country < ApplicationRecord
has_many :coffee_beans
end
class CoffeeBlend < ApplicationRecord
belongs_to :coffee_bean
belongs_to :coffee_roast
end
I am able to show the related coffee_beans on the coffee_roasts show page, and also the country, however, I can not work out how to display them correctly.
My current code is attempting to show the bean and its related country on the same row on the table, however the top is blank and the two countries are both in the second row.
coffee_roasts/show.html.erb
<h1 class="display-3"><%= #coffee_roast.name %></h1>
<p>
by <h2 class="display-6"><%= #coffee_roast.roaster.roaster_name %></h2>
</p>
<div class="table-responsive">
<table class="table">
<thead>
<tr>
<th>Bean</th>
<th>Country</th>
</tr>
</thead>
<tbody>
<% #coffee_roast.coffee_blends.each do |blend| %>
<tr>
<th><%= blend.coffee_bean.name %>
<% end %></th>
<th><%= #coffee_roast.coffee_beans.map {|cb| cb.country.country_name }.join(', ') %></th>
</tr>
</tbody>
</table>
Bean | Country
El Martillo |
Finca La Cumbre | El Salvador, Guatemala
El Salvador show be in-line with the El Martillo bean.
My approach feels quite wrong here, but I'm pretty new to working with multiple levels of models so still learning.
How can I get the beans associated country to display alongside the bean?
This was actually a lot simpler than I thought. I've found the below works perfectly. No need to map an array.
<tbody>
<% #coffee_roast.coffee_blends.each do |blend| %>
<tr>
<td><%= blend.coffee_bean.name %></td>
<td><%= blend.coffee_bean.country.country_name %></td> #this bit was the original concern.
<td><%= blend.coffee_bean.variety %></td>
<td><%= blend.coffee_bean.process %></td>
<% end %>
</tr>
</tbody>
<tbody>
<% #coffee_roast.coffee_blends.each do |blend| %>
<tr>
<td><%= blend.coffee_bean.name %></td>
<td><%= #coffee_roast.coffee_beans.map {|cb| cb.country.country_name }.join(', ') %></td>
</tr>
<% end %>
</tbody>
try and see if this works?

Rails loop in table by column and group

I'm looking to produce a looped table that has 3 results for each treatment. I want to one row to contain the date, degrees then list each individual treatment.
Controller
#trial = Trial.find(params[:trial_id])
#max_length = [#trial.treatment_selections].map(&:size).max
Model
has_many :treatment_selections, primary_key: 'trial_id'
has_many :assessments, primary_key: 'trial_id'
has_many :methods, through: :assessments
So far I have this:
<table class="table table-bordered">
<th>Date</th>
<th>Degree</th>
<% #max_length.times do |data| %>
<th><%= #trial.treatment_selections[data].try(:treatment).try(:name) %></th>
<% end %>
<% #max_length.times do |data| %>
<% #trial.methods.order(:treatment_selection_id).order("assessment_date ASC").in_groups_of(3)[data].each_with_index do |e, index| %>
<tr>
<td></td>
<td><%= Time.at(e.try(:assessment).try(:assessment_date)/1000).strftime("%d/%m/%Y") rescue 0 %></td>
<td><%= e.try(:assessment).try(:degrees) rescue 0 %></td>
<td><%= e.try(:total).round(1) rescue 0 %></td>
</tr>
<% end %>
<% end %>
</table>
Which produces this:
But i'd like it to produce this:
I would say there is at least two problems in your code:
1_ Your one liner seems to not work as you think, test the result in console to be sure it's really what you expect. We can't help you more without more details about your models.
<% #trial.methods.order(:treatment_selection_id).order("assessment_date ASC").in_groups_of(3)[data].each_with_index do |e, index| %>
2_ You can't fill columns 4 (Treatment 2), 5(Treatment 3), 6(Treatment 4) if you only have one <td>...</td> after your <td>...degre...</td>.
You probably need to put a loop here as you did for your <th>treatment x</th>
I guess each row in your last table is an assessment, and each column (treatment 1 to 4) for each assessment is a method. So you would need nested loops:
<% #trial.assessments.order("assessment_date ASC").each do |a| %>
<tr>
<td></td>
<td><%= Time.at(a.try(:assessment_date)/1000).strftime("%d/%m/%Y") rescue 0 %></td>
<td><%= a.try(:degrees) rescue 0 %></td>
<% a.methods.each do |m| %>
<td><%= m.try(:total).round(1) rescue 0 %></td>
<% end %>
</tr>
<% end %>

Displaying has and belongs to many associations in index

Hey I'm new to Rails and all this so bear with me, thanks!
I have two models:
class User < ApplicationRecord
has_and_belongs_to_many :sports
end
class Sport < ApplicationRecord
has_and_belongs_to_many :users
end
My users have a few different sports that they can choose each. I'm simply trying to display all users in a table, along with which sports they do. However.. the only way I've managed to get anything without an error is by using current_user as shown below. I've been looking how to do this for hours... I know it's going to be stupidly simple but I just can't figure it out or even know how to go in the right direction.
# users_controller.rb
def index
#users = User.all
#sports = current_user.sports
end
# users/index.html.erb
<% #users.each do |user| %>
<tr>
<td><%= link_to user.name, user %></td>
<td><%= link_to user.email, user %></td>
<% #sports.each do |s| %>
<td><%= s.name %></td>
<% end %>
</tr>
<% end %>
That's my current code but obviously this shows only the signed in users associations and repeats it for the other users like this:
<table>
<tr>
<th>Name</th>
<th>Sport 1:</th>
<th>2:</th>
</tr>
<tr>
<td>User 1 (current_user)</td>
<td>Football</td>
<td>Running</td>
</tr>
<tr>
<td>User 2</td>
<td>Football (User 1's Sports)</td>
<td>Running </td>
</tr>
</table>
Thanks in advance.
You can try using the following and deleting #sports = current_user.sports:
<% user.sports.each do |s| %>
<td><%= s.name %></td>
<% end %>
using user.sports while looping through each of the user will lead to N+1 queries on your database. You can change your controller method to something like
def index
#users = User.all.eager_load(:sports)
end
and then in html
<% user.sports.each do |s| %>
<td><%= s.name %></td>
<% end %>
This will load users along with left_outer_join on sports table and this will save to lot of extra queries on your database.
For Info you can refer this good blog.
Thanks

Rails Way of Grouping By an Association

I know I am making this more difficult than it needs to be. There has to be a rails way of accomplishing this task. To demonstrate: here are two models:
#app/models/user.rb
class User < ActiveRecord::Base
has_many :blogs
def to_s
name
end
end
#app/models/blog.rb
class Blog < ActiveRecord::Base
belongs_to :user
delegate :name, to: :user, prefix: true, allow_nil: true
def to_s
title
end
end
So what I want to do is group all of the blogs by the associated user. Then I want to list those blogs per each user.
Key Detail: not all blogs have an associated user. Some have user_id = nil. Here is a listing of the blogs to demonstrate (last two blogs have user_id = nil):
So I got what I wanted to work. But the solution is not easy to read, and I know there must be some way to accomplish this using Rails' query interface. I couldn't figure it out though, so I hacked together my own solution below:
#app/controllers/admin_controller.rb
class AdminController < ApplicationController
def index
#group_blogs_by_user = {}
User.all.pluck(:name).each{|user| #group_blogs_by_user[user] = []}
#group_blogs_by_user[nil] = [] #provide nil category when no user_id was specified for a blog
Blog.all.each {|blog| #group_blogs_by_user[blog.user_name].push(blog)}
#group_blogs_by_user.reject!{ |_ , v|v.empty?} #do not show users that have no blogs
end
end
And here is the view to display it:
#app/views/admin/index.html.erb
<h1>Showing Count of Blogs per User</h1>
<table>
<thead>
<th>User</th>
<th>Blogs Count</th>
</thead>
<tbody>
<% #group_blogs_by_user.each do |user, blogs_of_this_user| %>
<tr>
<td><%= user || "No User Specified"%></td>
<td><%= blogs_of_this_user.size %></td>
</tr>
<% end %>
</tbody>
</table>
<hr>
<h1>Showing Breakdown of Blogs per User</h1>
<% #group_blogs_by_user.each do |user, blogs_of_this_user| %>
<h3><%= (user || "No User Specified") + " (#{blogs_of_this_user.size} blogs)" %></h3>
<table class="table">
<thead>
<th>Blog ID</th>
<th>Created At</th>
</thead>
<tbody>
<% blogs_of_this_user.each do |blog| %>
<tr>
<td> <%= link_to(blog.id, blog)%></td>
<td> <%= blog.created_at.strftime("%d-%m-%Y")%></td>
</tr>
<% end %>
</tbody>
</table>
<% end %>
And here is what it renders, which is what I want:
I run into this situation all the time where I want to group a table by some association, and I find myself continually hacking together a solution. How can I do this the rails way with Rails' Query Interface?
To get all the blogs from a user and print the username, blog_id and blog count
<% #users.each do |user| %>
<%= user.name %>
<%= user.blogs.count %>
<% user.blogs.each do |blog|%>
<%= blog.id %>
<% end %>
<% end %>
To get the amount of blogs with no user
<%= Blog.where(user: nil).count %>
I hope I got your question right and this helps!

Ordering results in show view

I've got two models - service_request_work_plan where service_request_work_plan has_many work_plan_tasks and work_plan_tasks belongs to service_request_work_plan. The linkage works, associations render properly and I have the code below in my show view for service_reqeust_work_plan, the goal of which is to show the work_plan_tasks in order. The show action works properly, but they are not showing in order (i.e. order_of_exeuction). What am I missing?
<table>
<tr>
<th>Order of Execution</th>
<th>Task</th>
<th>SLO</th>
<th>Task Instructions</th>
</tr>
<% #service_request_work_plan.work_plan_tasks.each do |work_plan_task| %>
<tr>
<td><%= work_plan_task.order_of_execution %></td>
<td><%= work_plan_task.task_name %></td>
<td><%= work_plan_task.task_slo %></td>
<td><%= work_plan_task.task_instructions %></td>
</tr>
<% end %>
</table>
class ServiceRequestWorkPlan < ActiveRecord::Base
attr_accessible :testing_company_id, :work_plan_name, :work_plan_comments
belongs_to :testing_company
has_many :work_plan_tasks
end
class WorkPlanTask < ActiveRecord::Base
attr_accessible :testing_company_id, :task_name, :task_instructions, :service_request_work_plan_id, :task_slo, :order_of_execution
belongs_to :testing_company
belongs_to :service_request_work_plan
end
def show
#service_request_work_plan = ServiceRequestWorkPlan.find(params[:id])
end
Add a .order(order_of_execution: :asc) for work_plan_tasks when querying the database from the controller. See http://guides.rubyonrails.org/active_record_querying.html#ordering
Controller:
def show
#service_request_work_plan = ServiceRequestWorkPlan.find(params[:id]).work_plan_tasks.order(order_of_execution: :asc)
end
Change this line:
<% #service_request_work_plan.work_plan_tasks.each do |work_plan_task| %>
into this line:
<% #service_request_work_plan.work_plan_tasks.all.order(:order_of_execution).each do |work_plan_task| %>
Default order is ascending, so the above line is complete. If you need descending order:
order(:order_of_execution => :desc)

Resources