squeel 1.1.1 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +3 -0
- data/.rspec +3 -0
- data/.travis.yml +36 -4
- data/CHANGELOG.md +15 -0
- data/Gemfile +1 -1
- data/README.md +47 -6
- data/Rakefile +14 -2
- data/lib/squeel.rb +9 -1
- data/lib/squeel/adapters/active_record.rb +0 -1
- data/lib/squeel/adapters/active_record/3.0/join_dependency_extensions.rb +1 -0
- data/lib/squeel/adapters/active_record/3.0/relation_extensions.rb +12 -1
- data/lib/squeel/adapters/active_record/3.1/join_dependency_extensions.rb +1 -0
- data/lib/squeel/adapters/active_record/3.2/join_dependency_extensions.rb +1 -0
- data/lib/squeel/adapters/active_record/4.0/join_dependency_extensions.rb +1 -0
- data/lib/squeel/adapters/active_record/4.0/relation_extensions.rb +92 -0
- data/lib/squeel/adapters/active_record/4.1/compat.rb +15 -0
- data/lib/squeel/adapters/active_record/4.1/context.rb +88 -0
- data/lib/squeel/adapters/active_record/4.1/preloader_extensions.rb +31 -0
- data/lib/squeel/adapters/active_record/4.1/reflection_extensions.rb +37 -0
- data/lib/squeel/adapters/active_record/4.1/relation_extensions.rb +307 -0
- data/lib/squeel/adapters/active_record/4.2/compat.rb +1 -0
- data/lib/squeel/adapters/active_record/4.2/context.rb +1 -0
- data/lib/squeel/adapters/active_record/4.2/preloader_extensions.rb +1 -0
- data/lib/squeel/adapters/active_record/4.2/relation_extensions.rb +108 -0
- data/lib/squeel/adapters/active_record/context.rb +7 -7
- data/lib/squeel/adapters/active_record/join_dependency_extensions.rb +9 -13
- data/lib/squeel/adapters/active_record/relation_extensions.rb +38 -8
- data/lib/squeel/core_ext/symbol.rb +3 -3
- data/lib/squeel/dsl.rb +1 -1
- data/lib/squeel/nodes.rb +1 -0
- data/lib/squeel/nodes/as.rb +12 -0
- data/lib/squeel/nodes/join.rb +8 -4
- data/lib/squeel/nodes/key_path.rb +10 -1
- data/lib/squeel/nodes/node.rb +21 -0
- data/lib/squeel/nodes/stub.rb +8 -4
- data/lib/squeel/nodes/subquery_join.rb +44 -0
- data/lib/squeel/version.rb +1 -1
- data/lib/squeel/visitors.rb +2 -0
- data/lib/squeel/visitors/enumeration_visitor.rb +101 -0
- data/lib/squeel/visitors/order_visitor.rb +9 -2
- data/lib/squeel/visitors/predicate_visitor.rb +11 -0
- data/lib/squeel/visitors/preload_visitor.rb +12 -0
- data/lib/squeel/visitors/visitor.rb +89 -13
- data/spec/config.travis.yml +13 -0
- data/spec/config.yml +12 -0
- data/spec/console.rb +3 -12
- data/spec/core_ext/symbol_spec.rb +3 -3
- data/spec/helpers/squeel_helper.rb +8 -5
- data/spec/spec_helper.rb +4 -16
- data/spec/squeel/adapters/active_record/context_spec.rb +8 -4
- data/spec/squeel/adapters/active_record/join_dependency_extensions_spec.rb +123 -38
- data/spec/squeel/adapters/active_record/relation_extensions_spec.rb +350 -124
- data/spec/squeel/core_ext/symbol_spec.rb +3 -3
- data/spec/squeel/nodes/join_spec.rb +4 -4
- data/spec/squeel/nodes/stub_spec.rb +3 -3
- data/spec/squeel/nodes/subquery_join_spec.rb +46 -0
- data/spec/squeel/visitors/order_visitor_spec.rb +3 -3
- data/spec/squeel/visitors/predicate_visitor_spec.rb +69 -36
- data/spec/squeel/visitors/select_visitor_spec.rb +1 -1
- data/spec/squeel/visitors/visitor_spec.rb +7 -6
- data/spec/support/models.rb +99 -15
- data/spec/support/schema.rb +109 -4
- data/squeel.gemspec +8 -6
- metadata +89 -107
- data/.ruby-gemset +0 -1
- data/.ruby-version +0 -1
- data/spec/blueprints/articles.rb +0 -5
- data/spec/blueprints/comments.rb +0 -5
- data/spec/blueprints/notes.rb +0 -3
- data/spec/blueprints/people.rb +0 -4
- data/spec/blueprints/tags.rb +0 -3
| @@ -33,7 +33,7 @@ describe Symbol do | |
| 33 33 | 
             
                  join = :blah.inner
         | 
| 34 34 | 
             
                  join.should be_a Squeel::Nodes::Join
         | 
| 35 35 | 
             
                  join._name.should eq :blah
         | 
| 36 | 
            -
                  join._type.should eq  | 
| 36 | 
            +
                  join._type.should eq Squeel::InnerJoin
         | 
| 37 37 | 
             
                end
         | 
| 38 38 | 
             
              end
         | 
| 39 39 |  | 
| @@ -42,7 +42,7 @@ describe Symbol do | |
| 42 42 | 
             
                  join = :blah.outer
         | 
