Rails 5: Combining two ActiveRecord Models - ruby-on-rails

I'm currently trying to display the users that where invited by the current user and I also want to display the last reservation the made, if they made one.
My Users Controller:
#users = User.where(invited_by_id: current_user.id)
My View:
<% #users.each do |user| %>
<%= user.fullname %> #Works
<%= user.invited_by.fullname %> #Works
<% end %>
What I've already tried:
<% #users.each do |user| %>
<% user.reservations.each do |reservation| %>
<%= reservation.user.fullname %> #Works
<%= reservation.price %> # Works
<% end %>
<% end %>
But this gives me all reservations a user made, I only want the first reservation from the user and therefore only one table for each user.
Is it possible to achieve this in the view or do I need to make some changes in my controller ?

since you only need first reservation from each user, the custom associations (has_one) below can help your query in controller
User.rb
class User < ActiveRecord::Base
has_many :reservations
has_one :first_reservation, -> { order('created_at ASC')}, class_name: "Reservation"
end
User Controller:
#users = User.where(invited_by_id: current_user.id).preload(:first_reservation)
# preload will make sure load the reservation record as well to prevent n+1
your view combined user and first reservation, since you already setup has_one, you can call user.first_reservation
<% #users.each do |user| %>
<%= user.fullname %>
<%= user.first_reservation.price %>
<% end %>

Related

Where's the textNode in the view coming from?

# controller
def index
#teams = TeamMember.where(user: current_user)
end
# view
<%= #teams.each do |t| %>
<h2><%= t.project.name %></h2>
<p>Where's the line below this coming from?</p>
<!-- what's happening here? -->
<% end %>
The result in the browser looks as follows. It returns #projects as a string. Where is this coming from and how do I remove it?
ERB
You trigger ERB by using embeddings such as <% %>, <% -%>, and <%= %>. The <%= %> tag set is used when you want output.
You have used <%= %> for looping projects and the block form of Array#each returns the original Array object, which is why it prints the projects result at the end.
you have to use <% %> for #projects.each do |p| instead of <%= %>
# view
<% #projects.each do |p| %>
<h2><%= p.name %></h2>
<% end %>
Team member Model
class TeamMember < ApplicationRecord
belongs_to :user
belongs_to :project
end
User Model
class User < ApplicationRecord
has_many :team_members
end
Project Model
class Project < ApplicationRecord
has_many :team_members
end
Controller
def index
#teams = current_user.team_members
end
View
<% #teams.each do |t| %> // Remove '=' from the loop itereation
<h2> <%= t.project.name %> </h2>
<% end %>

Map modelA to modelB in controller

