Select the favorite groups - sql

I have a model favorit_group (user:references, group:references).
And would like to find all the favorites groups of my User with something like that :
current_user.fav_groups
I suppose that i have to write something like this in my model User, but it's not working
has_many :favorit_groups, dependent: :destroy
has_many :fav_groups, through: :favorit_groups, class_name: "Group"
Is anyone who is working with this kind of association ? Or should I have to join and merge the model favorit_groups inside my User model ?

As the relation name fav_groups is not the same as the relation name between FavoritGroup and Group, Rails does not not how to fetch those records.
Luckily, has_many accept a source option:
has_many :fav_groups, source: :group, through: :favorit_groups, class_name: "Group"
See full explanation here: https://stackoverflow.com/questions/tagged/ruby-on-rails

Its look like there is many to many relationship between user and group
class User
has_many :favorit_groups, dependent: :destroy
has_many :fav_groups, through: :favorit_groups, source: :group
end
Try
current_user.groups which will automatical fire a join query and fetch those groups that are marked favorite by the use i.e those groups for which an entry is present in favorit_groups table

Related

Querying for records where all records in an association meet multiple criteria

Let's say I have four tables, albums, songs, tags, and song_tags, and their relevant models in Rails, and I want to find all albums where every song has the tags with ids 1, 2, and 3. For this example, let's say I'm looking for some workout albums and I want every song in them to be tagged "rock", "energetic" and "instrumental".
Is there a simple way to find this with a small number of queries?
EDIT:
To clarify, song_tags is a join table for a many-to-many relationship between songs and tags, so my associations are as follows:
#app/models/albums.rb
has_many :songs
#app/models/songs.rb
has_many :song_tags
has_many :tags, through: :song_tags
belongs_to :album
#app/models/tags.rb
has_many :song_tags
has_many :songs, through: :song_tags
#app/models/song_tag.rb
belongs_to :tag
belongs_to :song
There is an ActiveRecord way to do it: .includesAPI dock
Assumed relationships
I've assumed you have the following code:
#app/models/albums.rb
has_many :songs
#app/models/songs.rb
has_many :tags
belongs_to :album
#app/models/tags.rb
belongs_to :song
has_one :song_tag
#app/models/song_tag.rb
Query Interface
Essentially what you would do is chain a call starting with the Album class.
Album.includes(songs: {tags: :song_tags}).where('song_tags.name = ?', ['instrumental', 'rock', 'energetic'])
Some additional information on this can be found at the API.rubyonrails.org

Rails has_many through query

I have many-to-many relationship with User, Attachment and Form model.
I want to reach to attachments not belongs to a user. I will try something like this but did not work.
Attachment.includes(:forms,:users).where.not('forms.user_id = ?', #user.id).references(:forms,:users)
I have tried more but did't find the correct one.
user.rb
has_many :forms
has_many :attachments, through: :forms
attachment.rb
has_many :forms
has_many :users, through: :forms
forms.rb
belongs_to :user
belongs_to :attachment
Update:
I m still finding an answer
Attachment.includes(:forms).where(forms: {user_id: user.id}).references(:forms)
is working but where.not returns empty
I think where.not only looks the attachments related to forms not all of them
It's actually pretty simple:
The first (sub)query you will need is to get all the attachments the user does have:
subquery = #user.attachments.select(:id)
Then you can easily get all the attachments that don't have the id's from the subquery.
Attachment.where.not(subquery)
# same as
Attachment.where.not(#user.attachments.select(:id))
Leading to the query:
SELECT "attachments".*
FROM "attachments"
WHERE ("attachments"."id" NOT IN (
SELECT "attachments"."id"
FROM "attachments"
INNER JOIN "forms"
ON "attachments"."id" = "forms"."attachment_id"
WHERE "forms"."user_id" = $1
))

Nested association query

Class User
has_many :universities
end
Class University
belongs_to :user
has_many :courses
end
Class Course
belongs_to :university
end
Now, I want to find the courses of any user.
I can use the following query:
User.find(1).universities.collect{|x| x.courses}
But is there any other simple ways to get this result? Please explain your answer so that I can understand.
Thanks in advance!
Add into User model:
has_many :courses, through: :universities
Now you can fetch all courses of a user via:
User.find(1).courses
From docs (http://guides.rubyonrails.org/association_basics.html#the-has-many-through-association):
A has_many :through association is often used to set up a many-to-many connection with another model. This association indicates that the declaring model can be matched with zero or more instances of another model by proceeding through a third model.

Generic many-to-many polymorphic association using through?

Before ask that, I must say that I really searched the web trying to find the answer, but I didn't found any that solved my problem. Answers like that doesn't solve my problem, because I don't want specify source_type, I want a generic thing - you'll understand.
Okay, let's go. I'm using a "many-to-many polymorphic" relationship in my project, but I can't get it to work. Before try to use polymorphic, this was just a "many-to-many" relationship and worked very well, so I want keep the structure, just adding polymorphic.
Structure:
Many-to-many: A user and visitor has many subject, and vice versa. We assume that user and visitor are followers and subject is followed.
Relationship table: This objects have a relationship table called "psrelations" (person-subject relations). This table stores the many-to-many relationship.
Models:
psrelations.rb:
attr_accessible :followed_id, :follower_type, :follower_id
belongs_to :follower, polymorphic: true
belongs_to :followed, class_name: "Subject"
user.rb:
has_many :psrelations, as: :follower, dependent: :destroy
has_many :followed_subjects, through: :psrelations, source: :followed
visitor.rb:
has_many :psrelations, as: :follower, dependent: :destroy
has_many :followed_subjects, through: :psrelations, source: :followed
subject.rb
has_many :psrelations, as: :followed, dependent: :destroy
has_many :followers, through: :psrelations, source: :follower
I want that "followers" return all "visitors" and "users", not just one or other, like specifying source_type.
Everything appears to be okay, but when I try to self.followers.include?(person) (where person can be either user or visitor), I got:
Cannot have a has_many :through association 'Subject#followers' on the polymorphic object 'Follower#follower'.
What am I doing wrong?

Unique Association :through

I have a many to many :through relationship between a set of classes like so:
class Company
has_many :shares
has_many :users, :through => :shares, :uniq => true
end
class User
has_many :shares
has_many :companys, :through => :shares, uniq => true
end
class Share
belongs_to :company
belongs_to :user
end
I want to ensure a unique relationship so that a user can only have one share in any one company, which is what I have tried to achieve using the "uniq" argument.
At first I thought this was working, however it seems the behaviour os the "uniq" is to filter on the SELECT of the record, not pre-INSERT so I still get duplicate records in the database, which becomes an issue if I want to start dealing with the :shares association directly, as calling user.shares will return duplicate records if they exist.
Can anyone help with an approach which would force truely uniq relationships? so that if I try adding the second relationships between a user and a company it will reject it and only keep the original?
Have you tried adding this to your Share class?
validates_uniqueness_of :user, scope: :company
Also, in your User class I think it should be:
has_many :companies, through: :shares
I hope that helps.