I have a base class Place
and multiple sub-classes using STI conventions. I have a separate model Post
, which belongs_to
one of the sub-classes of Place
:
class Place < ApplicationRecord
end
class SubPlace < Place
has_many :posts, class_name: "SubPlace", foreign_key: "sub_place_id"
end
class Post < ApplicationRecord
belongs_to :sub_place, class_name: "SubPlace", foreign_key: "sub_place_id"
end
It is possible to save a new Post
record using Rails console, but I get the following error when trying to find Posts
for a specific SubPlace
:
ActiveRecord::StatementInvalid (PG::UndefinedColumn: ERROR: column places.sub_place_id does not exist)
Is there a way to make this work, or must my associations relate to the base class only?
Added Schema:
create_table "posts", force: :cascade do |t|
t.string "title"
t.bigint "sub_place_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["sub_place_id"], name: "index_posts_on_sub_place_id"
end
create_table "places", force: :cascade do |t|
t.string "name"
t.string "type"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
A better way to handle assocations and STI is to just setup the assocations to the base class:
class Place < ApplicationRecord
end
class SubPlace < Place
has_many :posts, foreign_key: 'place_id', inverse_of: 'place'
end
class AnotherKindOfPlace < Place
has_many :posts, foreign_key: 'place_id', inverse_of: 'place'
end
class Post < ApplicationRecord
belongs_to :place
end
This keeps things nice and simple since Post
does not know or care that there are different kinds of places. When you access @post.place
ActiveRecord reads the places.type
column and will instanciate the correct subtype.
If the base Place class also has the association you just write it as:
class Place < ApplicationRecord
has_many :posts, foreign_key: 'place_id', inverse_of: 'place'
end