I have two unassociated models which normally would be associated. This is however sort of a freak-case where I don't want them to be associated.
In the view, I can do this:
<%= #user.each do |user| %>
<%= Option.where(:id => user.option_1).or(Option.where(:id => user.option_2).each do |option| %>
<% end %>
<% end %>
How can I move that logic to the controller?
If I, in controller do
#user = User.all.map do |user|
#options = Option.where(:id => user.option_1).or(Option.where(:id => user.option_2)
end
The results of #options do not map to the #user object the same way it would #user.options if models were associated.
Is there a way to mimic that functionality when the models are not associated so that when I loop through <% #users.each do %> I can access <% #options.each do %> within that scope the same way I would if :options belonged to :user and :user had many :options
So that the final output in the view would look like this:
<% #users.each do |user| %>
<% #options.each do |option| %>
#Outputs the result of Option.where(:id => user.option_1).......
<% end %>
<% end %>
Since you want to loop options, you should do this
In controller
#options = Option.joins("INNER JOIN users ON users.option_1 = options.id OR users.option_2 = options.id").distinct
In view,
<% #options.each do |option| %>
<% end %>
Give it a try.

act_as_followers get all posts of user I'm following

Im trying to get all the Posts from the the Users. I'm following using the act_as_follower gem. The User follows a profile model, and Posts belong to a User.
My User model:
acts_as_follower
My Profile model the user follows:
belongs_to :user
acts_as_followable
Post model:
belongs_to :user
My Post Controller.rb:
def follow
#profile = Profile.find(params[:id])
current_user.follow(#profile)
redirect_to :back
end
def unfollow
#profile = Profile.find(params[:id])
current_user.stop_following(#profile)
redirect_to :back
end
Im trying to implement something like this using follows_by_type method provided:
#posts = current_user.follows_by_type('Post').order("created_at DESC")
But the thing is the User follows the Profile model, but here I'm looking for a type 'Post'.
EDIT
In my index controller i'v set up the following:
#favoritePost = Post.where(user_id: current_user.all_follows.pluck(:id))
And in the view iv implemented this:
<% if user_signed_in? %>
<%#favoritePost.each do |post| %>
<%= post.title %>
<% end %>
<% end %>
The gem lets you follow multiple models and follows_by_type('Post') filters the Posts you follow.
What you're looking to do is to return the posts from the users you follow.
Controller
#posts = Post.where(user_id: current_user.all_following.pluck(:id))
View
<% #posts.each do |post| %>
<%= post.title %>
<% end %>
I worked out this solution, might not be the best, but it works as required.
In my controller i set this up:
#following = current_user.all_following
#followposts = #following.each do |f|
f.user.id
end
And in my view I have set this up:
<% #followposts.each do |f| %>
<% f.user.posts.each do |g| %>
<%= g.title %>
<% end %>
<% end %>

How can I get data from multiple table association in rails?

I want to get data from multiple table in rails,but it is not working.
Here is my code.
Category.rb
has_many :posts
post.rb
has_many :mini_posts
belongs_to :category
mini_post.rb
belongs_to :post
controller
#posts = Category.find(params[:id]).posts.mini_posts
viewfile
<% #posts.each do |post| %>
<%= post.title %>
<%= post.description %>
<% post.mini_posts.each do |mpost| %>
<%= mpost.name %>
<%= mpost.experience %>
<% end %>
<% end %>
The error shows "undefined method `mini_posts'.
How can I solve this?
Your code is chaining methods, and returning mini posts, not eager loading the mini posts which is what I assume you want.
You want either
#posts = Post.includes(:mini_posts).where(category_id: params[:id])
Or
#category = Category.includes(posts: :mini_posts).find(params[:id])
#posts = #category.posts
Change
#posts = Category.find(params[:id]).posts.mini_posts
to
#posts = Category.find(params[:id]).posts

Rails retrieving associated information

I fail to find the correct syntax to retrieve associated information. I have a model 'companyaccount' that belongs to a model 'company'.
class Company < ActiveRecord::base
has_many :companyaccounts
end
class Companyaccount < ActiveRecord::base
belongs_to :company
end
In the View, I can easily retrieve both the 'Companyaccount' 'number' and the 'id' of the associated company through the 'company_id' field of the 'companyaccount' table.
<%= #companyaccount.each do |companyaccount| %>
<%= companyaccount.company_id %>
<%= companyaccount.number %>
<% end %>
The View is called from this basic Controller
def index
#companyaccount = Companyaccount.all
end
Now, I do not want to have the company_id but the actual name of the company (housed in the 'company' table). I manage to do it for one specific company using a controller like this
def index
#companyaccount = Companyaccount.all
#company = Company.first
end
and then in the view change
<%= companyaccount.company_id %>
by
<%= company.name %>
but of course, this will retrieve, for each companyaccount, the same first company and not each of the company associated with the companyaccount. Could anyone provide me with the appropriate syntax to retrieve the associated company's name for each companyaccount in the "each" loop of my View? Thanks.
You can use delegate for this.
class Companyaccount < ActiveRecord::base
belongs_to :company
delegate :name, to: :company, prefix: true
end
and then you can call <%= companyaccount.company_name %>
You should be able to achieve what you want with this loop:
<%= #companyaccount.each do |companyaccount| %>
<%= companyaccount.company.name %>
<%= companyaccount.number %>
<% end %>
def index
#companyaccount = Companyaccount.all
end
and in view
<% #companyaccount.each do |companyaccount| %>
<%= companyaccount.company.name %>
<% end %>
for less db call you can change controller like
#companyaccount = Companyaccount.includes(:company).all

Resources