| 43 43 | 
             
                  join.should be_a Squeel::Nodes::Join
         | 
| 44 44 | 
             
                  join._name.should eq :blah
         | 
| 45 | 
            -
                  join._type.should eq  | 
| 45 | 
            +
                  join._type.should eq Squeel::OuterJoin
         | 
| 46 46 | 
             
                end
         | 
| 47 47 | 
             
              end
         | 
| 48 48 |  | 
| @@ -51,7 +51,7 @@ describe Symbol do | |
| 51 51 | 
             
                  join = :blah.of_class(Person)
         | 
| 52 52 | 
             
                  join.should be_a Squeel::Nodes::Join
         | 
| 53 53 | 
             
                  join._name.should eq :blah
         | 
| 54 | 
            -
                  join._type.should eq  | 
| 54 | 
            +
                  join._type.should eq Squeel::InnerJoin
         | 
| 55 55 | 
             
                  join._klass.should eq Person
         | 
| 56 56 | 
             
                end
         | 
| 57 57 | 
             
              end
         | 
| @@ -8,13 +8,13 @@ module Squeel | |
| 8 8 | 
             
                    @j = Join.new :name
         | 
| 9 9 | 
             
                  end
         | 
| 10 10 |  | 
| 11 | 
            -
                  it 'defaults to  | 
| 12 | 
            -
                    @j._type.should eq  | 
| 11 | 
            +
                  it 'defaults to Squeel::InnerJoin' do
         | 
| 12 | 
            +
                    @j._type.should eq Squeel::InnerJoin
         | 
| 13 13 | 
             
                  end
         | 
| 14 14 |  | 
| 15 15 | 
             
                  it 'allows setting join type' do
         | 
| 16 16 | 
             
                    @j.outer
         | 
| 17 | 
            -
                    @j._type.should eq  | 
| 17 | 
            +
                    @j._type.should eq Squeel::OuterJoin
         | 
| 18 18 | 
             
                  end
         | 
| 19 19 |  | 
| 20 20 | 
             
                  it 'allows setting polymorphic class' do
         | 
| @@ -32,7 +32,7 @@ module Squeel | |
| 32 32 | 
             
                  it 'creates a KeyPath with a join endpoint when sent a method with a Class param' do
         | 
| 33 33 | 
             
                    keypath = @j.another(Person)
         | 
| 34 34 | 
             
                    keypath.should be_a KeyPath
         | 
