get object using has many through with polymorphic association - ruby-on-rails

I am using rails 5.
Here I am using has many through with polymorphic
Tables are
categories, category_items, albums
Models are
Category, CategoryItem, Album
app/model/album.rb
class Album < ApplicationRecord
has_many :category_items, as: :category_itemable, dependent: :destroy
has_many :categories, through: :category_items
end
app/model/category.rb
class Category < ApplicationRecord
has_many :category_items, dependent: :destroy
end
app/model/category_item.rb
class CategoryItem < ApplicationRecord
belongs_to :category_itemable, polymorphic: true, optional: true
belongs_to :category, optional: true
end
I am able to get categories of a specific album through association. but now I need to get albums of a specific category.
Please find the solution and make sure don't use method. association should be clean and simple
Many Thanks in Advance

You just need to add a has_many association for album in Category model
class Category < ApplicationRecord
has_many :category_items, dependent: :destroy
has_many :albums, through: :category_items, source: :category_itemable, source_type: 'Album'
end
And now you will be able to get albums for a category instance

Related

Is this database relation schema correct?

I made my first project and got into problem that I couldn't get the right category_information values for specific competitions category through relations. So I started thinking that this could be the wrong schema for this task, so my question - is it actually wrong?
Current Scheme:
Assuming the following relationships between models from your image.
class Competition < ApplicationRecord
has_many :categories
has_many :informations
has_many :category_informations, through: :categories
end
class Category < ApplicationRecord
belongs_to :competetion
has_many :category_informations
has_many :information, through: :category_informations
end
class CategoryInformation
belongs_to :catagory
belongs_to :information
end
class Information < ApplicationRecord
belongs_to :competetion
has_many :category_informations
has_many :catagory, through: :category_information
end
Model can relates with one_to_many_to_many using :through option
It explains a association used to set up a many-to-many connection with another model.
you can get the category_informations from competition like
Competition.first.category_informations
It is all for doing! Pretty good, right?
And you could do get information from category too
Category.first.informations
Actually wrong schema doesn't exist, just there exists some wrong association description.
You can get more usage to use association from docs at 2.3 section and 4.3 section
Assuming the following relationships between tables,
A competition has_many categories,
A competition has_many information,
A category has_many information,
A category has_many competition,
An information has_many category
You can use has_many_through relationships
class Category < ApplicationRecord
has_many :category_competitions
has_many :competitions, through: :category_competition
has_many :category_informations
has_many :informations, through: :category_informations
end
class Information < ApplicationRecord
has_many :category_informations
has_many :categories, through: :category_informations
end
class Competition < ApplicationRecord
has_many :category_competition
has_many :categories, through: :category_competitions
end
class CategoryCompetition < ApplicationRecord
belongs_to :category
belongs_to :information
end
class CategoryInformation < ApplicationRecord
belongs_to :category
belongs_to :information
end
By this way you can access,Categories of a particular competition by #competition.categories
This article might be helpful for you to understand associations better
https://www.sitepoint.com/master-many-to-many-associations-with-activerecord/

Join Table Confusion Ruby on Rails

I have read a lot of the questions and answers here about join tables, STI tables, and polymorphic associations, in addition to many articles and documentation spread throughout the internet. While I've learned a lot I'm still confused about what I should do in my situation. I may have read the answer and not known I was reading the answer, but I wanted to see if someone could help me understand what it is I should do here.
I have a Gallery model, an Album model, an Image model and a Category model. These are all nested in a User model.
When you create an Album assign a Category to it and those are saved with an Album_Categories model. I want the Gallery model to be aware of what Categories exist and be able to choose which ones it would like to use.
Once it selects a Category, it should be able to access the Albums associated with the Category and the Album's Images, which are linked through and Album_Images join table. The Category should be able to continue to exist even if the Album or Gallery that it was originally created with is deleted so that another Album or Gallery can take advantage of it later.
My sense is that whenever a unique Category is created is should some how connect to Gallery through a Category_Galleries model, but in my use of Images which is connected to Gallery and Album with their own specific join tables, Gallery is unaware of an Album_images Connection, so I assume sharing the knowledge of a Category created by the other would be the same.
Any way to help me unerstand this would be appreciated.
Edit: model code
class User < ActiveRecord::Base
has_many :images, dependent: :destroy
has_many :galleries, dependent: :destroy
has_many :albums, dependent: :destroy
has_many :categories, dependent: :destroy
accepts_nested_attributes_for :images, :galleries, :albums, :categories, allow_destroy: true
accepts_attachments_for :images, attachment: :file, append: true
end
class Image < ActiveRecord::Base
belongs_to :user
has_many :gallery_images, dependent: :destroy
has_many :galleries, through: :gallery_images
has_many :album_images, dependent: :destroy
has_many :albums, through: :album_images
attachment :file, type: :image
validates :file, presence: true
end
class Album < ActiveRecord::Base
belongs_to :user
validates :user_id, presence: true
has_many :album_galleries
has_many :galleries, through: :album_galleries # , dependent: :destroy
has_many :album_images, dependent: :destroy
has_many :images, through: :album_images
has_many :album_categories
has_many :categories, through: :album_categories
accepts_attachments_for :images, attachment: :file, append: true
accepts_nested_attributes_for :images
end
class Gallery < ActiveRecord::Base
belongs_to :user
validates :user_id, presence: true
has_many :gallery_images, dependent: :destroy
has_many :images, through: :gallery_images
has_many :album_galleries, dependent: :destroy
has_many :albums, through: :album_galleries
accepts_attachments_for :images, attachment: :file, append: true
accepts_nested_attributes_for :images
end
class Category < ActiveRecord::Base
belongs_to :user
validates :user_id, presence: true
has_many :albums, through: :album_categories
has_many :album_categories
end
class GalleryImage < ActiveRecord::Base
belongs_to :gallery
belongs_to :image
end
class AlbumCategory < ActiveRecord::Base
belongs_to :category
belongs_to :album
end
class AlbumGallery < ActiveRecord::Base
belongs_to :gallery
belongs_to :album
end
class AlbumImage < ActiveRecord::Base
belongs_to :album
belongs_to :image
end
It really depends on the requirements you're trying to model. Does this accurately reflect your requirements? (ignoring the user for the current moment and not necessarily detailing rails associations)
A gallery can consist of many categories
A category can contain many albums
An album can have many images
If so, you could simply have:
a has_many through association between galleries and categories
a has_many through association between albums and categories
a has_many through association between albums and images
The has_many through will allow your categories, galleries, albums and images to exist even after relations are destroyed.
At the moment I don't see any need for STI or polymorphism. Usually you use polymorphic associations when two models share (own) the same table. But since you would use has_many through associations, polymorphism wouldn't even be necessary. (It prevents clashes of the owning table ids when occuring as a foreign key in the owned table).
To get to images, from gallery, for example you would be essentially displaying all the images of all albums belonging to all categories that are assigned to a gallery. That can be done through associations and querying.
So basically, I don't think your scenario...based on my understanding...is too complex and has_many through associations should suffice.
An interesting question would by why a user is associated to all of your models. Are they responsible for creating/those model instances a user is associated to?

