В настоящее время я сталкиваюсь со следующей проблемой. У меня есть следующие 2 модели:
PageElement
Страница
Страница has_many :page_elements
, и я добавил следующее отношение has_many
в модель page_element
:
#PageElement model
has_many :siblings, ->(pe) { where.not(id: pe.id) }, through: :page, class_name: "PageElement", source: :page_elements
Итак, внутри метода, называемого set_position
, я ищу самую высокую позицию братьев и сестер и устанавливаю ее на 1 цифру выше:
def set_position
if position.zero? && siblings.present?
new_position = (siblings.order("position ASC").pluck(:position).last + 1 rescue 0)
update(position: new_position) if position != new_position
end
end
Однако, когда я смотрю на запрос, сгенерированный методом siblings
, я вижу, что по какой-то причине он автоматически ограничивается в зависимости от "элемента текущей страницы":
PageElement Load (0.6ms) SELECT "page_elements".* FROM "page_elements" WHERE "page_elements"."page_id" = $1 AND "page_elements"."element_type" = $2 ORDER BY "page_elements"."position" ASC LIMIT $3 [["page_id", 69], ["element_type", 6], ["LIMIT", 1]]
Как вы можете видеть, важной частью здесь является то, что он фильтрует по «текущему типу элемента», который равен 6. Однако я ожидаю не такого поведения, так как хочу получить всех братьев и сестер, без какого-либо вида фильтрации.
Почему рельсы автоматически определяют область на основе текущего элемента? Я также выяснил, что это происходит с другими видами столбцов, такими как строки, если я добавлю к этому элементу title
, он также будет фильтровать по этой строке заголовка.
Я знаю, что решение состоит в том, чтобы сначала удалить область сбора, например:
has_many :siblings, ->(pe) { unscoped.where.not(id: pe.id) }, through: :page, class_name: "PageElement", source: :page_elements
Однако я бы хотел понять, почему он изначально ограничен, так что я понимаю, что я не делаю ничего плохого.
UPDATE:
Я обнаружил, что эта «область видимости» происходит только тогда, когда я запускаю эти отношения в методе, вызванном after_commit
. При использовании rails console
я пытаюсь сделать PageElement.first.siblings
, я получаю правильный запрос SQL:
irb(main):002:0> PageElement.last.siblings
PageElement Load (0.7ms) SELECT "page_elements".* FROM "page_elements" ORDER BY "page_elements"."id" DESC LIMIT $1 [["LIMIT", 1]]
PageElement Load (0.8ms) SELECT "page_elements".* FROM "page_elements" INNER JOIN "pages" ON "page_elements"."page_id" = "pages"."id" WHERE "pages"."id" = $1 AND "page_elements"."id" != $2 ORDER BY "page_elements"."position" ASC LIMIT $3 [["id", 79], ["id", 200], ["LIMIT", 11]]
UPDATE2:
После еще нескольких копаний я обнаружил, что проблема в том, что я генерирую эти экземпляры в файле seed, используя where(element_type: 'something').first_or_create
. Используя first_or_create, отношения «братьев и сестер» автоматически ограничиваются. Я выяснил причину проблемы, но не причину ее появления.
В настоящее время мы используем page_instance.page_elements.where(some_condition).first_or_create
, чтобы мы могли снова и снова запускать файл seed без получения дубликатов.