HAS_MANY THROUGH ASSOCIATIONS!
I finally got to Rails!... I personally feel has_many through associations need a deeper explanation than what you find in https://guides.rubyonrails.org/association_basics.html#the-has-many-through-association
As my project has these types of associations, I thought it would be of great value to whoever reads my blog posts.
Here is my schema:
ActiveRecord::Schema.define(version: 2020_11_23_171000) do
create_table "landmarks", force: :cascade do |t|
t.string "name"
t.string "city"
t.string "country"
t.text "description"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
end
create_table "reviews", force: :cascade do |t|
t.string "review"
t.integer "landmark_id"
t.integer "user_id"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
end
create_table "users", force: :cascade do |t|
t.string "username"
t.string "email"
t.string "password_digest"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
end
end
What has_many through does is create a join table by connecting, in this case, three models which will work as many to many relations. In my join table above is “REVIEWS” containing a “landmark_id” and “user_id” as attributes which are called FOREIGN KEYS. These keys are many to many relations to my other two models “USERS” and “LANDMARKS”.
Once you have your migrations set up, you move into your models by creating the association itself.
LANDMARK CLASS:
class Landmark < ApplicationRecord
has_many :reviews, dependent: :destroy
has_many :users, through: :reviews
scope :find_name, -> (name) {find_by(name: name)}
validates :name, presence: true
validates :city, presence: true
validates :country, presence: true
validates :description, presence: true
end
REVIEW CLASS:
class Review < ApplicationRecord
belongs_to :user
belongs_to :landmark
validates :review, presence: true
end
USER CLASS:
class User < ApplicationRecord
has_secure_password
has_many :reviews
has_many :landmarks, through: :reviews
validates :username, presence: true, uniqueness: :true
validates :email, presence: true, uniqueness: :true
end
The drawing above is my migrations representation, which is what I expressed on my schema.
Active Record is pretty magical and by doing this association, when you see the model USER has_many :landmarks through reviews means that the instances of our USER now responds to a method called Landmarks. This will return a collection of LANDMARKS that share a REVIEW with the USER.
HAPPY CODING!
Top comments (0)