2012-06-07 3 views
1

У меня возникла проблема с интерфейсом запросов на запись в режиме Rails 3. У меня есть таблица поиска (lookups), основная таблица (through_references) и таблица сквозного/join, называемая through_tables. Таким образом, это конфигурация HABTM, которую я создал с помощью has_many: through.Проблемы с Rails 3 Интерфейс запроса активной записи с подключением по ID

Обновление: Особо следует отметить, что когда я делаю эти объединения, я присоединился к идентификаторам, чтобы обеспечить фильтрацию записей. Кажется, что это не работает с Active Record Query Interface. Если вы не хотите видеть подробные сведения о моих муках, вы можете пропустить вниз, чтобы увидеть мое обходное решение ниже.

У нас также будет несколько основных элементов (через таблицу_соединений), которые должны иметь любую комбинацию элементов поиска и удобно иметь возможность щелкнуть соответствующие элементы поиска, используя флажки.

Я разместил код на github. Существует гораздо больше объяснений по исходному коду github. чтобы увидеть результаты, перейдите на страницу индекса поиска. Обратите внимание, что вам нужно будет создать записи, используя код эшафота.

У меня также есть код, начинающийся на heroku, с дополнительными пояснениями и примерами.

class Lookup < ActiveRecord::Base 
    has_many :fk_references 
    has_many :through_tables 
    has_many :through_references, :through => :through_tables 
    attr_accessible :name, :value 
end 

class ThroughTable < ActiveRecord::Base 
    belongs_to :through_reference 
    belongs_to :lookup 
    attr_accessible :description, :through_reference_id, :lookup_id 
end 

class ThroughReference < ActiveRecord::Base 
    has_many :through_tables 
    has_many :lookups, :through => :through_tables 
    attr_accessible :description 
end 

Если мы хотим иметь список, если все элементы поиска, и основные пункты, которые соответствуют с ними, мы можем LEFT JOIN таблицы «Lookups» с таблицей основных пунктов (through_references). Соответствуя SQL:

SELECT * FROM lookups 
    LEFT OUTER JOIN through_tables ON (lookups.id = through_tables.lookup_id AND through_tables.through_reference_id = 1) 
    LEFT OUTER JOIN through_references ON through_references.id = through_tables.through_reference_id 
    ORDER BY lookups.id 

Возвращенные записи:

1;“Lookup Item 1”;“1”;“2012-06-06 17:14:40.819791”;“2012-06-06 17:14:40.819791”;1;1;1;“Main Item 1 has Lookup item 1”;“2012-06-06 17:17:31.355425”;“2012-06-06 17:17:31.355425”;1;“Main Item 1”;“2012-06-06 17:16:30.004375”;“2012-06-06 17:16:30.004375” 

2;“Lookup Item 2”;“2”;“2012-06-06 17:14:59.584756”;“2012-06-06 17:14:59.584756”;;;;“”;“”;“”;;“”;“”;“” 

3;“Lookup Item 3”;“3”;“2012-06-06 17:15:14.700239”;“2012-06-06 17:15:14.700239”;2;1;3;“Main Item 1 has Lookup item 3”;“2012-06-06 17:17:53.169715”;“2012-06-06 17:17:53.169715”;1;“Main Item 1”;“2012-06-06 17:16:30.004375”;“2012-06-06 17:16:30.004375” 

Это то, что я ожидал.

=== Active Record Query Interface с использованием пользовательского соединения слева

Lookup.joins(“LEFT OUTER JOIN through_tables ON (lookups.id = through_tables.lookup_id AND through_tables.through_reference_id = 1)”).includes(:through_references).order(‘lookups.id’) 

Что возвращается из Active Record Query Interface (обратите внимание, я перемещаться вниз по иерархии Active Record):

Lookup ID Lookup Name Lookup Value Through Table ID Through Table Description Main Item ID Main Item Description 
1 Lookup Item 1 1 1 Main Item 1 has Lookup item 1 1 Main Item 1 
1 Lookup Item 1 1 3 Main Item 2 has Lookup item 1 2 Main Item 2 
2 Lookup Item 2 2 4 Main Item 2 has Lookup item 2 2 Main Item 2 
3 Lookup Item 3 3 2 Main Item 1 has Lookup item 3 1 Main Item 1 

