From 6f340fe3f028cc3722cb000c455c6a01099330f4 Mon Sep 17 00:00:00 2001 From: Jonas Nicklas Date: Thu, 1 Nov 2012 17:23:02 +0100 Subject: [PATCH] Yo dawg... I heard you like recursion --- lib/ar_outer_join/join.rb | 11 ++++++++-- spec/outer_join_spec.rb | 43 ++++++++++++++++++++++++++++++++++++++- spec/spec_helper.rb | 5 ++++- 3 files changed, 55 insertions(+), 4 deletions(-) diff --git a/lib/ar_outer_join/join.rb b/lib/ar_outer_join/join.rb index 08d6496..f66f756 100644 --- a/lib/ar_outer_join/join.rb +++ b/lib/ar_outer_join/join.rb @@ -7,8 +7,15 @@ def initialize(klass) end def generate(*args) - args.compact.map do |arg| - JoinBuilder.new(klass.reflect_on_association(arg)).build + args.flatten.compact.map do |arg| + if arg.is_a?(Hash) + arg.map do |key, value| + association = klass.reflect_on_association(key) + generate(key) + Join.new(association.klass).generate(value) + end + else + JoinBuilder.new(klass.reflect_on_association(arg)).build + end end end diff --git a/spec/outer_join_spec.rb b/spec/outer_join_spec.rb index 049bfc1..e0abb97 100644 --- a/spec/outer_join_spec.rb +++ b/spec/outer_join_spec.rb @@ -20,10 +20,13 @@ class Image < ActiveRecord::Base belongs_to :product end +class Discount < ActiveRecord::Base + belongs_to :line_item +end + class Basket < ActiveRecord::Base; end class Category < ActiveRecord::Base; end class Site < ActiveRecord::Base; end -class Discount < ActiveRecord::Base; end class Tag < ActiveRecord::Base; end describe ActiveRecord::Base do @@ -116,5 +119,43 @@ class Tag < ActiveRecord::Base; end query.all.should =~ [product1, product3] end end + + context "with nested associations" do + it "allows hashes" do + product1 = Product.create! + product2 = Product.create! + product3 = Product.create! :published => true + product4 = Product.create! + + basket1 = Basket.create! :purchased => true + basket2 = Basket.create! :purchased => false + + LineItem.create! :product => product1, :basket => basket1 + LineItem.create! :product => product2, :basket => basket2 + LineItem.create! :product => product3 + + query = Product.outer_join(:line_items => :basket).where("baskets.purchased = ? OR products.published = ?", true, true) + query.all.should =~ [product1, product3] + end + + it "allows hashes with arrays" do + product1 = Product.create! + product2 = Product.create! + product3 = Product.create! :published => true + product4 = Product.create! + + basket1 = Basket.create! :purchased => true + basket2 = Basket.create! :purchased => false + + line_item1 = LineItem.create! :product => product1, :basket => basket1 + line_item2 = LineItem.create! :product => product2, :basket => basket2 + line_item3 = LineItem.create! :product => product4 + + Discount.create! :line_item => line_item3, :percentage => 80 + + query = Product.outer_join(:line_items => [:basket, :discounts]).where("baskets.purchased = ? OR products.published = ? OR discounts.percentage > ?", true, true, 50) + query.all.should =~ [product1, product3, product4] + end + end end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index e60e9ce..69fb615 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -29,7 +29,10 @@ t.string :name end -ActiveRecord::Base.connection.create_table :discounts +ActiveRecord::Base.connection.create_table :discounts do |t| + t.integer :percentage, :default => 0, :null => false + t.integer :line_item_id +end ActiveRecord::Base.connection.create_table :tags do |t| t.string :name