| 35 | 
            -
                    keypath.path.should eq [@j, Join.new(:another,  | 
| 35 | 
            +
                    keypath.path.should eq [@j, Join.new(:another, Squeel::InnerJoin, Person)]
         | 
| 36 36 | 
             
                  end
         | 
| 37 37 |  | 
| 38 38 | 
             
                  it 'creates an absolute keypath with just an endpoint with ~' do
         | 
| @@ -48,7 +48,7 @@ module Squeel | |
| 48 48 | 
             
                  it 'creates a KeyPath with a join endpoint when sent a method with a Class param' do
         | 
| 49 49 | 
             
                    keypath = @s.another(Person)
         | 
| 50 50 | 
             
                    keypath.should be_a KeyPath
         | 
| 51 | 
            -
                    keypath.path.should eq [@s, Join.new(:another,  | 
| 51 | 
            +
                    keypath.path.should eq [@s, Join.new(:another, Squeel::InnerJoin, Person)]
         | 
| 52 52 | 
             
                  end
         | 
| 53 53 |  | 
| 54 54 | 
             
                  it 'creates a KeyPath with a sifter endpoint when sent #sift' do
         | 
| @@ -189,13 +189,13 @@ module Squeel | |
| 189 189 | 
             
                  it 'creates inner joins' do
         | 
| 190 190 | 
             
                    join = @s.inner
         | 
| 191 191 | 
             
                    join.should be_a Join
         | 
| 192 | 
            -
                    join._type.should eq  | 
| 192 | 
            +
                    join._type.should eq Squeel::InnerJoin
         | 
| 193 193 | 
             
                  end
         | 
| 194 194 |  | 
| 195 195 | 
             
                  it 'creates outer joins' do
         | 
| 196 196 | 
             
                    join = @s.outer
         | 
| 197 197 | 
             
                    join.should be_a Join
         | 
| 198 | 
            -
                    join._type.should eq  | 
| 198 | 
            +
                    join._type.should eq Squeel::OuterJoin
         | 
| 199 199 | 
             
                  end
         | 
| 200 200 |  | 
| 201 201 | 
             
                  it 'creates functions with #func' do
         | 
| @@ -0,0 +1,46 @@ | |
| 1 | 
            +
            require 'spec_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Squeel
         | 
| 4 | 
            +
              module Nodes
         | 
| 5 | 
            +
                describe SubqueryJoin do
         | 
| 6 | 
            +
                  before(:each) do
         | 
| 7 | 
            +
                    @j =
         | 
| 8 | 
            +
                      if activerecord_version_at_least('4.1.0')
         | 
| 9 | 
            +
                        SubqueryJoin.new(OrderItem.all.as('items'), dsl {(items.orderable_id == id) & (items.orderable_type == 'Seat')} )
         | 
| 10 | 
            +
                      else
         | 
| 11 | 
            +
                        SubqueryJoin.new(OrderItem.scoped.as('items'), dsl {(items.orderable_id == id) & (items.orderable_type == 'Seat')} )
         | 
| 12 | 
            +
                      end
         | 
| 13 | 
            +
                  end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                  it 'defaults to Squeel::InnerJoin' do
         | 
| 16 | 
            +
                    @j.type.should eq Squeel::InnerJoin
         | 
| 17 | 
            +
                  end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                  it 'allows setting join type' do
         | 
| 20 | 
            +
                    @j.outer
         | 
| 21 | 
            +
                    @j.type.should eq Squeel::OuterJoin
         | 
| 22 | 
            +
                  end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                  it 'subquery should be a Nodes::As' do
         | 
| 25 | 
            +
                    @j.subquery.should be_kind_of(As)
         | 
| 26 | 
            +
                  end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                  it 'constraints should be a node' do
         | 
| 29 | 
            +
                    @j.constraints.should be_kind_of(Node)
         | 
| 30 | 
            +
                  end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                  it 'only convert an ActiveRecord::Relation to a SubqueryJoin' do
         | 
| 33 | 
            +
                    j =
         | 
| 34 | 
            +
                      if activerecord_version_at_least('4.1.0')
         | 
| 35 | 
            +
                        OrderItem.all.as('items').on{(items.orderable_id == id) & (items.orderable_type == 'Seat')}
         | 
| 36 | 
            +
                      else
         | 
| 37 | 
            +
                        OrderItem.scoped.as('items').on{(items.orderable_id == id) & (items.orderable_type == 'Seat')}
         | 
| 38 | 
            +
                      end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                    j.should be_kind_of(SubqueryJoin)
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                    expect { As.new('name', 'alias').on{(items.orderable_id == id) & (items.orderable_type == 'Seat')} }.to raise_error
         | 
| 43 | 
            +
                  end
         | 
| 44 | 
            +
                end
         | 
| 45 | 
            +
              end
         | 
| 46 | 
            +
            end
         | 
| @@ -18,17 +18,17 @@ module Squeel | |
| 18 18 |  | 
| 19 19 | 
             
                  it 'accepts Order with Function expression' do
         | 
| 20 20 | 
             
                    function = @v.accept(dsl{find_in_set(children.children.id, '1,2,3').desc})
         | 
| 21 | 
            -
                    function.to_sql.should match /find_in_set\( | 
| 21 | 
            +
                    function.to_sql.should match /find_in_set\(#{Q}children_people_2#{Q}.#{Q}id#{Q}, '1,2,3'\) DESC/
         | 
| 22 22 | 
             
                  end
         | 
| 23 23 |  | 
| 24 24 | 
             
                  it 'accepts Order with Operation expression' do
         | 
| 25 25 | 
             
                    operation = @v.accept(dsl{(id / 1).desc})
         | 
| 26 | 
            -
                    operation.to_sql.should match  | 
| 26 | 
            +
                    operation.to_sql.should match /#{Q}people#{Q}.#{Q}id#{Q} \/ 1 DESC/
         | 
| 27 27 | 
             
                  end
         | 
| 28 28 |  | 
| 29 29 | 
             
                  it 'orders by predicates' do
         | 
| 30 30 | 
             
                    orders = @v.accept(dsl{name == 'Ernie'})
         | 
| 31 | 
            -
                    orders.to_sql.should match  | 
| 31 | 
            +
                    orders.to_sql.should match /#{Q}people#{Q}.#{Q}name#{Q} = 'Ernie'/
         | 
| 32 32 | 
             
                  end
         | 
| 33 33 |  | 
| 34 34 | 
             
                end
         | 
| @@ -23,25 +23,38 @@ module Squeel | |
| 23 23 | 
             
                    node.right.should be_a Arel::Nodes::SelectStatement
         | 
| 24 24 | 
             
                  end
         | 
| 25 25 |  | 
| 26 | 
            -
                  it ' | 
| 26 | 
            +
                  it 'quote nil values in Predicate nodes' do
         | 
| 27 27 | 
             
                    predicate = Nodes::Predicate.new(Nodes::Function.new(:blah, [1, 2]), :in, nil)
         | 
| 28 28 | 
             
                    node = @v.accept(predicate)
         | 
| 29 29 | 
             
                    node.should be_a Arel::Nodes::In
         | 
| 30 | 
            -
                     | 
| 30 | 
            +
                    if defined?(Arel::Nodes::Quoted)
         | 
| 31 | 
            +
                      node.right.expr.should == 'NULL'
         | 
| 32 | 
            +
                    else
         | 
| 33 | 
            +
                      node.right.should be_nil
         | 
| 34 | 
            +
                    end
         | 
| 35 | 
            +
             | 
| 31 36 | 
             
                  end
         | 
| 32 37 |  | 
| 33 38 | 
             
                  it 'creates Equality nodes for simple hashes' do
         | 
| 34 39 | 
             
                    predicate = @v.accept(:name => 'Joe')
         | 
| 35 40 | 
             
                    predicate.should be_a Arel::Nodes::Equality
         | 
| 36 41 | 
             
                    predicate.left.name.to_s.should eq 'name'
         | 
| 37 | 
            -
                     | 
| 42 | 
            +
                    if defined?(Arel::Nodes::Casted)
         | 
| 43 | 
            +
                      predicate.right.val.should eq 'Joe'
         | 
| 44 | 
            +
                    else
         | 
| 45 | 
            +
                      predicate.right.should eq 'Joe'
         | 
| 46 | 
            +
                    end
         | 
| 38 47 | 
             
                  end
         | 
| 39 48 |  | 
| 40 49 | 
             
                  it 'creates In nodes for simple hashes with an array as a value' do
         | 
| 41 50 | 
             
                    predicate = @v.accept(:name => ['Joe', 'Bob'])
         | 
| 42 51 | 
             
                    predicate.should be_a Arel::Nodes::In
         | 
| 43 52 | 
             
                    predicate.left.name.to_s.should eq 'name'
         | 
| 44 | 
            -
                     | 
| 53 | 
            +
                    if defined?(Arel::Nodes::Casted)
         | 
| 54 | 
            +
                      predicate.right.map(&:val).should eq ['Joe', 'Bob']
         | 
| 55 | 
            +
                    else
         | 
| 56 | 
            +
                      predicate.right.should eq ['Joe', 'Bob']
         | 
| 57 | 
            +
                    end
         | 
| 45 58 | 
             
                  end
         | 
| 46 59 |  | 
| 47 60 | 
             
                  it 'generates "1=0" when given an empty array value in a hash' do
         | 
| @@ -88,32 +101,32 @@ module Squeel | |
| 88 101 |  | 
| 89 102 | 
             
                  it 'generates IS NULL for hash keys with a value of [nil]' do
         | 
| 90 103 | 
             
                    predicate = @v.accept(:id => [nil])
         | 
| 91 | 
            -
                    predicate.to_sql.should be_like  | 
| 104 | 
            +
                    predicate.to_sql.should be_like "#{Q}people#{Q}.#{Q}id#{Q} IS NULL"
         | 
| 92 105 | 
             
                  end
         | 
| 93 106 |  | 
| 94 107 | 
             
                  it 'generates IS NULL for in predicates with a value of [nil]' do
         | 
| 95 108 | 
             
                    predicate = @v.accept(:id.in => [nil])
         | 
| 96 | 
            -
                    predicate.to_sql.should be_like  | 
| 109 | 
            +
                    predicate.to_sql.should be_like "#{Q}people#{Q}.#{Q}id#{Q} IS NULL"
         | 
| 97 110 | 
             
                  end
         | 
| 98 111 |  | 
| 99 112 | 
             
                  it 'generates IS NOT NULL for not_in predicates with a value of [nil]' do
         | 
| 100 113 | 
             
                    predicate = @v.accept(:id.not_in => [nil])
         | 
| 101 | 
            -
                    predicate.to_sql.should be_like  | 
| 114 | 
            +
                    predicate.to_sql.should be_like "#{Q}people#{Q}.#{Q}id#{Q} IS NOT NULL"
         | 
| 102 115 | 
             
                  end
         | 
| 103 116 |  | 
| 104 117 | 
             
                  it 'generates IN OR IS NULL for hash keys with a value of [1, 2, 3, nil]' do
         | 
| 105 118 | 
             
                    predicate = @v.accept(:id => [1, 2, 3, nil])
         | 
| 106 | 
            -
                    predicate.to_sql.should be_like  | 
| 119 | 
            +
                    predicate.to_sql.should be_like "(#{Q}people#{Q}.#{Q}id#{Q} IN (1, 2, 3) OR #{Q}people#{Q}.#{Q}id#{Q} IS NULL)"
         | 
| 107 120 | 
             
                  end
         | 
| 108 121 |  | 
| 109 122 | 
             
                  it 'generates IN OR IS NULL for in predicates with a value of [1, 2, 3, nil]' do
         | 
| 110 123 | 
             
                    predicate = @v.accept(:id.in => [1, 2, 3, nil])
         | 
| 111 | 
            -
                    predicate.to_sql.should be_like  | 
| 124 | 
            +
                    predicate.to_sql.should be_like "(#{Q}people#{Q}.#{Q}id#{Q} IN (1, 2, 3) OR #{Q}people#{Q}.#{Q}id#{Q} IS NULL)"
         | 
| 112 125 | 
             
                  end
         | 
| 113 126 |  | 
| 114 127 | 
             
                  it 'generates IN AND IS NOT NULL for not_in predicates with a value of [1, 2, 3, nil]' do
         | 
| 115 128 | 
             
                    predicate = @v.accept(:id.not_in => [1, 2, 3, nil])
         | 
| 116 | 
            -
                    predicate.to_sql.should be_like  | 
| 129 | 
            +
                    predicate.to_sql.should be_like "#{Q}people#{Q}.#{Q}id#{Q} NOT IN (1, 2, 3) AND #{Q}people#{Q}.#{Q}id#{Q} IS NOT NULL"
         | 
| 117 130 | 
             
                  end
         | 
| 118 131 |  | 
| 119 132 | 
             
                  it 'allows a subquery on the value side of an explicit predicate' do
         | 
| @@ -133,39 +146,47 @@ module Squeel | |
| 133 146 | 
             
                  it 'selects the primary key of a relation with no select_values with an explicit predicate' do
         | 
| 134 147 | 
             
                    predicate = @v.accept dsl{name.in(PersonWithNamePrimaryKey.where{name.in(['Aric Smith', 'Gladyce Kulas'])})}
         | 
| 135 148 | 
             
                    predicate.right.should be_a Arel::Nodes::SelectStatement
         | 
| 136 | 
            -
                    predicate.right.to_sql.should match /SELECT  | 
| 149 | 
            +
                    predicate.right.to_sql.should match /SELECT #{Q}people#{Q}.#{Q}name#{Q}/
         | 
| 137 150 | 
             
                  end
         | 
| 138 151 |  | 
| 139 152 | 
             
                  it 'selects the primary key of a relation with no select_values with an implicit predicate' do
         | 
| 140 153 | 
             
                    predicate = @v.accept(:name => PersonWithNamePrimaryKey.where{name.in(['Aric Smith', 'Gladyce Kulas'])})
         | 
| 141 154 | 
             
                    predicate.right.should be_a Arel::Nodes::SelectStatement
         | 
| 142 | 
            -
                    predicate.right.to_sql.should match /SELECT  | 
| 155 | 
            +
                    predicate.right.to_sql.should match /SELECT #{Q}people#{Q}.#{Q}name#{Q}/
         | 
| 143 156 | 
             
                  end
         | 
| 144 157 |  | 
| 145 158 | 
             
                  it "doesn't clobber a relation value's existing select_values if present with an explicit predicate" do
         | 
| 146 159 | 
             
                    predicate = @v.accept dsl{name.in(Person.select{name})}
         | 
| 147 160 | 
             
                    predicate.right.should be_a Arel::Nodes::SelectStatement
         | 
| 148 | 
            -
                    predicate.right.to_sql.should match /SELECT  | 
| 161 | 
            +
                    predicate.right.to_sql.should match /SELECT #{Q}people#{Q}.#{Q}name#{Q}/
         | 
| 149 162 | 
             
                  end
         | 
| 150 163 |  | 
| 151 164 | 
             
                  it "doesn't clobber a relation value's existing select_values if present with an implicit predicate" do
         | 
| 152 165 | 
             
                    predicate = @v.accept(:name => Person.select{name})
         | 
| 153 166 | 
             
                    predicate.right.should be_a Arel::Nodes::SelectStatement
         | 
| 154 | 
            -
                    predicate.right.to_sql.should match /SELECT  | 
| 167 | 
            +
                    predicate.right.to_sql.should match /SELECT #{Q}people#{Q}.#{Q}name#{Q}/
         | 
| 155 168 | 
             
                  end
         | 
| 156 169 |  | 
| 157 170 | 
             
                  it 'converts ActiveRecord::Base objects to their id' do
         | 
| 158 171 | 
             
                    predicate = @v.accept(:id => Person.first)
         | 
| 159 172 | 
             
                    predicate.should be_a Arel::Nodes::Equality
         | 
| 160 173 | 
             
                    predicate.left.name.to_s.should eq 'id'
         | 
| 161 | 
            -
                     | 
| 174 | 
            +
                    if defined?(Arel::Nodes::Casted)
         | 
| 175 | 
            +
                      predicate.right.val.should eq 1
         | 
| 176 | 
            +
                    else
         | 
| 177 | 
            +
                      predicate.right.should eq 1
         | 
| 178 | 
            +
                    end
         | 
| 162 179 | 
             
                  end
         | 
| 163 180 |  | 
| 164 181 | 
             
                  it 'converts arrays of ActiveRecord::Base objects to their ids' do
         | 
| 165 182 | 
             
                    predicate = @v.accept(:id => [Person.first, Person.last])
         | 
| 166 183 | 
             
                    predicate.should be_a Arel::Nodes::In
         | 
| 167 184 | 
             
                    predicate.left.name.to_s.should eq 'id'
         | 
| 168 | 
            -
                     | 
| 185 | 
            +
                    if defined?(Arel::Nodes::Casted)
         | 
| 186 | 
            +
                      predicate.right.map(&:val).should eq [Person.first.id, Person.last.id]
         | 
| 187 | 
            +
                    else
         | 
| 188 | 
            +
                      predicate.right.should eq [Person.first.id, Person.last.id]
         | 
| 189 | 
            +
                    end
         | 
| 169 190 | 
             
                  end
         | 
| 170 191 |  | 
| 171 192 | 
             
                  it 'creates the node against the proper table for nested hashes' do
         | 
| @@ -182,7 +203,11 @@ module Squeel | |
| 182 203 | 
             
                    })
         | 
| 183 204 | 
             
                    predicate.should be_a Arel::Nodes::Equality
         | 
| 184 205 | 
             
                    predicate.left.relation.table_alias.should eq 'parents_people_2'
         | 
| 185 | 
            -
                     | 
| 206 | 
            +
                    if defined?(Arel::Nodes::Casted)
         | 
| 207 | 
            +
                      predicate.right.val.should eq 'Joe'
         | 
| 208 | 
            +
                    else
         | 
| 209 | 
            +
                      predicate.right.should eq 'Joe'
         | 
| 210 | 
            +
                    end
         | 
| 186 211 | 
             
                  end
         | 
| 187 212 |  | 
| 188 213 | 
             
                  it 'treats keypath keys like nested hashes' do
         | 
| @@ -255,28 +280,28 @@ module Squeel | |
| 255 280 | 
             
                    predicate = @v.accept(dsl{{name => name}})
         | 
| 256 281 | 
             
                    predicate.should be_a Arel::Nodes::Equality
         | 
| 257 282 | 
             
                    predicate.right.should be_a Arel::Attribute
         | 
| 258 | 
            -
                    predicate.to_sql.should match  | 
| 283 | 
            +
                    predicate.to_sql.should match /#{Q}people#{Q}.#{Q}name#{Q} = #{Q}people#{Q}.#{Q}name#{Q}/
         | 
| 259 284 | 
             
                  end
         | 
| 260 285 |  | 
| 261 286 | 
             
                  it 'contextualizes Symbol values' do
         | 
| 262 287 | 
             
                    predicate = @v.accept(:name => :name)
         | 
| 263 288 | 
             
                    predicate.should be_a Arel::Nodes::Equality
         | 
| 264 289 | 
             
                    predicate.right.should be_a Arel::Attribute
         | 
| 265 | 
            -
                    predicate.to_sql.should match  | 
| 290 | 
            +
                    predicate.to_sql.should match /#{Q}people#{Q}.#{Q}name#{Q} = #{Q}people#{Q}.#{Q}name#{Q}/
         | 
| 266 291 | 
             
                  end
         | 
| 267 292 |  | 
| 268 293 | 
             
                  it 'contextualizes KeyPath values in hashes' do
         | 
| 269 294 | 
             
                    predicate = @v.accept(dsl{{name => children.name}})
         | 
| 270 295 | 
             
                    predicate.should be_a Arel::Nodes::Equality
         | 
| 271 296 | 
             
                    predicate.right.should be_a Arel::Attribute
         | 
| 272 | 
            -
                    predicate.to_sql.should match  | 
| 297 | 
            +
                    predicate.to_sql.should match /#{Q}people#{Q}.#{Q}name#{Q} = #{Q}children_people#{Q}.#{Q}name#{Q}/
         | 
| 273 298 | 
             
                  end
         | 
| 274 299 |  | 
| 275 300 | 
             
                  it 'contextualizes KeyPath values in predicates' do
         | 
| 276 301 | 
             
                    predicate = @v.accept(dsl{name == children.name})
         | 
| 277 302 | 
             
                    predicate.should be_a Arel::Nodes::Equality
         | 
| 278 303 | 
             
                    predicate.right.should be_a Arel::Attribute
         | 
| 279 | 
            -
                    predicate.to_sql.should match  | 
| 304 | 
            +
                    predicate.to_sql.should match /#{Q}people#{Q}.#{Q}name#{Q} = #{Q}children_people#{Q}.#{Q}name#{Q}/
         | 
| 280 305 | 
             
                  end
         | 
| 281 306 |  | 
| 282 307 | 
             
                  it 'visits Squeel Sifters at top level' do
         | 
| @@ -284,8 +309,8 @@ module Squeel | |
| 284 309 | 
             
                    predicate.should be_a Arel::Nodes::Grouping
         | 
| 285 310 | 
             
                    expr = predicate.expr
         | 
| 286 311 | 
             
                    expr.should be_a Arel::Nodes::Or
         | 
| 287 | 
            -
                    expr.left.to_sql.should match  | 
| 288 | 
            -
                    expr.right.to_sql.should match  | 
| 312 | 
            +
                    expr.left.to_sql.should match /#{Q}people#{Q}.#{Q}name#{Q} [I]*LIKE 'smith%'/
         | 
| 313 | 
            +
                    expr.right.to_sql.should match /#{Q}people#{Q}.#{Q}name#{Q} [I]*LIKE '%smith'/
         | 
| 289 314 | 
             
                  end
         | 
| 290 315 |  | 
| 291 316 | 
             
                  it 'visits nested Squeel sifters' do
         | 
| @@ -293,8 +318,8 @@ module Squeel | |
| 293 318 | 
             
                    predicate.should be_a Arel::Nodes::Grouping
         | 
| 294 319 | 
             
                    expr = predicate.expr
         | 
| 295 320 | 
             
                    expr.should be_a Arel::Nodes::Or
         | 
| 296 | 
            -
                    expr.left.to_sql.should match  | 
| 297 | 
            -
                    expr.right.to_sql.should match  | 
| 321 | 
            +
                    expr.left.to_sql.should match /#{Q}children_people#{Q}.#{Q}name#{Q} [I]*LIKE 'smith%'/
         | 
| 322 | 
            +
                    expr.right.to_sql.should match /#{Q}children_people#{Q}.#{Q}name#{Q} [I]*LIKE '%smith'/
         | 
| 298 323 | 
             
                  end
         | 
| 299 324 |  | 
| 300 325 | 
             
                  it 'visits sifters in a keypath' do
         | 
| @@ -302,14 +327,14 @@ module Squeel | |
| 302 327 | 
             
                    predicate.should be_a Arel::Nodes::Grouping
         | 
| 303 328 | 
             
                    expr = predicate.expr
         | 
| 304 329 | 
             
                    expr.should be_a Arel::Nodes::Or
         | 
| 305 | 
            -
                    expr.left.to_sql.should match  | 
| 306 | 
            -
                    expr.right.to_sql.should match  | 
| 330 | 
            +
                    expr.left.to_sql.should match /#{Q}children_people#{Q}.#{Q}name#{Q} [I]*LIKE 'smith%'/
         | 
| 331 | 
            +
                    expr.right.to_sql.should match /#{Q}children_people#{Q}.#{Q}name#{Q} [I]*LIKE '%smith'/
         | 
| 307 332 | 
             
                  end
         | 
| 308 333 |  | 
| 309 334 | 
             
                  it 'honors an explicit table in string keys' do
         | 
| 310 335 | 
             
                    predicate = @v.accept('things.attribute' => 'retro')
         | 
| 311 336 | 
             
                    predicate.should be_a Arel::Nodes::Equality
         | 
| 312 | 
            -
                    predicate.to_sql.should match  | 
| 337 | 
            +
                    predicate.to_sql.should match /#{Q}things#{Q}.#{Q}attribute#{Q} = 'retro'/
         | 
| 313 338 | 
             
                  end
         | 
| 314 339 |  | 
| 315 340 | 
             
                  it 'does not allow "table.column" keys after context change' do
         | 
| @@ -324,28 +349,32 @@ module Squeel | |
| 324 349 | 
             
                    predicate = @v.accept(dsl{id >> Person.select{id}.limit(3).order{id.desc}})
         | 
| 325 350 | 
             
                    predicate.should be_a Arel::Nodes::In
         | 
| 326 351 | 
             
                    predicate.right.should be_a Arel::Nodes::SelectStatement
         | 
| 327 | 
            -
                    predicate.to_sql.should be_like  | 
| 352 | 
            +
                    predicate.to_sql.should be_like "#{Q}people#{Q}.#{Q}id#{Q} IN (SELECT  #{Q}people#{Q}.#{Q}id#{Q} FROM #{Q}people#{Q}  ORDER BY #{Q}people#{Q}.#{Q}id#{Q} DESC LIMIT 3)"
         | 
| 328 353 | 
             
                  end
         | 
| 329 354 |  | 
| 330 355 | 
             
                  it 'converts ActiveRecord::Relation values in function arguments to their Arel AST' do
         | 
| 331 356 | 
             
                    predicate = @v.accept(dsl{exists(Person.where{name == 'Aric Smith'})})
         | 
| 332 357 | 
             
                    predicate.should be_a Arel::Nodes::NamedFunction
         | 
| 333 358 | 
             
                    predicate.expressions.first.should be_a Arel::Nodes::SelectStatement
         | 
| 334 | 
            -
                    predicate.to_sql.should be_like "exists(SELECT  | 
| 359 | 
            +
                    predicate.to_sql.should be_like "exists(SELECT #{Q}people#{Q}.* FROM #{Q}people#{Q}  WHERE #{Q}people#{Q}.#{Q}name#{Q} = 'Aric Smith')"
         | 
| 335 360 | 
             
                  end
         | 
| 336 361 |  | 
| 337 362 | 
             
                  it "doesn't try to sanitize_sql an array of strings in the value of a Predicate" do
         | 
| 338 363 | 
             
                    predicate = @v.accept(dsl{name >> ['Aric Smith', 'Gladyce Kulas']})
         | 
| 339 364 | 
             
                    predicate.should be_a Arel::Nodes::In
         | 
| 340 365 | 
             
                    predicate.right.should be_an Array
         | 
| 341 | 
            -
                    predicate.to_sql.should match  | 
| 366 | 
            +
                    predicate.to_sql.should match /#{Q}people#{Q}.#{Q}name#{Q} IN \('Aric Smith', 'Gladyce Kulas'\)/
         | 
| 342 367 | 
             
                  end
         | 
| 343 368 |  | 
| 344 369 | 
             
                  it 'creates a node of the proper type when a hash has a Predicate as a key' do
         | 
| 345 370 | 
             
                    predicate = @v.accept(:name.matches => 'Joe%')
         | 
| 346 371 | 
             
                    predicate.should be_a Arel::Nodes::Matches
         | 
| 347 372 | 
             
                    predicate.left.name.should eq :name
         | 
| 348 | 
            -
                     | 
| 373 | 
            +
                    if defined?(Arel::Nodes::Casted)
         | 
| 374 | 
            +
                      predicate.right.val.should eq 'Joe%'
         | 
| 375 | 
            +
                    else
         | 
| 376 | 
            +
                      predicate.right.should eq 'Joe%'
         | 
| 377 | 
            +
                    end
         | 
| 349 378 | 
             
                  end
         | 
| 350 379 |  | 
| 351 380 | 
             
                  it 'treats hash keys as an association when there is an Or on the value side' do
         | 
| @@ -383,7 +412,11 @@ module Squeel | |
| 383 412 | 
             
                    predicate.should be_a Arel::Nodes::Equality
         | 
| 384 413 | 
             
                    predicate.left.relation.table_alias.should eq 'children_people_2'
         | 
| 385 414 | 
             
                    predicate.left.name.to_s.should eq 'name'
         | 
| 386 | 
            -
                     | 
| 415 | 
            +
                    if defined?(Arel::Nodes::Casted)
         | 
| 416 | 
            +
                    predicate.right.val.should eq 'Joe'
         | 
| 417 | 
            +
                    else
         | 
| 418 | 
            +
                      predicate.right.should eq 'Joe'
         | 
| 419 | 
            +
                    end
         | 
| 387 420 | 
             
                  end
         | 
| 388 421 |  | 
| 389 422 | 
             
                  it 'creates an Arel Grouping node containing an Or node for Or nodes' do
         | 
| @@ -409,7 +442,7 @@ module Squeel | |
| 409 442 |  | 
| 410 443 | 
             
                  it 'maps symbols in Function args to Arel attributes' do
         | 
| 411 444 | 
             
                    function = @v.accept(:find_in_set.func(:id, '1,2,3'))
         | 
| 412 | 
            -
                    function.to_sql.should match  | 
| 445 | 
            +
                    function.to_sql.should match /#{Q}people#{Q}.#{Q}id#{Q}/
         | 
| 413 446 | 
             
                  end
         | 
| 414 447 |  | 
| 415 448 | 
             
                  it 'sets the alias on the Arel NamedFunction from the Function alias' do
         | 
| @@ -419,12 +452,12 @@ module Squeel | |
| 419 452 |  | 
| 420 453 | 
             
                  it 'accepts As nodes containing symbols' do
         | 
| 421 454 | 
             
                    as = @v.accept(:name.as('other_name'))
         | 
| 422 | 
            -
                    as.to_sql.should match  | 
| 455 | 
            +
                    as.to_sql.should match /#{Q}people#{Q}.#{Q}name#{Q} AS other_name/
         | 
| 423 456 | 
             
                  end
         | 
| 424 457 |  | 
| 425 458 | 
             
                  it 'accepts As nodes containing stubs' do
         | 
| 426 459 | 
             
                    as = @v.accept(dsl{name.as(other_name)})
         | 
| 427 | 
            -
                    as.to_sql.should match  | 
| 460 | 
            +
                    as.to_sql.should match /#{Q}people#{Q}.#{Q}name#{Q} AS other_name/
         | 
| 428 461 | 
             
                  end
         | 
| 429 462 |  | 
| 430 463 | 
             
                  it 'creates an Arel Addition node for an Operation node with + as operator' do
         | 
| @@ -33,6 +33,7 @@ module Squeel | |
| 33 33 | 
             
                        }
         | 
| 34 34 | 
             
                      }
         | 
| 35 35 | 
             
                    })
         | 
