diff options
-rw-r--r-- | lib/arel/primitives/attribute.rb | 8 | ||||
-rw-r--r-- | lib/arel/relations/join.rb | 9 | ||||
-rw-r--r-- | lib/arel/relations/nil.rb | 1 | ||||
-rw-r--r-- | lib/arel/relations/relation.rb | 4 | ||||
-rw-r--r-- | spec/arel/unit/primitives/attribute_spec.rb | 29 | ||||
-rw-r--r-- | spec/arel/unit/relations/join_spec.rb | 17 |
6 files changed, 60 insertions, 8 deletions
diff --git a/lib/arel/primitives/attribute.rb b/lib/arel/primitives/attribute.rb index 14b8c18cb2..5895f7e9b9 100644 --- a/lib/arel/primitives/attribute.rb +++ b/lib/arel/primitives/attribute.rb @@ -1,3 +1,5 @@ +require 'set' + module Arel class Attribute attr_reader :relation, :name, :alias, :ancestor @@ -67,9 +69,9 @@ module Arel !(history & other.history).empty? end - def %(other) - if other then (history - other.history) + (other.history - history) - else history + def /(other) + if other then (history & other.history).size.to_f / Set.new(history + other.history).size + else 0 end end end diff --git a/lib/arel/relations/join.rb b/lib/arel/relations/join.rb index 4269731092..5356e57394 100644 --- a/lib/arel/relations/join.rb +++ b/lib/arel/relations/join.rb @@ -44,9 +44,12 @@ module Arel end def relation_for(attribute) - externalize([relation1[attribute], relation2[attribute]].select { |a| a =~ attribute }.min do |a1, a2| - (attribute % a1).size <=> (attribute % a2).size - end.relation).relation_for(attribute) + x = [externalize(relation1), externalize(relation2)].max do |r1, r2| + o1, o2 = r1.relation_for(attribute), r2.relation_for(attribute) + a1, a2 = o1 && o1[attribute], o2 && o2[attribute] + + attribute / a1 <=> attribute / a2 + end.relation_for(attribute) end private diff --git a/lib/arel/relations/nil.rb b/lib/arel/relations/nil.rb index 258f60f478..b0d97dd174 100644 --- a/lib/arel/relations/nil.rb +++ b/lib/arel/relations/nil.rb @@ -2,6 +2,7 @@ module Arel class Nil < Relation def table; self end def table_sql(formatter = nil); '' end + def relation_for(attribute); nil end def name; '' end def to_s; '' end diff --git a/lib/arel/relations/relation.rb b/lib/arel/relations/relation.rb index cc0f40ea17..8c56a0cdcc 100644 --- a/lib/arel/relations/relation.rb +++ b/lib/arel/relations/relation.rb @@ -140,8 +140,8 @@ module Arel end def attribute_for_attribute(attribute) - attributes.select { |a| a =~ attribute }.min do |a1, a2| - (attribute % a1).size <=> (attribute % a2).size + attributes.select { |a| a =~ attribute }.max do |a1, a2| + (attribute / a1) <=> (attribute / a2) end end end diff --git a/spec/arel/unit/primitives/attribute_spec.rb b/spec/arel/unit/primitives/attribute_spec.rb index 561c47da16..b253892b58 100644 --- a/spec/arel/unit/primitives/attribute_spec.rb +++ b/spec/arel/unit/primitives/attribute_spec.rb @@ -57,6 +57,35 @@ module Arel end end + describe '/' do + before do + @aliased_relation = @relation.alias + @doubly_aliased_relation = @aliased_relation.alias.alias.alias.alias + end + + describe 'when dividing two identical attributes' do + it "returns 1.0" do + (@relation[:id] / @relation[:id]).should == 1.0 + (@aliased_relation[:id] / @aliased_relation[:id]).should == 1.0 + end + end + + describe 'when dividing two unrelated attributes' do + it "returns 0.0" do + (@relation[:id] / @relation[:name]).should == 0.0 + end + end + + describe 'when dividing two similar attributes' do + it 'returns a the highest score for the most similar attributes' do + (@aliased_relation[:id] / @relation[:id]) \ + .should == (@aliased_relation[:id] / @relation[:id]) + (@aliased_relation[:id] / @relation[:id]) \ + .should < (@aliased_relation[:id] / @aliased_relation[:id]) + end + end + end + describe 'hashing' do it "implements hash equality" do Attribute.new(@relation, 'name').should hash_the_same_as(Attribute.new(@relation, 'name')) diff --git a/spec/arel/unit/relations/join_spec.rb b/spec/arel/unit/relations/join_spec.rb index d517da8c1f..a538c8af68 100644 --- a/spec/arel/unit/relations/join_spec.rb +++ b/spec/arel/unit/relations/join_spec.rb @@ -203,6 +203,23 @@ module Arel end end end + + describe 'something really really complex' do + it '' do + users = @relation1 + photos = @relation2 + users_2 = users.alias + photos_2 = photos.alias + r = users \ + .join(photos) \ + .on(photos[:user_id].eq users[:id]) \ + .join(users_2) \ + .on(users_2[:id].eq photos[:user_id]) \ + .join(photos_2) \ + .on(users_2[:id].eq photos_2[:user_id]) + r.relation_for(photos[:user_id]).should == photos + end + end describe '[]' do describe 'when given an attribute belonging to both sub-relations' do |