Rails query to retrieve related association for all query - ruby-on-rails

Beginner # rails here.. When using find_by_id I can retrieve the associated record but I'm unclear on how to do this through the all query. How can I adapt the find_by_id LEFT..JOIN for .all so it also retrieves the associated model.
My fail
#user = User.all.joins(:userpaintings).joins("LEFT JOIN paintings on userpaintings.painting_id = paintings.id")
This works
#user = User.find_by_id(1).joins(:userpaintings).joins("LEFT JOIN paintings on userpaintings.painting_id = paintings.id")

Try this:
#user = User.joins(:userpaintings).joins("LEFT JOIN paintings on userpaintings.painting_id = paintings.id").all
#all will convert the relation into an Array, which you can't run methods such as #joins on.

Related

Rails - Filter the results if they match the association

I have ManytoMany association setup between Model User and Tag, suppose if I do
users = User.all
This will give me all the users, I want to filter these records if they are in ManyToMany association with lets say tag_id 55
For a single object I know I can do users.first.tags.exists?(55) and this will give true or false bot how do I perform this on a users which contains 100's of record?
My questions are
Is using loop the only way to achieve this?
How to remove to records from users where the relationship does not exist?
I have hundreds of records in users so I need to do this in a way it does not effect the performance.
I will really appreciate any feedback on this.
You can access the tag id 55 of user in this way
#user = User.joins(:tags).where("tags.id = ?" ,55)
OR
#user = User.includes(:tags).where(tags: {id: 55})
You can also filter for multiple ids of tag in this way
tags_id = [55,56,57,58,59]
#user = User.joins(:tags).where("tags.id IN = (?)" ,tags_id)
You can find whether associations is exists or not with this query
User.includes(:tags).where( :tags => { :id => nil } ).
It will give all users who dont have any tags.

Ruby on Rails "has_many :through" association return an array

I have created an "has_many :through" association. I have a posts, categories and a categorization model. This categorization model has a Categorizations table which links all the post_ids to category_ids. Every post has multiple categories and every category has multiple posts. I want to list all the posts if I call an category, but to do that I have to make an array and store it in post_ids. This array gets stored in #post_ids. How can I make an array from this: "Categorization.find_by(category_id: #category_id).post_id" and store it in #post_ids?
def index
if params[:category].blank?
#posts = Post.all.order("created_at DESC")
else
#category_id = Category.find_by(name: params[:category]).id
#post_ids = Categorization.find_by(category_id: #category_id).post_id
#posts = Post.where(id: (#post_ids)).order("created_at DESC")
end
Thanks in advance!
After your retrieve the ActiveRecord Object
a = Categorization.where(category_id: #category_id)
Use pluck to retrieve all the post_ids by
a.pluck(:post_id) # Ensure that pluck is a ActiveRecord call and can only be used on Active Record objects.
This approach seems much cleaner.
Simply replace
#post_ids = Categorization.find_by(category_id: #category_id).post_id
with
#post_ids = Categorization.where(category_id: #category_id).map(&:post_id)

Rails - Find with no associated records

I want to select one user and add to it associated records such as child for this example.
But only the child with a specific place_id.
This code works, but when the user doesn't have any child entry I got an error.
#user = User.includes(:child).find(params[:id],
:conditions => ["child.place_id = ?", #place_id])
Here is the error:
Couldn't find User with id=19 [WHERE (child.place_id = 0)]
Thanks !
Try where clause, since you are already using brute SQL. This will not produce error and will either fetch or set to nil:
#user = User.includes(:child).
where("users.id=? AND child.place_id = ?",
params[:id],#place_id).first
PS: Is it child.place_id or children.place_id? ActiveRecord tends to pluralize table names.
EDIT:
This only works if there are children. If you want it to work event without children,do this:
#user = User.joins('LEFT JOIN child on child.user_id = users.id').
where('child.place_id = ? AND users.id = ?', #place_id, params[:id]).
select('users.field1, child.field2 as field3')
If you want specific fields, add them in select method above, which is provided as an example.

Summing child objects rails 4.0

I have a model Task Orders that has_many Invoices. One of my Task Order attributes is "total invoiced". One of my Invoice attributes is "amount". I want a relationship where Total Invoiced = sum of "Amount". I want this to show up in my task_order/index page. Here is my task order index controller:
def index
#task_orders = TaskOrder.all
#invoices = #task_order.invoices
#task_order.invoicedAmount = #task_order.invoices.sum(:amount)
end
I am getting the error undefined method `invoices' for nil:NilClass
I do want to mention that my code in task_order/show works:
def show
#invoices = #task_order.invoices
#task_order.invoicedAmount = #invoices.sum(:amount)
end
As a follow up question, I am much more familiar with SQL queries than I am using Active Record queries. Can someone point me to a guide on how to render the results of a pure SQL query?
Thank you!!
Your index method is not going to work, because you're getting #invoices from #task_order.invoices, but you declare #task_orders instead. Note the singular vs. plural difference.

rails getting attributes of associated model for many objects in one query

My title might be confusing, I wasn't sure what to write.
In rails I understand how to fetch Many Objects for One parent object
#first_user = User.first
#first_user_posts = #first_user.posts
But how can I fetch Many Objects for Many parent objects and select its attributes in one query?. I am trying to do something like that:
#many_posts = Post.all
#posts_by_user_gender = #many_posts.joins(:user).map(&:gender)
hoping it would give me an array that could look something like this:
#posts_by_user_gender => ["male", nil, "female", nil]
#I know I can do this map technique if I fetch it directly from the User model
# User.all.map(&:gender),
# but I want to start with those that posted in a specific category
# Post.where(:category_id => 1)
and then to count the males I could use the Ruby Array method .count
#males_count_who_posted = #posts_by_user_gender.count("male")
=> 1
I could always do 3 separate queries
#males_count_who_posted = #many_posts.select(:user_id).joins(:user)
.where("gender = ?", "male").count
#females_count_who_posted = ...
but I find that extremely inefficient, especially if I do the same for something like "industry" where you could have more than 3 options.
you can join model via SQL syntax
#posts_by_user_gender = #many_posts.joins("LEFT JOIN Users where users.id=posts.user_id").joins("LEFT JOIN Genders where genders.id=user.gender_id")

Resources