Loop through array in joining tables - ruby-on-rails

am trying to join tables, i have 3 models
class ClassAdviser < ActiveRecord::Base
has_many :feeds
has_many :students
end
class Feed < ActiveRecord::Base
belongs_to :hod
belongs_to :class_adviser
belongs_to :student
end
class Student < ActiveRecord::Base
belongs_to :class_adviser
has_many :feeds
end
How do iterate through the array and get all rows in the joined table,i want to display the details of each student individually.Below is what i tried but i get only details of feeds.
#get_stds = current_class_adviser.students
#get_stds.each do |d|
#students << d.id
end
#students = #students.flatten
for number in #students
#feeds = Feed.joins(:student).where ("student_id = '#{number}'")
end

A few things:
1) I think it is weird that a feed belongs_to a class_advisor. I would change that to be a class_advisor has_many feeds through students.
2) You should be able to just do
#students = #students.flatten
#feeds = #students.map(&:feeds)

To display each student detail along with their respective feed,here is what i did
Controller
#std_feeds = Feed.where(student: current_class_adviser.students)
View
<tbody>
<% #std_feeds.each do |feed| %>
<tr class="table-row">
<td class="table-img">
<p><%=feed.student.first_name%> <%= feed.student.last_name%></p>
<div><%= feed.created_at.strftime('%d %b %Y')%></div>
</td>
<td class="table-text" rowspan="1">
<%= feed.subject %>
<p class='message'><%= feed.message %></p>
</td>
<td class="march">
<h6>DELETE</h6>
</td>
</tr>
<%end%>
</tbody>
This #std_feeds contains both the student details and feed details,all thanks to Rails Association.

Related

Rails 5 many to many index

