2010-10-15 32 views
5

Tôi đang cố gắng hết sức để hiểu ý nghĩa của Arel, chủ yếu là vì tôi ghét giao dịch với SQL; Tôi đã làm rất tốt, nhưng tôi đã đánh một bức tường.Điều gì đã xảy ra với Arel và tôi phải làm gì với Arel :: SelectManager?

Tôi đã làm việc trong Rails 3.0.0 và tôi đang cố tạo một truy vấn phức tạp với một số phép toán trong đó. Trường hợp thực sự khá phức tạp, nhưng tôi đã đơn giản hóa một chút. Trong ví dụ của tôi, tôi có một bảng với một trường chuỗi cụ thể và tôi muốn đếm tất cả các bản ghi, cũng như đếm cho mỗi giá trị có thể có của trường đó, được nhóm theo id nước ngoài.

Dưới Rails 3.0.0, tôi có thể làm được điều này (giao diện điều khiển lệnh):

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])) 

và vào thời điểm này tôi có thể làm làm x.to_sql và ... tốt, tôi không hoàn toàn chắc chắn đó là đúng, nhưng kết quả có vẻ đúng, ngoài việc có cột nước ngoài hai lần.

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` 

Cho đến nay rất tốt. Tuy nhiên, khi tôi cố gắng tham gia vào một bộ thứ hai của tội như thế này:

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])) 

nó chỉ bị treo lên, dẫn tôi nghĩ rằng tôi đánh this bug

(btw Tôi đã có số lượng nhiều hơn để thêm vào, và lý tưởng 'some_thingies' nên chính nó là một đối tượng arel đại diện cho lọc nhiều hơn trên thingies chúng tôi đang đếm ... nhưng tôi digress ...)

Vì vậy, tôi quyết định thử các cạnh mới nhất Arel và Rails, và bumped lên đá quý của tôi cho phù hợp:

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' 

và bây giờ khi tôi cố gắng làm làm đầu tiên tham gia, nó thất bại thảm hại:

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>' 

này không có vẻ như một lỗi trong Arel - nếu bất cứ điều gì, nó có vẻ giống như thực tế là nó trước đây là lỗi. Tôi nghĩ rằng tôi chỉ không biết những gì một Arel :: SelectManager là và phải làm gì với nó. Có vẻ như tôi đã làm rất tốt, nhưng tôi thực sự không hiểu chuyện gì đang diễn ra.

Tôi có cần bằng cách nào đó tạo một bảng mới dựa trên SelectManager mà tôi có không? Hoặc đang làm điều gì đó sai trong cấu hình của tôi mà làm cho [] cú pháp thất bại? Hay tôi hoàn toàn không hiểu Arel làm gì? Tôi vẫn không nhận được những gì tôi phải làm với Arel :: Hàng, nhưng tôi cho rằng tôi sẽ nhận được hang của điều đó; và tôi nghi ngờ tôi có thể loại bỏ các khóa ngoại thêm trong các kết quả với một dự án() ...

Nhưng tôi vẫn khá lạc. Haaaaalp!

p.s. 'lan can' vần điệu với 'sự yếu đuối', hoặc với 'những người gửi thư'?

Trả lời

3

Tôi sẽ trả lời câu hỏi của riêng mình, vì không ai quan tâm và giờ tôi biết mình đang làm gì sai, tôi có thể thấy rõ ràng nếu tôi hiểu SQL.

Vấn đề 1 với cách tôi đang sử dụng Arel là bạn chỉ có thể tham gia một bảng mới được tạo. Đó là bên cạnh điểm.

Vấn đề thực sự là tôi đang cố gắng đếm hai thứ khác nhau. Tôi thực sự nên được nhóm theo ID nước ngoài và 'some_field'. Tôi chỉ không biết bạn có thể làm điều đó, và kết quả từ nó là một chút lạ.Nếu tôi không quan tâm đến tất cả các giá trị có thể của some_field, điều này có thể gây phiền nhiễu, nhưng tôi quan tâm đến tất cả chúng, và tôi có thể thêm chúng một cách dễ dàng để có được tổng số, và rất dễ dàng để lọc chúng ngay bây giờ.

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

Khi tôi figured mà ra, tôi đã tìm ra cách để làm điều đó với ActiveRecord bình thường và không có Arel:

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

D'oh! Đạo đức: SQL chỉ biết về các hàng. Giai đoạn.

+1

Tôi cũng nhận được một SelectManager và tôi không biết Làm gì với nó đây. Câu trả lời này của bạn không trả lời câu hỏi này. Dù sao, nếu bạn cho rằng câu trả lời mà bạn đang đưa ra cho chính mình là câu trả lời đúng, bạn có thể đánh dấu là "câu trả lời đúng". –

+0

vâng, tôi không thực sự có câu trả lời đúng. Tôi đoán những gì tôi đã thực sự yêu cầu là "ai đó có thể vui lòng chỉ cho tôi cách sử dụng Arel một cách thiết thực." Tôi đã từ bỏ điều đó và tôi nhận được kết quả rất tốt với Squeel https://github.com/ernie/squeel –

+0

Hm ... Chỉ cần ý kiến ​​của tôi: Tôi đoán bạn không cố gắng quá nhiều. Tôi chưa bao giờ sử dụng mệnh đề nhóm trong arel, mặc dù, tôi đã ngày càng sử dụng nó với sự thích thú. –

3

Arel đã được hoàn toàn làm lại từ ruột. Sáng kiến ​​này đã được bắt đầu bởi tenderlove (Aaron) Đã có vấn đề về hiệu năng về các truy vấn được soạn thảo chủ yếu.

Tôi thậm chí đã tự đóng góp cho sáng kiến ​​mới này.

Arel hiện sử dụng Cây cú pháp trừu tượng (trong Chọn người quản lý) và Mẫu khách truy cập.

Bạn cũng có thể loại bỏ cách mà Arel 1.0.1 công trình trong hương vị cho 2.0.0 (trên đường đến 3.0.x để phù hợp với đường ray)

Các vấn đề liên quan