Want to achieve
ruby 2.6.5 rails 6.0.3
Thank you for your interest. I am creating a web application with rails.
I would like to know how to extract only the data of the columns I want from multiple tables, put them into an array, and then output them using each.
Details
I want to extract the relevant users.name, companies.company_name, and tasks.task_name from the following table and put them into an array as a single unit. I want to output the array we have created in this way, one at a time, using each in erb.
Like this
・john Acompany task3
・white Dcompany task12
・carl Bcompany task8
・mark Ccompany task97
tables
users table
id | name | sex | company_id |
---|---|---|---|
1 | john | 1 | 1 |
2 | white | 1 | 4 |
3 | carl | 1 | 2 |
4 | mark | 1 | 3 |
companies table
id | company_name | industry_1 | industry_2 |
---|---|---|---|
1 | Acompany | 3 | 9 |
2 | Bcompany | 6 | 10 |
3 | Ccompany | 1 | 3 |
4 | Dcompany | 4 | 8 |
tasks table
id | task_name | company_id |
---|---|---|
1 | task3 | 1 |
2 | task12 | 4 |
3 | task97 | 3 |
4 | task8 | 2 |
Tried
I thought that I could pack each element into an array as shown below. But I couldn't imagine how to implement it, so I gave up.
user_name = []
users.each do |user|
user_name << user.name
end
CodePudding user response:
You can use the joins
method from ActiveRecord and get the columns you're looking for with pluck
:
user_details = User.joins(company: :tasks).pluck("users.name", "companies.company_name", "tasks.task_name")
#=> [["john", "Acompany", "task3"], ["white", "Dcompany", "task12"], ...]
Next, iterate over the array of arrays that was returned from the above code to display the data in the way you want. Keep in mind in that in your DB architecture a company has_many
tasks so you may end up with several arrays for the same company if that company has more than one task.
user_details.each do |user_detail|
puts "・ " user_detail.join(" ")
end
Other (and preferred) solution based on comment from max :
User.includes(company: :tasks).each do |user|
# Here you can retrieve and display the data you need using user.name, user.company.name, user.company.tasks
end
CodePudding user response:
This is not a good idea. By passing arrays from your controller to the view you're skipping the model layer completely and skipping all it provides in terms of desearialization and encapsulation (and more). Dealing with simple arrays also destroys the readability of the code:
# which one of these was what now?
<tr>
<td><%= data[0] %></td>
<td><%= data[1] %></td>
</tr>
It is after all a MVC framework built in an object oriented language. Your code should not look like that.
Instead you can either use eager loading and delegation:
class User < ApplicationRecord
belongs_to :company
delegate :name, to: :company, prefix: true
end
@users = User.eager_load(:company)
.all
<table>
<thead>
<tr>
<th>Name</th>
<th>Company</th>
</tr>
</thead>
<tbody>
<%= @users.each do |user| %>
<tr>
<td><%= user.name %></td>
<td><%= user.company_name %></td>
# ...
</tr>
</tbody>
<% end %>
In some cases you may want to use joins
instead to just select a single column or an aggregate from the assocation through:
class UsersController
def index
@users = User.joins(:company)
.select(
'users.*', 'companies.name AS company_name'
)
end
end
When it comes to tasks you have to figure out what it is that you want to actually display. Since the assocations is most likely many to many to both users and companies its not clear which task should even be listed. All of them? The first? The last?