Creating a custom validation across two HMT associations

I have two HMT associations. The first is between my Artist and Album models, basically signifying that multiple artists can belong to an album. The other association is setup between my Artist and Track models via TrackFeature. The purpose of this association is add a featured artist to a track.
I'd like to setup a validation that none of the possible album artists cannot be featured artists on any tracks pertaining to that particular album. I know that this validation would need to be on the join model. The problem is that what I have now doesn't seem to work. What do I need to change in order for this to successfully validate?
class Artist < ActiveRecord::Base
has_many :album_artists
has_many :albums, through: :album_artists
has_many :track_features
has_many :tracks, through: :track_features
end
class Album < ActiveRecord::Base
has_many :album_artists
has_many :artists, through: :album_artists
end
class AlbumArtist < ActiveRecord::Base
belongs_to :album
belongs_to :artist
end
class Track < ActiveRecord::Base
has_many :track_features
has_many :featured_artists, through: :track_features
belongs_to :album
end
class TrackFeature < ActiveRecord::Base
belongs_to :track
belongs_to :featured_artist, class_name: "Artist", foreign_key: :artist_id
validate :track_artist
private
def track_artist
if track.album.artists.exists?(name: artist.name)
track.errors[:base] << "Album artist cannot be a featured artist"
end
end
end

Rails: ignoring duplicates in an nested association

I have models User, Team, Document. There's a many-to-many relationship between Users and Teams, and a many-to-many relationship between Teams and Documents, using join tables called TeamMembership and TeamDocument respectively.
The relationships in my models look like this:
class Document < ActiveRecord::Base
has_many :team_documents, dependent: :destroy
has_many :teams, through: :team_documents
end
class User < ActiveRecord::Base
has_many :team_memberships, dependent: :destroy, foreign_key: :member_id
has_many :teams, through: :team_memberships
has_many :documents, through: :teams
end
class TeamDocument < ActiveRecord::Base
belongs_to :team
belongs_to :document
end
class TeamMembership < ActiveRecord::Base
belongs_to :team
belongs_to :member, class_name: "User"
end
class Team < ActiveRecord::Base
has_many :team_documents, dependent: :destroy
has_many :documents, through: :team_documents
has_many :team_memberships, dependent: :destroy
has_many :members, through: :team_memberships
end
The idea is that users can belong to many teams, a document can be associated with many teams, and users will only have access to documents that "belong" to at least one team that the user is a member of.
Here's the question: I can use User#documents to retrieve a list of all the documents that this user is allowed to view. But this will return duplicates if a document is viewable by more than one team which the user is a member of. How can I avoid this?
I know I can remove the duplicates after the fact with #user.documents.uniq, but as I will never want to include the duplicates in any case, is there a way I can just make #documents not include duplicates every time?
I don't have nested has_many :through like yours to test it, but I suspect using uniq option on your user association would help :
class User < ActiveRecord::Base
has_many :documents, through: :teams, uniq: true
end
You can add a default_scope on Document model:
class Document < ActiveRecord::Base
default_scope group: { documents: :id }

rails polymorphic many-to-many association

I have these models:
class Company < ActiveRecord::Base
has_many :categorizings, as: :categorizable
has_many :categories, :through => :categorizings
class Categorizing < ActiveRecord::Base
belongs_to :category
belongs_to :categorizable, polymorphic: true
class Category < ActiveRecord::Base
has_many :categorizings
has_many :categorizables, through: :categorizings
How can I get all the companies having a specific category?
I tried
Category.find_by_name("fff").companies
plus a lot of other solutions but couldn't get it working
Thx!
You could do the following
Category.first.categorizables.where(categorizable_type: 'Company')
that would select all the Companies associated with Category using your relationship schema.
Also read some about has_many :through association because I think you don't quite get it http://guides.rubyonrails.org/association_basics.html#the-has-many-through-association

Resources