| 36 | 
            +
             | 
| 36 37 | 
             
                    attributes.should be_a Array
         | 
| 37 38 | 
             
                    attribute = attributes.first
         | 
| 38 39 | 
             
                    attribute.should be_a Arel::Attributes::Attribute
         | 
| @@ -68,7 +69,7 @@ module Squeel | |
| 68 69 | 
             
                  it 'allows a subquery as a selection' do
         | 
| 69 70 | 
             
                    relation = Person.where(:name => 'Aric Smith').select(:id)
         | 
| 70 71 | 
             
                    node = @v.accept(relation.as('aric'))
         | 
| 71 | 
            -
                    node.to_sql.should be_like "(SELECT  | 
| 72 | 
            +
                    node.to_sql.should be_like "(SELECT #{Q}people#{Q}.#{Q}id#{Q} FROM #{Q}people#{Q}  WHERE #{Q}people#{Q}.#{Q}name#{Q} = 'Aric Smith') aric"
         | 
| 72 73 | 
             
                  end
         | 
| 73 74 |  | 
| 74 75 | 
             
                  it 'creates an Arel NamedFunction node for a Function node' do
         | 
| @@ -78,12 +79,12 @@ module Squeel | |
| 78 79 |  | 
| 79 80 | 
             
                  it 'maps symbols in Function args to Arel attributes' do
         | 
