2010-10-15 56 views
5

我拼命地尝试了解Arel,主要是因为我讨厌处理SQL;我做得很好,但我撞到了墙上。Arel刚刚发生了什么,我该如何处理Arel :: SelectManager?

我一直在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])) 

它只是挂断,导致我觉得我打this bug

(顺便说一句,我得到了更多的计数加入,理想情况下'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 :: SelectManager是什么以及如何处理它。看起来我做得很好,但我真的不知道发生了什么。

我需要以某种方式创建一个基于SelectManager的新表吗?或者我的配置使得[]语法失败了吗?或者我完全不明白Arel做什么?我仍然不完全明白我应该用Arel :: Rows做什么,但我想我会得到这个结论;我怀疑我可以通过一个项目()删除结果中的额外外键...

但我仍然很迷茫。 Haaaaalp!

p.s.与'脆弱'或'邮件家伙'是'railties'韵吗?

回答

3

我要回答我自己的问题,因为没有人感兴趣,现在我知道我在做什么错了,我可以看到,如果我理解SQL,这将是显而易见的。

问题1我使用Arel的方式是只能加入新鲜制作的表格。这是没有关系的。

真正的问题是我试图计数两个不同的东西。我真的应该由外国ID和'some_field'分组。我只是不知道你能做到这一点,而它的结果有点奇怪。如果我不关心some_field的所有可能值,这可能很烦人,但我确实关心它们,我可以轻松地将它们加起来以获得总数,现在可以很容易地将它们滤除。

t = Arel::Table.new(:some_thingies)  
e = t.group(:foreign_id, :some_field).project(t[:id], t[:foreign_id], t[:some_field]) 

一旦我想通了这一点,我想出如何与正常的ActiveRecord并没有AREL做到这一点:

SomeThing.group('foreign_id, some_field').select('id, foreign_id, some_field, count(1)') 

D'哦!道德:SQL只知道行。期。

+1

我也得到一个SelectManager的方式,我不知道如何处理它。你的答案不回答这个问题。无论如何,如果你认为你给自己的答案是正确的答案,那么你应该将商标称为“正确的答案”。 – 2011-07-20 12:40:57

+0

是的,我真的没有一个正确的答案。我想我真正要问的是“有人能告诉我如何以实用的方式使用Arel。” 我放弃了这一点,我得到了非常好的结果与Squeel https://github.com/ernie/squeel – 2011-07-27 08:40:49

+0

嗯...只是我的意见:我想你不是太努力。我从来没有使用过arel中的group子句,但是,我越来越多地使用它来享受乐趣。 – 2011-07-27 09:09:24

3

阿雷尔已经完全重新从胆量上升。这一举措是由tenderlove(Aaron)开始的。在主要构成的查询中存在性能问题。

我自己甚至为这个新举措做出了贡献。

Arel现在使用抽象语法树(在选择管理器中)和访问者模式。

你还不如放弃该阿雷尔1.0.1香精,用于2.0.0工程(道路上的3.0.x到与轨道对准)