Этот НЕ то, что я ожидал.

То, что у нас здесь, идентично простому левому соединению (без предложения И). Это говорит мне, что предложение AND игнорируется в интерфейсе запросов активной записи.

=== Active Record Query Interface с использованием find_by_sql подход

Lookup.find_by_sql("SELECT * FROM lookups LEFT OUTER JOIN through_tables ON (through_tables.lookup_id = lookups.id AND through_tables.through_reference_id = 1) LEFT OUTER JOIN through_references ON through_references.id = through_tables.through_reference_id ORDER BY lookups.value, through_references.id") 

Что возвращается из Active Record Query Interface (обратите внимание, я перемещаться вниз по иерархии Active Record) ::

Lookup ID Lookup Name  Lookup Value Through Table ID Through Table Description Main Item ID Main Item Description 
1 Lookup Item 1 1 3 Main Item 2 has Lookup item 1 2 Main Item 2 
1 Lookup Item 1 1 1 Main Item 1 has Lookup item 1 1 Main Item 1 
    Lookup Item 2 2 No through_tables entry 
1 Lookup Item 3 3 3 Main Item 2 has Lookup item 1 2 Main Item 2 
1 Lookup Item 3 3 1 Main Item 1 has Lookup item 1 1 Main Item 1 

В результаты здесь сумасшедшие!

Является ли это ошибкой, это намеченные эффекты, или я чего-то не хватает?

Надеюсь, что существует чистый способ сделать это, без необходимости генерировать два набора результатов и объединить их по коду.

ответ

0

Ну, чтение проекта GitHub, я вижу это:

То, что я действительно хочу сделать, это список всех элементов поиска, и если есть соответствующие основные пункты, которые их прилагаемыми на возвращаемую запись , а если нет, я хочу nulls. Это метод, который I использовался более 10 лет.

Я думаю, что проблема именно, что вы хотите сделать это таким образом, когда это было бы более естественно, чтобы рельсы жадная загрузка с этим справиться, и поэтому вы получили зациклены на выборку все в одном массовое соединение.

Что я хотел бы сделать что-то вроде:

Lookup.where (.. вставить все необходимые условия здесь ...) включает в себя. (: Through_tables)

Тогда ActiveQuery будет получать весь поиск в одном запросе, а затем использовать загрузку для загрузки любых ассоциаций, названных в инструкции include, по одному запросу для каждой ассоциации.

Примечание. Я не говорю, что соединения плохие, просто говоря, что это более естественный способ сделать это в рельсах. Мне нравится использовать Preloader http://apidock.com/rails/ActiveRecord/Associations/Preloader, чтобы отделить решение о том, что нужно для загрузки из решения о том, какие данные нужно извлечь. Я считаю, что это полезно в контроллерах - пусть модель решит, каковы условия, но пусть контроллер решает, какие объекты ему нужно будет с нетерпением.

HTH

+0

Я не зациклен на извлечении всего в одном массивном соединении. Если вы заметили в проекте github, я попробовал предложение where, и он не возвращал все элементы поиска и не выполнял функцию предложения sql where. Просмотрите страницу герою. Я бы проголосовал за вас, но у меня нет рейтинга, чтобы это сделать. –

+0

Я получил некоторое здравомыслие в отношении предложения where, используя хэш на включениях (проверьте github или heroku выше). Теперь он работает как предложение SQL where (что не решает мою проблему). –

1

Я нашел работу вокруг. Проблема заключается в том, что Active Record не распознает объединения, которые фильтруют идентификатор (LEFT OUTER JOIN xyz ON xyz.id = ID).

Мое обхождение включает создание хранимой процедуры или функции, которая принимает идентификатор в качестве параметра, выполняет ли соединение в базе данных и возвращает хороший плоский набор записей.

см: Heroku demo page (skip to bottom)

Обратите внимание, я не помечают как решение, так как это не является обходным, и ничего общего с активной записи.