| 80 81 | 
             
                    function = @v.accept(:find_in_set.func(:id, '1,2,3'))
         | 
| 81 | 
            -
                    function.to_sql.should match /find_in_set\( | 
| 82 | 
            +
                    function.to_sql.should match /find_in_set\(#{Q}people#{Q}.#{Q}id#{Q}, '1,2,3'\)/
         | 
| 82 83 | 
             
                  end
         | 
| 83 84 |  | 
| 84 85 | 
             
                  it 'accepts keypaths as function args' do
         | 
| 85 86 | 
             
                    function = @v.accept(dsl{find_in_set(children.children.id, '1,2,3')})
         | 
| 86 | 
            -
                    function.to_sql.should match /find_in_set\( | 
| 87 | 
            +
                    function.to_sql.should match /find_in_set\(#{Q}children_people_2#{Q}.#{Q}id#{Q}, '1,2,3'\)/
         | 
| 87 88 | 
             
                  end
         | 
| 88 89 |  | 
| 89 90 | 
             
                  it 'sets the alias on the Arel NamedFunction from the Function alias' do
         | 
| @@ -93,17 +94,17 @@ module Squeel | |
| 93 94 |  | 
| 94 95 | 
             
                  it 'accepts As nodes containing symbols' do
         | 
| 95 96 | 
             
                    as = @v.accept(:name.as('other_name'))
         | 
| 96 | 
            -
                    as.to_sql.should match  | 
| 97 | 
            +
                    as.to_sql.should match /#{Q}people#{Q}.#{Q}name#{Q} AS other_name/
         | 
| 97 98 | 
             
                  end
         | 
| 98 99 |  | 
| 99 100 | 
             
                  it 'accepts As nodes containing stubs' do
         | 
| 100 101 | 
             
                    as = @v.accept(dsl{name.as(other_name)})
         | 
| 101 | 
            -
                    as.to_sql.should match  | 
| 102 | 
            +
                    as.to_sql.should match /#{Q}people#{Q}.#{Q}name#{Q} AS other_name/
         | 
| 102 103 | 
             
                  end
         | 
| 103 104 |  | 
| 104 105 | 
             
                  it 'accepts As nodes containing keypaths' do
         | 
| 105 106 | 
             
                    as = @v.accept(dsl{children.name.as(other_name)})
         | 
| 106 | 
            -
                    as.to_sql.should match  | 
| 107 | 
            +
                    as.to_sql.should match /#{Q}children_people#{Q}.#{Q}name#{Q} AS other_name/
         | 
| 107 108 | 
             
                  end
         | 
| 108 109 |  | 
| 109 110 | 
             
                  it 'creates an Arel Grouping node for a Squeel Grouping node' do
         |