I have 4 Models and i am not sure what is the correct way to write my relationships/associations.
class User < ActiveRecord::Base
has_many :boards
has_many :lists
has_many :cards
end
class Board < ActiveRecord::Base
belongs_to :user
has_many :lists
end
class List < ActiveRecord::Base
belongs_to :user
belongs_to :board
has_many :cards
end
class Card < ActiveRecord::Base
belongs_to :user
belongs_to :list
end
If you want to be more explicit about your relationships, feel free to do the following (preferred in most every case):
class User < ActiveRecord::Base
has_many :boards, inverse_of: :user, dependent: :destroy
has_many :lists, inverse_of: :user, dependent: :destroy
has_many :cards, inverse_of: user, dependent: :destroy
end
class Board < ActiveRecord::Base
belongs_to :user, inverse_of: :boards
has_many :lists, inverse_of: :board
end
class List < ActiveRecord::Base
belongs_to :user, inverse_of: :lists
belongs_to :board, inverse_of :lists
has_many :cards, inverse_of :list
end
class Card < ActiveRecord::Base
belongs_to :user, inverse_of: :cards
belongs_to :list, inverse_of :cards
end
Finally, make sure any of your models that are dependent on another (e.g. Board belongs_to User) have the appropriate foreign key in their table. So, for example, Board will need to have a user_id foreign key to correctly create the association.
You can create a migration for any of those entities if you haven't already like so:
rails generate migration AddUserRefToBoards user:references
Related
I'm trying to create associations for three models in my Rails application. In the application a User can access courses which have videos. How would I model this?
This is what I currently have:
class User < ApplicationRecord
has_many :courses
has_many :videos, through: :courses
end
class Course < ApplicationRecord
belongs_to :user
has_many :videos
end
class Video < ApplicationRecord
belongs_to :course
belongs_to :user
end
Is this the correct way to model these associations for what I want the application to be able to achieve?
Normally, this would look something like:
class UserCourse < ApplicationRecord
belongs_to :user
belongs_to :course
end
class User < ApplicationRecord
has_many :user_courses
has_many :courses, through: :user_courses
has_many :videos, through: :courses
end
class Course < ApplicationRecord
has_many :user_courses
has_many :users, through: :user_courses
has_many :videos
end
class Video < ApplicationRecord
belongs_to :course
has_many :users, through: :course
end
That should let you do:
#user.courses
#user.videos
#course.users
#course.videos
#video.course
#video.users
(Assuming, of course, you've instantiated each of the above variables and you have associated records.)
I have a Products & Parts model which would each have multiple uploads, which are also polymorphic. Is it possible for me to have a single ItemUpload model to handle the association between the Products/Parts and Uploads, or do they need to be separate? I'd try myself just to see, but don't want to cause any potential headaches down the line! Note that I'm aware I need to do the source: and source_type: stuff to clean up the polymorphic association with has_many, but would like to clarify this point first before proceeding. Current models:
class Product < ApplicationRecord
has_many :uploads, as: :uploadable, dependent: :destroy
end
class Part < ApplicationRecord
has_many :uploads, as: :uploadable, dependent: :destroy
end
class Upload < ApplicationRecord
belongs_to :uploadable, polymorphic: true
end
What I would ideally like:
Class ItemUpload < ApplicationRecord
belongs_to :product, optional: true
belongs_to :part, optional: true
belongs_to :upload
end
Is that ok or would I need a separate ProductUpload and PartUpload model?
I would have thought your associations would look more like:
class Product < ApplicationRecord
has_many :item_uploads, as: :itemable, dependent: :destroy
has_many :uploads, through: :item_uploads
end
class Part < ApplicationRecord
has_many :item_uploads, as: :itemable, dependent: :destroy
has_many :uploads, through: :item_uploads
end
class Upload < ApplicationRecord
has_many :item_uploads
has_many :products, through: :item_uploads, source: :itemable, source_type: 'Product'
has_many :parts, through: :item_uploads, source: :itemable, source_type: 'Part'
end
Class ItemUpload < ApplicationRecord
belongs_to :itemable, polymorphic: true
belongs_to :upload
end
That should allow you to do:
product.uploads
part.uploads
upload.products
upload.parts
BTW, in reference to the link you provided:
Upload ≈ User
ItemUpload ≈ Membership
Product, Part ≈ Project, Group
The above follows the pattern in the linked article.
What would be the best method to model "likes" in rails for my app. I could either to the following:
class User < ActiveRecord::Base
has_many :things
has_many :likes
has_many :liked_things, through: :likes, source: :thing
end
class Like < ActiveRecord::Base
belongs_to :user
belongs_to :thing
end
class Thing < ActiveRecord::Base
belongs_to :user
has_many :likes
has_many :liking_users, through: :likes, source: :user
end
Or
class User < ActiveRecord::Base
has_many :things
has_and_belongs_to_many :things
end
class Thing < ActiveRecord::Base
belongs_to :user
has_and_belongs_to_many :users
end
What approach would be best and why? I plan to have an activity feed in my app as well, if that helps determine the best approach.
The answer to this question depends on whether or not Like will ever have any attributes or methods.
If its only purpose of existence is to be the HABTM relationship between Users and Things, then using the has_and_belongs_to_many relationship would suffice. In your example, having has_many and belongs_to is redundant. All you would need in this case is:
class User < ActiveRecord::Base
has_and_belongs_to_many :things
end
class Thing < ActiveRecord::Base
has_and_belongs_to_many :users
end
On the other hand, if you anticipate that a Like will have an attribute (e.g. maybe someone will really like something, or love it, etc.) then you can do
class User < ActiveRecord::Base
has_many :likes
has_many :liked_things, through: :likes, source: :thing
end
class Like < ActiveRecord::Base
belongs_to :user
belongs_to :thing
end
class Thing < ActiveRecord::Base
has_many :likes
has_many :liking_users, through: :likes, source: :user
end
Note that I removed has_many :things and belongs_to :user as they are redundant.
How can I add ownership in many to many relationships?
For example like this models.
class User < ActiveRecord::Base
has_many :editabilities, dependent: :destroy
has_many :files, through: :editabilities
end
class File < ActiveRecord::Base
has_many :editabilities, dependent: :destroy
has_many :users, through: :editabilities
end
class Editabilities < ActiveRecord::Base
belongs_to :user
belongs_to :file
end
And I want to add a one-to-many relationship to User-and-Files.
At first I thought it is best to add owner boolean column to Editabilities, but I have no idea how to handle it.
Secondly I thought if I make a new junction model Ownerships, then I can handle it same way as Editabilities. But I've got a uninitialized constant User::Ownership when I tried it with code like this.
class User < ActiveRecord::Base
has_many :editabilities, dependent: :destroy
has_many :ownerships, dependent: :destroy
has_many :files, through: :editabilities
has_many :owned_files, through: :ownerships, source: :file
end
class File < ActiveRecord::Base
has_many :editabilities, dependent: :destroy
has_many :ownerships, dependent: :destroy
has_many :users, through: :editabilities
has_one :owner, through: :ownerships, source: :user
end
class Editabilities < ActiveRecord::Base
belongs_to :user
belongs_to :file
end
class Ownerships < ActiveReord::Base
belongs_to :user
belongs_to :file
end
How can I implement a feature like this?
The only problems I see here are the classes Editabilities and Ownerships. By Rails convention model class names should be singular, not plural.
class Editability < ActiveRecord::Base
belongs_to :user
belongs_to :file
end
class Ownership < ActiveReord::Base
belongs_to :user
belongs_to :file
end
One way to quickly check your class names is by checking the result of the classify function:
> "editibilities".classify
=> "Editibility"
> "ownerships".classify
=> "Ownership"
The rest of the associations all look correct.
Your class should be named Ownership and not Ownerships.
ActiveRecord class names are normally singular and table names are plural.
Easier solution seems to add belongs_to association to File model. Because 1 File can have only 1 owner.
class File < ActiveRecord::Base
...
belongs_to :owner, class_name: 'User'
end
You will need to add owner_id column to files table.
I have these models and associations. I want to reach roleable trough privilege model doesnt matter what roleable_type is(Dj or Photographer)? Use join model because privilege model will have other attributes. It is possible something like this:
class User
has_one :privilege, dependent: :destroy
has_one :roleable, through: :privilege
end
class Dj < ActiveRecord::Base
has_one :privilege
has_one :user, through: :privilege, as: :roleable
end
class Photographer < ActiveRecord::Base
has_one :privilege
has_one :user, through: :privilege, as: :roleable
end
class Privilege < ActiveRecord::Base
belongs_to :user
belongs_to :roleable, polymorphic: true
end
If i add source_type: 'Dj' to has_many :through return only with roleable_type 'Dj'. I want to do this bellow:
u = User.first
u.roleable #return privilage roleable( doesnt matter Dj or Photograher)
I'd make those belongs_to, not that that changes anything.
class User < ActiveRecord::Base
has_one :privilege, dependent: :destroy
has_one :roleable, through: :privilege
end
class Dj < ActiveRecord::Base
has_one :privilege
belongs_to :user, through: :privilege, as: :roleable
end
class Photographer < ActiveRecord::Base
has_one :privilege
belongs_to :user, through: :privilege, as: :roleable
end
class Privilege < ActiveRecord::Base
belongs_to :user
belongs_to :roleable, polymorphic: true
end
Can you post, what u.roleable returns?