I am having a problem in the eyes when presenting the data.
I have 3 user models, sponsors and pets Result that sponsors in a table join between users and pets that are nan, my problem is in the hour to show all the sponsors of the mascot in sight and achievement but in a wrong way to La time to msotrar the data. I hope you can tell me how to fix it. Thank you.
Index.html.erb
<h1>Sponsors#index</h1>
<table class="table table-bordered table-hover table-striped" id="histories">
<thead>
<tr>
<th>Mascota</th>
<th>Padrinos</th>
<th>Apadrinar</th>
</tr>
</thead>
<tbody>
<% #pets.each do |pet| %>
<tr>
<td><%= pet.name %></td>
<td>
<% #users.each do |user| %>
<% #sponsors.each do |sponsor| %>
<% if user.id == sponsor.user_id and pet.id == sponsor.pet_id %>
<%= user.email%>
<% else %>
<p>No Tengo Padinos =-( </p>
<% end %>
<% end %>
<% end %>
</td>
<td><button>Apadrinar</button></td>
</tr>
<% end %>
</tbody>
</table>
My controller has the three models that I am sending to view.
def index
#sponsors = Sponsor.all
#users = User.all
#pets = Pet.all
end
pet.rb
class Pet < ApplicationRecord
has_many :adoptions
belongs_to :race, required: false
has_many :users, through: :sponsors
end
user.rb
class User < ApplicationRecord
has_many :pets, through: :sponsors
end
sponsor.rb
class Sponsor < ApplicationRecord
belongs_to :user
belongs_to :pet
end
The output that now shows me the attachment in the image.enter image description here
I also wonder if there is a better way to make the query, to show the respective data.
Another thing is how would I do to no longer be able to sponsor pets that I have already given a sponsor?
You are using a through table to join users and pets, but your associations aren't setup properly. For a through model, you have to have_many of the through table along with a has_many: :through association. Your associations should look like this:
class Pet < ApplicationRecord
has_many :adoptions
belongs_to :race, required: false
**has_many :sponsors**
has_many :users, through: :sponsors
end
class User < ApplicationRecord
**has_many :sponsors**
has_many :pets, through: :sponsors
end
Afther working and following diferent recomendations here is my solution.
<% #pets.each do |pet| %>
<tr>
<td> <%= pet.name %></td>
<td>
<% if pet.sponsors.any? %>
<% pet.sponsors.each do |sponsor| %>
| <%= sponsor.user_email %> |
<% end %>
<% else %>
<p>No Tengo Padinos =-( </p>
<% end %>
</td>
<td>
<%= link_to "Apadrinar", {:controller => "sponsors", :action => "new", :mascot => pet.id }%>
</td>
</tr>
<% end %>
I changed also my models.
sponsor.rb
class Sponsor < ApplicationRecord
belongs_to :user
belongs_to :pet
has_many :gifts
delegate :email, to: :user, prefix: true, allow_nil: true
end
user.rb
class User < ApplicationRecord
has_many :sponsors
has_many :pets, through: :sponsors
end
pet.rb
class Pet < ApplicationRecord
has_many :sponsors
has_many :users, through: :sponsors
end
And finally mi index on Controller.
sponsors_controller.rb
def index
# #sponsors = Sponsor.all
# #users = User.all
# #pets = Pet.all
# #pets_no_sponsors = Pet.where.not(id: Sponsor.select("pet_id")).select("id")
#pets = Pet.includes(:sponsors)
end
By making a delegation now I only make a query which sends everything necessary to my index.

One-to-one association

I have two models and I want to display them in one table.
Model 1:
class Name < ActiveRecord::Base
has_one :employer, :foreign_key => 'application_id'
end
Model 2:
class Employer < ActiveRecord::Base
belongs_to :name, :foreign_key => 'application_id'
end
Controller:
def summary
#name = Name.all
end
I have this in my view:
<% #name.each do |e| %>
<tr>
<td ><%= e.application_id %></td>
<td ><%= e.Name_of_employee%></td>
<td ><%= e.Employer_name%></td>
</tr>
<% end %>
The name only have one employer.
I am getting "undefined method `Employer' for #
"
TYIA!
as the association is defined,
has_one :employer, :foreign_key => 'application-id'
notice the case employer, so it has to be small case, and not class name
<td ><%= e.employer.name %></td> # name or some other attribute you wish to display
Also, including the association first will help eliminate n+1
#name = Name.includes(:employer)

Active Record query optimizations for two many-to-many join models

I am displaying the following table for a Product model in Rails 4 with ActiveRecord and Postgres SQL:
Here is my ERD, where I am using a couple of many-to-many models, each arrow here represents a one-to-many relationship:
impact_line_items are the row headings ("Total Impacts", "Source" ... etc.).
categories are the column headings ("Greenhouse Gases", "Energy Consumptions" ... etc.)
By adding entries to impact_line_items and categories, I can essentially extend the row and columns of the table
product_impact_line_item represents a reference to a row of data
impact_entry represents a cell of data
Question: Here is what I have in my modesl and products/show.html.erb, displaying the table. It is making 35 queries to get each ImpactEntry, and taking a while to load. I would like to optimize that down and looking for suggestions.
Models:
class Product < ActiveRecord::Base
...
has_many :product_impact_line_items, dependent: :destroy
has_many :impact_line_items, through: :product_impact_line_items
...
end
class ProductImpactLineItem < ActiveRecord::Base
belongs_to :product
belongs_to :impact_line_item
has_many :impact_entries, dependent: :destroy
has_many :categories, through: :impact_entries
def find_impact_entry(category)
impact_entries.find_by_category_id(category.id)
end
end
class ImpactEntry < ActiveRecord::Base
belongs_to :product_impact_line_item
belongs_to :category
end
class ImpactLineItem < ActiveRecord::Base
has_many :product_impact_line_items, dependent: :destroy
has_many :products, through: :product_impact_line_items
validates :name, uniqueness: true
end
class Category < ActiveRecord::Base
has_many :impact_entries, dependent: :destroy
has_many :categories, through: :impact_entries
validates :name, uniqueness: true
end
View:
<table id="impacts-table" class="table table-bordered table-medium">
<thead>
<tr>
<th class="col-md-2"></th>
<% Category.all.each do |category| %>
<th class="col-md-2"><%= category.name %></th>
<% end %>
</tr>
</thead>
<tbody>
<% product_impact_line_items = #product.product_impact_line_items %>
<% product_impact_line_items.all.each do |product_impact_line_item| %>
<tr>
<th scope="row"><%= product_impact_line_item.impact_line_item.name %></th>
<% Category.all.each do |category| %>
<%# byebug %>
<td class="col-md-2"> <%= product_impact_line_item.find_impact_entry(category).value %></td>
<% end %>
</tr>
<% end %>
</tbody>
</table>
Use ProductImpactLineItem.includes(:impact_line_item, :impact_entries) instead of ProductImpactLineItem.all (http://apidock.com/rails/ActiveRecord/QueryMethods/includes)
Change impact_entries.find_by_category_id(category.id) to impact_entries.find{ |ie| ie.category_id == category.id } so it won't call the DB each time
Use the bullet gem to detect n+1 queries in the future

How to use has_many fields in views, rails?

Frnds I am new to rails, here i created two tables caleed stocks and stock_availabilities.
in the stock model
class Stock < ActiveRecord::Base
belongs_to :projects_lkp
has_many :stock_availabilities
validates_presence_of :item
end
In the stock_availabilities model
class StockAvailability < ActiveRecord::Base
belongs_to :stock
validates_presence_of :qty,:add_or_issue,:price, :captured_at, :stock_id,:unit
end
Now my doubt is how to bring the field of stock_availabilties in the views of stock
<% #stock.each do |d| %>
<tr>
<td><%= d.item %></td>
"Here i need to print the values of qty and pricevwhich is in stock_availabilities class"?
</tr>
You are on the right track.
this is what you need:
<% #stock.each do |d| %>
<tr>
<td><%= d.item %></td>
<% d.stock_availabilities.each do |sAV| %>
<td> <%= sAV.qty %> </td>
... <-- You do the other ones here
<% end %>
</tr>

Need data from a many:many join in a Rails view

Its maybe not the best solution in most cases, but i want a table with data form 3 tables.
class Media < ActiveRecord::Base
belongs_to :user
belongs_to :type
has_many :ratings
end
class User < ActiveRecord::Base
has_many :medias
has_many :ratings
end
class Rating < ActiveRecord::Base
belongs_to :user
belongs_to :media
end
Thats the view I want
<table>
<tr>
<th>Name</th>
<th>Comment</th>
<th>Creator</th>
<th>Type</th>
<% for user in #users %>
<th><%=h user.login %></th>
<% end %>
</tr>
<% for media in #medias %>
<tr>
<td><%=h media.name %></td>
<td><%=h media.comment %></td>
<td><%=h media.user.login %></td>
<td><%=h media.type.name %></td>
<% for user in #users %>
<td><%=h GET_RATING (media, user) %></td>
<% end %>%>
</tr>
<% end %>
</table>
Basicly i want one new row for each users ratings for each media
What I want is a Table that looks like that:
media.name media.comment ... rating(media, user).rating
I think it would be better to use a join in the Controller with the Media find methods but I dont know how exactly, enougher possible solution could be helper method that takes media and user as parameters.
What do you think is the best solution for this?
This kind of association belongs in your model, a has many through relationship is perfect for this.
class User < ActiveRecord::Base
has_many :ratings
has_many :media, :through => :ratings
end
class Media < ActiveRecord::Base
has_many :ratings
has_many :users, :through => ratings
end
class Rating < ActiveRecord::Base
belongs_to :user
belongs_to :media
end
Then you can access
media.name media.comment
Then could also access
user.ratings
or:
<% media.users.each do |user| %>
## Do stuff with user.ratings array
<% end %>
You can also:
media.ratings.each do |rating|
rating.your_attribute
rating.user.your_attribute
end

Resources