0

У меня есть записи, которые вместо удаления становятся недействительными, создавая запись в таблице полиморфных записей record_invalidations.Область рельсов из-за отсутствия полиморфной ассоциации has_one

Установка выглядит следующим образом:

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_invalidations, а не в таблице записей.

UPDATE 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 

UPDATE 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 
+0

Я не могу проверить это в данный момент, поэтому комментарий, но я думаю, что вы можете сделать. .joins (: invalidation) .where ('invalidations.id is null') 'или аналогичный, сообщите мне, если он работает , –

+0

Ближе! Я пробовал: self.joins (: недействительности) .где ('invalidations.id равна нулю') и получил очень близкий выход SQL, но видя ошибку: ActiveRecord :: StatementInvalid: PG :: UndefinedTable: ERROR : отсутствует запись FROM-clause для таблицы «invalidation» LINE 1: ... cord_invalidations "." archivable_type "= $ 1 WHERE (invalidati ... ^ –

+0

Можете ли вы попробовать« self.table_name = 'records'' (или независимо от имени таблицы на самом деле) в классе RecordInvalidation? Может быть, старая область действия будет работать - в этом случае? –

ответ

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 

Благодаря rails scope to check if association does NOT exist

Я просто добавил необходимую фильтрацию для полиморфная связь с этим ответом.

Если у кого-то есть лучшее решение, не стесняйтесь добавлять, и я соглашусь с тем, что вместо своего.

Смежные вопросы