1

ポリモーフィックな record_invalidations テーブルにエントリを作成することで、削除される代わりに無効化されるレコードがあります。

セットアップは次のようになります。

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

(複数のレコード クラスがあるため、ポリモーフィックな関係になります。)

質問: 問題のクラスを指す別のクラスにエントリがないことに基づいてレコードを返すスコープを作成するにはどうすればよいですか。

リレーション ポインタが records テーブルではなく records_invalidations テーブルにあるため、現在のコードは機能しません。

更新 2

record_invalidation クラスはテーブル名とうまく一致します。問題は列名だと思います。(簡略化された)スキーマは次のとおりです。

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

更新 3

最初のエラーが発生した理由がわかったので、その更新を削除しました。現在、SQL クエリに参加している正しいテーブル名を渡していますが、いくつかの引数が一致していません。where 句に別の引数を渡すことはできますか?

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

与えます:

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
4

1 に答える 1

0

これは最も効率的な方法ではないかもしれませんが、うまくいきます:

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

関連が存在しないかどうかを確認するレールスコープのおかげで

その回答に、ポリモーフィックな関連付けに必要なフィルタリングを追加しました。

誰かがより良い解決策を持っている場合は、自由に追加してください。私自身の代わりにそれを受け入れます。

于 2015-09-11T18:10:45.780 に答える