Attempting to create a join table that takes two attributes on one model, and associates them with the id of a second model. Cannot use the id of the first model due to a constant refresh process, that reorders the rows on that model's table (ConstantlyRefreshingModels).
class ConstantlyRefreshingModels < ApplicationRecord
attr_accessor :home_id, :chair, :floor, :number
has_and_belongs_to_many :family
end
class Family < ApplicationRecord
attr_accessor :bread_winner
has_and_belongs_to_many :constantlyrefreshingmodel
end
class CreateFamilyModelThatConstantlyRefreshesJoinTable < ActiveRecord::Migration[5.0]
def change
create_join_table :families, :constantlyrefreshingmodel
end
end
Looking for a join table that looks like this:
home_id | number | family_id
-----------------------------
2 | '3003' | 4
1 | '2100' | 1
And then this works out for exposing data:
new_home = constantlyrefreshingmodel.where(home_id: 2)
new_home.families == 4 == true
Any suggestions as to creating the join table, and the declaring of the associations?
You need a has_many :through Association
not a has_and_belongs_to_many
since you have additional attributes (:number
) in join model
You should
use has_many :through
if you need validations, callbacks or extra attributes on the join model. Section 2.8
Try this approach:
class Home < ApplicationRecord
has_many :points
has_many :families, through: :points
end
# Point is your join model, AKA ConstantlyRefreshingModel
class Point < ApplicationRecord
belongs_to :family
belongs_to :home
validates :points, presence: true # Or some other validation, :number in your question.
end
class Family < ApplicationRecord
has_many :points
has_many :houses, through: :points
end
Join table migration:
class CreatePoints < ActiveRecord::Migration[5.2]
def change
create_table :points do |t|
t.references :home, foreign_key: true, null: false
t.references :family, foreign_key: true, null: false
t.string :points, null: false
t.timestamps
end
end
end
For example, having the following data:
home_1 = Home.create(id: 1) # home with an id of 1
home_2 = Home.create(id: 2) # home with an id of 2
family_4 = Family.create(id: 4) # family with an id of 4
family_1 = Family.create(id: 1) # family with an id of 1
Point.create(points: "3003", home: home_2, family: family_4)
Point.create(points: "2100", home: home_1, family: family_1)
Then:
points = Point.where(home: home_2) # you get a collection of all points assigned to house with ID: 2
points.first.family # family with an id of 4
To expose that a :home
with id: 2
and the number 3003
points to the family where the id: 4
home = Home.find(2)
home.families.ids # 4
home.points.first # 3003
To expose family with an id: 4
is associated to the home with an id of 2 and the number 3003.
family = Family.find(4)
family.homes.ids # 2
family.points.first # 3003
Also, attr_accessor
, attr_reader
and attr_writer
are deprecated in Rails 5.1
. See this post