简体   繁体   English

缺少has_one多态关联的Rails范围

[英]Rails scope by absence of has_one polymorphic association

I have records that, instead of being deleted, are invalidated by creating an entry in a polymorphic record_invalidations table. 我有记录,而不是被删除,而是通过在多态record_invalidations表中创建一个条目来使记录无效。

The setup looks like this: 设置如下所示:

class RecordInvalidation < ActiveRecord::Base
  belongs_to :archivable, polymorphic: true
end


class Record < ActiveRecord::Base
  has_one :invalidation, class_name: "RecordInvalidation", as: :archivable

  def self.default_scope
    where(invalidation: nil)
  end
end

(There are multiple record classes, hence the polymorphic relation.) (有多个记录类,因此是多态关系。)

Question: How do I make a scope, that returns records based on the absence of entries in another class pointing back at the class in question. 问:我如何做一个范围,返回基于在有关类别回指向另一个类没有条目记录。

The current code does not work because the relation pointer is in the records_invalidations table, not the records table. 当前代码不起作用,因为关系指针位于records_invalidations表中,而不是在records表中。

UPDATE 2 更新2

The record_invalidation class matches the table name just fine, I think the problem is the column name. record_invalidation类与表名匹配就好了,我认为问题是列名。 Here's the (simplified) schema: 这是(简化的)模式:

create_table "records", force: :cascade do |t|
  t.text     "content",        null: false
end

create_table "record_invalidations", force: :cascade do |t|
  t.integer  "archivable_id"
  t.string   "archivable_type"
end

UPDATE 3 更新3

I see know why the first error was happening, so I removed that update. 我知道知道为什么会发生第一个错误,因此我删除了该更新。 Now I am passing the correct table name that I am joining in the SQL query, but I have a number of arguments mismatch. 现在,我传递了要在SQL查询中加入的正确表名,但是我有许多参数不匹配。 Can I pass another argument to the where clause? 我可以将另一个参数传递给where子句吗?

self.joins(:invalidation).where('record_invalidations.id is null')

Gives: 得到:

ActiveRecord::StatementInvalid: PG::ProtocolViolation: ERROR:  bind 
message supplies 1 parameters, but prepared statement "a56" requires 2

: SELECT  "records".* FROM "records" 
    INNER JOIN "record_invalidations" ON 
    "record_invalidations"."archivable_id" = "records"."id" AND 
    "record_invalidations"."archivable_type" = $1 WHERE 
    (record_invalidations.id is null) AND "plans"."id" = $2 LIMIT 1

This may not be the most efficient way, but it works: 这可能不是最有效的方法,但是它起作用:

def self.default_scope
  # Only show records that were not invalidated
  # Makes a list of all invalidated record ids in a subquery then checks for id
  where.not(:id => RecordInvalidation.select(:archivable_id)
                                     .where(archivable_type: self.name)
                                     .uniq)
end

Thanks to rails scope to check if association does NOT exist 感谢Rails作用域检查关联是否不存在

I just added the required filtering for the polymorphic association to that answer. 我刚刚将多态关联所需的过滤添加到该答案。

If anyone has a better solution feel free to add and I will accept that instead of my own. 如果有人有更好的解决方案,请随时添加,我会接受,而不是我自己的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM