Я отчаянно пытаюсь разобраться в Arel, главным образом потому, что ненавижу иметь дело с SQL; У меня все было хорошо, но я уперся в стену.
Я работаю в Rails 3.0.0 и пытаюсь сделать сложный запрос с некоторой математикой. Реальный случай несколько сложнее, но я немного упростил. В моем примере у меня есть таблица с определенным строковым полем, и мне нужно количество всех записей, а также количество для каждого из двух возможных значений этого поля, сгруппированных по внешнему идентификатору.
В Rails 3.0.0 я могу сделать это (консольные команды):
t = Arel::Table.new(:some_thingies)
e = t .project(t[:foreign_id], t[:foreign_id].count.as('all_count')) .group(t[:foreign_id])
c = t.where(t[:some_field].eq('type1')).project(t[:foreign_id], t[:foreign_id].count.as('type1_count')).group(t[:foreign_id])
x = e
x = x.join(c).on(e[:foreign_id].eq(c[:foreign_id]))
и в этот момент я могу сделать x.to_sql и... ну, я не совсем уверен, что это правильно, но результаты выглядят правильно, за исключением того, что столбец Foreign_id дважды.
SELECT
`some_thingies_external`.`foreign_id`,
`some_thingies_external`.`all_count`,
`some_thingies_external_2`.`foreign_id`,
`some_thingies_external_2`.`type1_count`
FROM
(SELECT
`some_thingies`.`foreign_id`, COUNT(`some_thingies`.`foreign_id`)
AS `type1+count`
FROM `some_thingies`
GROUP BY `some_thingies`.`foreign_id`) `some_thingies_external`
INNER JOIN
(SELECT `some_thingies`.`foreign_id`, COUNT(`some_thingies`.`foreign_id`)
AS `type1_count`
FROM `some_thingies`
WHERE `some_thingies`.`type` = 'type1'
GROUP BY `some_thingies`.`foreign_id`) `some_thingies_external_2`
ON `some_thingies_external`.`foreign_id` = `some_thingies_external_2`.`foreign_id`
Все идет нормально. Однако, когда я пытаюсь присоединиться ко второму набору подсчетов, например:
i = t.where(t[:some_field].eq('type2')).project(t[:foreign_id], t[:foreign_id].count.as('type2_count')).group(t[:foreign_id])
x = x.join(i).on(e[:foreign_id].eq(i[:foreign_id]))
он просто зависает, заставляя меня думать, что я сталкиваюсь с этой ошибкой
(кстати, у меня есть больше счетчиков, которые нужно добавить, и в идеале 'some_thingies' должен сам быть объектом arel, представляющим большую фильтрацию, на какие вещи мы рассчитываем... но я отвлекся...)
Итак, я решил попробовать последнюю версию Arel и Rails и соответственно увеличил свои драгоценные камни:
gem 'rails', :git => 'git://github.com/rails/rails.git'
gem 'rack', :git => 'git://github.com/rack/rack.git'
gem 'arel', :git => 'http://github.com/brynary/arel.git'
и теперь, когда я пытаюсь выполнить первое соединение, это с треском проваливается:
ruby-1.9.2-preview3 > x = x.join(c).on(e[:foreign_id].eq(c[:foreign_id]))
NoMethodError: undefined method `[]' for #<Arel::SelectManager:0x00000104311e38>
from (irb):12
from /Users/stephan/.rvm/gems/ruby-1.9.2-preview3/bundler/gems/rails-c42ea2172eb9/railties/lib/rails/commands/console.rb:44:in `start'
from /Users/stephan/.rvm/gems/ruby-1.9.2-preview3/bundler/gems/rails-c42ea2172eb9/railties/lib/rails/commands/console.rb:8:in `start'
from /Users/stephan/.rvm/gems/ruby-1.9.2-preview3/bundler/gems/rails-c42ea2172eb9/railties/lib/rails/commands.rb:33:in `<top (required)>'
from script/rails:6:in `require'
from script/rails:6:in `<main>'
Это не похоже на ошибку в Arel — во всяком случае, больше похоже на то, что это работало раньше, и есть ошибка. Думаю, я просто не знаю, что такое Arel::SelectManager и что с ним делать. Казалось, что у меня все хорошо, но я действительно не понимаю, что происходит.
Нужно ли мне как-то создавать новую таблицу на основе моего SelectManager? Или я делаю что-то неправильно в моей конфигурации, что приводит к сбою синтаксиса []? Или я просто совершенно не понимаю, что делает Арел? Я все еще не совсем понимаю, что я должен делать с Arel::Rows, но я полагаю, что разберусь с этим; и я подозреваю, что могу избавиться от лишнего внешнего ключа в результатах с помощью проекта()...
Но я все еще довольно потерян. Хааааалп!
p.s. рифмуется ли слово «railties» со словом «failties» или с «почтальонами»?