从具有多态关联的一张表中检索行

发布于 2024-12-01 03:28:50 字数 1673 浏览 1 评论 0原文

我有一个模型与其他三个表具有多态关联:

class User < ActiveRecord::Base
    belongs_to :authenticatable, :polymorphic => true


# == Schema Information
#
# Table name: employees
#
#  id                     :integer(4)      not null, primary key
#  ...
#  school_id              :integer(4)

class Guardian < ActiveRecord::Base
    has_one :user, :as => :authenticatable
    belongs_to :school


# == Schema Information
#
# Table name: guardians
#
#  id                     :integer(4)      not null, primary key
#  ...
#  school_id              :integer(4)

class Guardian < ActiveRecord::Base
    has_one :user, :as => :authenticatable
    belongs_to :school

# == Schema Information
#
# Table name: students
#
#  id                     :integer(4)      not null, primary key
#  ...
#  school_id              :integer(4)

class Student < ActiveRecord::Base
    has_one :user, :as => :authenticatable
    belongs_to :school

如您所见,最后 3 个模型属于“学校”模型,因此有一个名为 school_id 的列。我想从 user 检索所有行,以便它们相应的可验证 school_id 等于某个值。为了澄清,我想做这样的事情:

User.joins(:authenticatable).where(:school_id => some_value)

事实上,这将导致

ActiveRecord::EagerLoadPolymorphicError

最后的说明,我设法查找一些文档,这些文档表明在多态关联上使用 include 应该有效,例如:

User.find(:all, :include => :authenticatable) (This works)

但是如果我这样做:

User.find(:all, :include => :authenticatable).where(:school_id => some_value)

它会破坏轨道,因为 User.find(...) 返回一个 Array 并且没有为该类定义 where 方法。

我尝试过其他一些选择,但没有找到实现我想要的方法。你能帮助我吗?谢谢!

I have one model which has a polymorphic association with three other tables:

class User < ActiveRecord::Base
    belongs_to :authenticatable, :polymorphic => true


# == Schema Information
#
# Table name: employees
#
#  id                     :integer(4)      not null, primary key
#  ...
#  school_id              :integer(4)

class Guardian < ActiveRecord::Base
    has_one :user, :as => :authenticatable
    belongs_to :school


# == Schema Information
#
# Table name: guardians
#
#  id                     :integer(4)      not null, primary key
#  ...
#  school_id              :integer(4)

class Guardian < ActiveRecord::Base
    has_one :user, :as => :authenticatable
    belongs_to :school

# == Schema Information
#
# Table name: students
#
#  id                     :integer(4)      not null, primary key
#  ...
#  school_id              :integer(4)

class Student < ActiveRecord::Base
    has_one :user, :as => :authenticatable
    belongs_to :school

As you can see, the last 3 models belong to a "school" model and therefore have a column named school_id. I want to retrieve all rows from user such that their corresponding authenticatable school_id is equal to some value. To clarify, I'd like to do something like this:

User.joins(:authenticatable).where(:school_id => some_value)

As it is, that will result in an

ActiveRecord::EagerLoadPolymorphicError

on a final note, i managed to look up some documentation which suggests that using include on a polymorphic association should work, such as:

User.find(:all, :include => :authenticatable) (This works)

However if I do this:

User.find(:all, :include => :authenticatable).where(:school_id => some_value)

It breaks rails, because User.find(...) returns an Array and the where method is not defined for that class.

I've tried some other options and have not found a way to accomplish what I want. Can you help me? Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

只是一片海 2024-12-08 03:28:50

您可以尝试通过在joins语句中使用SQL查询来解决它:

Model1.joins("INNER JOIN model2 ON model2.id = model1.polymorphizm_id INNER JOIN model3 ON model3.id = model1.polymorphizm_id INNER JOIN model4 ON model4.id = model1.polymorphizm_id").where("model2.column_id = ... or model3.column_id = ... or model4.column_id = ...")

我实际上没有尝试它,但是多态关联。向模型添加 2 列:xxx_typexxx_id。他们负责处理关联。具有多种型号。

You can try to solve it by using SQL query in joins statement:

Model1.joins("INNER JOIN model2 ON model2.id = model1.polymorphizm_id INNER JOIN model3 ON model3.id = model1.polymorphizm_id INNER JOIN model4 ON model4.id = model1.polymorphizm_id").where("model2.column_id = ... or model3.column_id = ... or model4.column_id = ...")

I not actually try it, but polimorphic assoc. adds 2 columns to model: xxx_type and xxx_id. They serve to handle assoc. with multiple models.

笨笨の傻瓜 2024-12-08 03:28:50

您可以使用子查询进行操作,也许可以得到一些工作:

User.where(authenticable: Guardian.where(school_id: some_value))

如果您使用的是 Rails 5,他们将 .or 添加到 ActiveRecord,因此您可能能够加入有些组合在一起,例如:

User.where(authenticable: Guardian.where(school_id: some_value))
    .or.where(authenticable: Student.where(school_id: some_value))

merge 是另一种可能会产生一些结果的方法:

User.all.merge(Guardian.where(school_id: some_value))

我不太熟悉跨多态表的查询,因此您的情况可能与上述方法有所不同。最坏的情况是,您可能最终不得不执行多个查询来保留范围:

user_ids = Guardian.joins(:user).select('users.id').where(school_id: some_value).pluck(:user_id) +
           Student.joins(:user).select('users.id').where(school_id: some_value).pluck(:user_id)
users = User.where(id: user_ids)

您现在可能会陷入模式困境,但如果您可以自由地更改它,那么看起来您可能会更好地使用单个查询-表继承关系:

class User < ActiveRecord::Base
  belongs_to :school
end

class Student < User
end

class Guardian < User
end

然后你只需说:

User.where(school_id: some_value)

我发现多态关系在很多情况下比它们的价值更麻烦,因为执行查询和批量更新等操作非常困难,并且使得不可能使用外键约束。经过一些额外的思考,通常会有一个合理的数据模型在没有它们的情况下也能很好地工作。

You could futz around with sub-queries and maybe get something working:

User.where(authenticable: Guardian.where(school_id: some_value))

If you're using Rails 5, they added .or to ActiveRecord, so you might be able to join some together like:

User.where(authenticable: Guardian.where(school_id: some_value))
    .or.where(authenticable: Student.where(school_id: some_value))

merge is another method that might yield some results:

User.all.merge(Guardian.where(school_id: some_value))

I'm not too familiar with querying across polymorphic tables, so your mileage may vary with the above. Worst case, you may end up having to do more than one query to preserve the scope:

user_ids = Guardian.joins(:user).select('users.id').where(school_id: some_value).pluck(:user_id) +
           Student.joins(:user).select('users.id').where(school_id: some_value).pluck(:user_id)
users = User.where(id: user_ids)

You may be stuck with the schema now, but if you're at liberty to change it, it looks like you might be better off with a single-table inheritance relationship:

class User < ActiveRecord::Base
  belongs_to :school
end

class Student < User
end

class Guardian < User
end

Then you simply say:

User.where(school_id: some_value)

I've found polymorphic relations to be more trouble than they're worth in many cases due to how difficult it is to do things like queries and bulk updates, as well as making it impossible to use foreign key constraints. With some extra thought, there's usually a reasonable data model that works well without them.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文