Как использовать Arel для запроса отношения полиморф c has_one - PullRequest
4 голосов
/ 04 апреля 2020

В настоящее время я работаю над проектом, который имеет внешний интерфейс jquery datatables и использую гем ajax -datatables-rails для обработки внутреннего интерфейса. После рассмотрения примеров они ссылаются на, и у меня возникла проблема.

У меня есть таблица данных, и она отображает данные из таблицы, назовем ее Foo, которая имеет отношение has_one polymorphi c с 3 различными таблицами. Мой поиск должен искать по столбцу в этом полиморфном c отношении.

def my_filter
    ->(column,value) { Arel.sql("Foo.bar.description").matches("%#{value}%")}
end

Одна вещь, которую я попытался, состояла в том, чтобы преобразовать Arel :: Table (a - таблица arel)

Foo.where(a[:id].not_eq(nil)).find(
     :all,
     :joins => "bar",
     :conditions => ["bar.description LIKE %asd%", true]
 ).arel_table

Однако в этом случае я получаю сообщение о том, что не может найти идентификатор на Foo.

Ответы [ 2 ]

1 голос
/ 09 апреля 2020

Есть два подхода, которые я могу придумать (и в зависимости от вашей СУБД, то, что происходит под прикрытием, может быть почти одинаковым):

  • создать представление для всех соответствующих полей всех различные полиморфы c bar типы
  • присоединяются к динамической таблице c, которая создается на лету

В обоих случаях базовая логика c является * Команда 1010 *, которая будет выглядеть примерно так:

SELECT foo_id, description FROM bars1
UNION
SELECT foo_id, description FROM bars2
UNION
SELECT foo_id, description FROM bars3

В случае представления это UNION будет составлять содержимое самого представления.

В случае для таблицы Dynami c она будет выглядеть примерно так:

SELECT foos.*, bars.*
FROM foos
LEFT JOIN (
  SELECT foo_id, description FROM bars1
  UNION
  SELECT foo_id, description FROM bars2
  UNION
  SELECT foo_id, description FROM bars3
) AS bars ON bars.foo_id = foos.id
WHERE bars.description LIKE 'whatever%'

С точки зрения, использование Arel в основном такое же, как обычно, только вы должны сделать JOIN явным:

Foo.joins("LEFT JOIN bars ON bars.foo_id = foos.id").where("bars.description LIKE ?", description)

Имея динамический c стол, я уверен, что есть способ express в чистом Ареле, но лично я бы просто go с SQL вместо:

joins_sql = <~SQL.strip_heredoc
  LEFT JOIN (
    SELECT foo_id, description FROM bars1
    UNION
    SELECT foo_id, description FROM bars2
    UNION
    SELECT foo_id, description FROM bars3
  ) AS bars ON bars.foo_id = foos.id
SQL

Foo.select("foos.*, bars.*").joins(joins_sql).where("bars.description LIKE ?", description)

Надеюсь, это поможет.

0 голосов
/ 09 апреля 2020

Попробуйте вот так

class Foo < ActiveRecord::Base
  has_one :bar, polymorphic: true

  def view_columns
    @view_columns ||= {
      description: { source: "City.id", cond: by_description },
    }
  end

  def by_description
    ->(column) { joins(:bar).where("description LIKE ?", "%#{column.search.value}%")}
  end
end
...