use*_*677 2 ruby polymorphism ruby-on-rails ruby-on-rails-5.2
class Car < ApplicationRecord
belongs_to :user
has_one :listing, as: :listable
has_one :firm, as: :firmable
has_one :seller, as: :sellable
end
class Truck < ApplicationRecord
belongs_to :user
has_one :listing, as: :listable
has_one :firm, as: :firmable
has_one :seller, as: :sellable
end
class Listing < ApplicationRecord
belongs_to :listable, polymorphic: true
has_many :favorites, dependent: :destroy
has_many :users_who_favorited, through: :favorites, source: :user
end
Run Code Online (Sandbox Code Playgroud)
假设汽车和卡车都有一个 user_id 字段......
Listing.includes(:listable)返回一个早期加载的列表 AR 关系。
但是,我需要按 user_id 进行过滤,所以我尝试了......
Listing.includes(:listable).where(user_id: 100)
但我收到错误..
ActiveRecord::StatementInvalid (PG::UndefinedColumn: 错误: 列listings.user_id 不存在) 第1行: SELECT "listings".* FROM "listings" WHERE "listings"."user_...
因为它似乎在列表中查找 user_id 。但是,我需要对可列表表进行过滤,因此这意味着汽车或卡车表。然而 listable 是被定义的。
我也尝试过:
Listing.includes(listable:[:user]).where('users.id = 100')
但我明白...
ActiveRecord::StatementInvalid (PG::UndefinedTable: 错误: 缺少表“users”的 FROM 子句条目) 第 1 行: SELECT “listings”.* FROM “listings” WHERE (users.id = 100) ... ^ : SELECT "listings".* 来自 "listings" WHERE (users.id = 100) LIMIT $1
然后尝试了
class Listing < ApplicationRecord
belongs_to :listable, polymorphic: true
has_many :favorites, dependent: :destroy
has_many :users_who_favorited, through: :favorites, source: :user
belongs_to :car, -> { includes(:listable).where(listable: { listable_type: Car.to_s }) }, foreign_key: :listable_id
belongs_to :truck, -> { includes(:listable).where(listable: { listable_type: Truck.to_s }) }, foreign_key: :listable_id
end
Run Code Online (Sandbox Code Playgroud)
并尝试过Listing.includes(:car, :truck)但得到了..
ActiveRecord::ConfigurationError(无法将“Car”加入名为“listable”的关联;也许您拼写错误?)
因此,在上述方法有效之前,我无法尝试以下方法。
Listing.includes(:car, :truck).where(cars: { user_id: 1 }).or(Listing.includes(:car, :truck).where(trucks: { user_id: 1 }))
但是,我可以执行 Listing.includes(:listable) 并且它确实有效,但当我添加条件时它会中断。
这是我几个月来一直思考的一个非常有趣的问题。然后我找到了解决方案。
在您的Listing模型中,为了能够包含您的polymorphic模型,您需要告诉您的模型它们是相关的。
class Car < ApplicationRecord
belongs_to :user
has_one :listing, as: :listable
has_one :firm, as: :firmable
has_one :seller, as: :sellable
end
class Truck < ApplicationRecord
belongs_to :user
has_one :listing, as: :listable
has_one :firm, as: :firmable
has_one :seller, as: :sellable
end
class Listing < ApplicationRecord
belongs_to :listable, polymorphic: true
has_many :favorites, dependent: :destroy
has_many :users, through: :favorites
#magic happens here
belongs_to :car, -> { includes(:listings).where(listings: { listable_type: Car.to_s }) }, foreign_key: :listable_id
belongs_to :truck, -> { includes(:listings).where(listings: { listable_type: Truck.to_s }) }, foreign_key: :listable_id
end
Run Code Online (Sandbox Code Playgroud)
现在,您可以简单地执行以下操作:Listing.includes(:car, :truck)并且它将完美地工作:-)
对于你的情况:
Listing.includes(:car, :truck).where(cars: { user_id: 1 }).or(Listing.includes(:car, :truck).where(trucks: { user_id: 1 }))
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3788 次 |
| 最近记录: |