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
| @@ -3,66 +3,151 @@ require 'spec_helper' | |
| 3 3 | 
             
            module Squeel
         | 
| 4 4 | 
             
              module Adapters
         | 
| 5 5 | 
             
                module ActiveRecord
         | 
| 6 | 
            -
                  describe JoinDependencyExtensions do
         | 
| 7 | 
            -
                    before do
         | 
| 8 | 
            -
                      @jd = new_join_dependency(Person, {}, [])
         | 
| 9 | 
            -
                    end
         | 
| 10 | 
            -
             | 
| 6 | 
            +
                  describe "JoinDependencyExtensions" do
         | 
| 11 7 | 
             
                    it 'joins with symbols' do
         | 
| 12 | 
            -
                      @jd | 
| 13 | 
            -
             | 
| 14 | 
            -
                       | 
| 15 | 
            -
                         | 
| 8 | 
            +
                      @jd = new_join_dependency(Person, { :articles => :comments }, [])
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                      if activerecord_version_at_least('4.2.0')
         | 
| 11 | 
            +
                        @jd.join_constraints([]).should have(2).join_info
         | 
| 12 | 
            +
                        @jd.join_constraints([]).map(&:joins).flatten.each do |join|
         | 
| 13 | 
            +
                          join.class.should eq Squeel::InnerJoin
         | 
| 14 | 
            +
                        end
         | 
| 15 | 
            +
                      elsif activerecord_version_at_least('4.1.0')
         | 
| 16 | 
            +
                        @jd.join_constraints([]).should have(2).joins
         | 
| 17 | 
            +
                        @jd.join_constraints([]).each do |join|
         | 
| 18 | 
            +
                          join.class.should eq Squeel::InnerJoin
         | 
| 19 | 
            +
                        end
         | 
| 20 | 
            +
                      else
         | 
| 21 | 
            +
                        @jd.join_associations.should have(2).associations
         | 
| 22 | 
            +
                        @jd.join_associations.each do |association|
         | 
| 23 | 
            +
                          association.join_type.should eq Squeel::InnerJoin
         | 
| 24 | 
            +
                        end
         | 
| 16 25 | 
             
                      end
         | 
| 17 26 | 
             
                    end
         | 
| 18 27 |  | 
| 19 28 | 
             
                    it 'joins has_many :through associations' do
         | 
| 20 | 
            -
                      @jd | 
| 21 | 
            -
             | 
| 22 | 
            -
                       | 
| 29 | 
            +
                      @jd = new_join_dependency(Person, :authored_article_comments, [])
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                      if activerecord_version_at_least('4.2.0')
         | 
| 32 | 
            +
                        @jd.join_constraints([]).should have(1).join_info
         | 
| 33 | 
            +
                        @jd.join_root.children.first.table_name.should eq 'comments'
         | 
| 34 | 
            +
                      elsif activerecord_version_at_least('4.1.0')
         | 
| 35 | 
            +
                        @jd.join_constraints([]).should have(2).joins
         | 
| 36 | 
            +
                        @jd.join_root.children.first.table_name.should eq 'comments'
         | 
| 37 | 
            +
                      else
         | 
| 38 | 
            +
                        @jd.join_associations.should have(1).association
         | 
| 39 | 
            +
                        @jd.join_associations.first.table_name.should eq 'comments'
         | 
| 40 | 
            +
                      end
         | 
| 23 41 | 
             
                    end
         | 
| 24 42 |  | 
| 25 43 | 
             
                    it 'joins with stubs' do
         | 
| 26 | 
            -
                      @jd | 
| 27 | 
            -
             | 
| 28 | 
            -
                       | 
| 29 | 
            -
                         | 
| 44 | 
            +
                      @jd = new_join_dependency(Person, { Squeel::Nodes::Stub.new(:articles) => Squeel::Nodes::Stub.new(:comments) }, [])
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                      if activerecord_version_at_least('4.2.0')
         | 
| 47 | 
            +
                        @jd.join_constraints([]).should have(2).join_info
         | 
| 48 | 
            +
                        @jd.join_constraints([]).map(&:joins).flatten.each do |join|
         | 
| 49 | 
            +
                          join.class.should eq Squeel::InnerJoin
         | 
| 50 | 
            +
                        end
         | 
| 51 | 
            +
                        @jd.join_root.children.first.table_name.should eq 'articles'
         | 
| 52 | 
            +
                        @jd.join_root.children.first.children.first.table_name.should eq 'comments'
         | 
| 53 | 
            +
                      elsif activerecord_version_at_least('4.1.0')
         | 
| 54 | 
            +
                        @jd.join_constraints([]).should have(2).joins
         | 
| 55 | 
            +
                        @jd.join_constraints([]).each do |join|
         | 
| 56 | 
            +
                          join.class.should eq Squeel::InnerJoin
         | 
| 57 | 
            +
                        end
         | 
| 58 | 
            +
                        @jd.join_root.children.first.table_name.should eq 'articles'
         | 
| 59 | 
            +
                        @jd.join_root.children.first.children.first.table_name.should eq 'comments'
         | 
| 60 | 
            +
                      else
         | 
| 61 | 
            +
                        @jd.join_associations.should have(2).associations
         | 
| 62 | 
            +
                        @jd.join_associations.each do |association|
         | 
| 63 | 
            +
                          association.join_type.should eq Squeel::InnerJoin
         | 
| 64 | 
            +
                        end
         | 
| 65 | 
            +
                        @jd.join_associations[0].table_name.should eq 'articles'
         | 
| 66 | 
            +
                        @jd.join_associations[1].table_name.should eq 'comments'
         | 
| 30 67 | 
             
                      end
         | 
| 31 | 
            -
                      @jd.join_associations[0].table_name.should eq 'articles'
         | 
| 32 | 
            -
                      @jd.join_associations[1].table_name.should eq 'comments'
         | 
| 33 68 | 
             
                    end
         | 
| 34 69 |  | 
| 35 70 | 
             
                    it 'joins with key paths' do
         | 
| 36 | 
            -
                      @jd | 
| 37 | 
            -
             | 
| 38 | 
            -
                       | 
| 39 | 
            -
                         | 
| 71 | 
            +
                      @jd = new_join_dependency(Person, dsl{ children.children.parent }, [])
         | 
| 72 | 
            +
             | 
| 73 | 
            +
                      if activerecord_version_at_least('4.2.0')
         | 
| 74 | 
            +
                        @jd.join_constraints([]).should have(3).join_info
         | 
| 75 | 
            +
                        @jd.join_constraints([]).map(&:joins).flatten.each do |join|
         | 
| 76 | 
            +
                          join.class.should eq Squeel::InnerJoin
         | 
| 77 | 
            +
                        end
         | 
| 78 | 
            +
                        (children_people = @jd.join_root.children.first).aliased_table_name.should eq 'children_people'
         | 
| 79 | 
            +
                        (children_people2 = children_people.children.first).aliased_table_name.should eq 'children_people_2'
         | 
| 80 | 
            +
                        children_people2.children.first.aliased_table_name.should eq 'parents_people'
         | 
| 81 | 
            +
                      elsif activerecord_version_at_least('4.1.0')
         | 
| 82 | 
            +
                        @jd.join_constraints([]).should have(3).joins
         | 
| 83 | 
            +
                        @jd.join_constraints([]).each do |join|
         | 
| 84 | 
            +
                          join.class.should eq Squeel::InnerJoin
         | 
| 85 | 
            +
                        end
         | 
| 86 | 
            +
                        (children_people = @jd.join_root.children.first).aliased_table_name.should eq 'children_people'
         | 
| 87 | 
            +
                        (children_people2 = children_people.children.first).aliased_table_name.should eq 'children_people_2'
         | 
| 88 | 
            +
                        children_people2.children.first.aliased_table_name.should eq 'parents_people'
         | 
| 89 | 
            +
                      else
         | 
| 90 | 
            +
                        @jd.join_associations.should have(3).associations
         | 
| 91 | 
            +
                        @jd.join_associations.each do |association|
         | 
| 92 | 
            +
                          association.join_type.should eq Squeel::InnerJoin
         | 
| 93 | 
            +
                        end
         | 
| 94 | 
            +
                        @jd.join_associations[0].aliased_table_name.should eq 'children_people'
         | 
| 95 | 
            +
                        @jd.join_associations[1].aliased_table_name.should eq 'children_people_2'
         | 
| 96 | 
            +
                        @jd.join_associations[2].aliased_table_name.should eq 'parents_people'
         | 
| 40 97 | 
             
                      end
         | 
| 41 | 
            -
                      @jd.join_associations[0].aliased_table_name.should eq 'children_people'
         | 
| 42 | 
            -
                      @jd.join_associations[1].aliased_table_name.should eq 'children_people_2'
         | 
| 43 | 
            -
                      @jd.join_associations[2].aliased_table_name.should eq 'parents_people'
         | 
| 44 98 | 
             
                    end
         | 
| 45 99 |  | 
| 46 100 | 
             
                    it 'joins with key paths as keys' do
         | 
| 47 | 
            -
                      @jd | 
| 48 | 
            -
             | 
| 49 | 
            -
                       | 
| 50 | 
            -
                         | 
| 101 | 
            +
                      @jd = new_join_dependency(Person, dsl{ { children.parent => parent } }, [])
         | 
| 102 | 
            +
             | 
| 103 | 
            +
                      if activerecord_version_at_least('4.2.0')
         | 
| 104 | 
            +
                        @jd.join_constraints([]).should have(3).join_info
         | 
| 105 | 
            +
                        @jd.join_constraints([]).map(&:joins).flatten.each do |join|
         | 
| 106 | 
            +
                          join.class.should eq Squeel::InnerJoin
         | 
| 107 | 
            +
                        end
         | 
| 108 | 
            +
                        (children_people = @jd.join_root.children.first).aliased_table_name.should eq 'children_people'
         | 
| 109 | 
            +
                        (parents_people = children_people.children.first).aliased_table_name.should eq 'parents_people'
         | 
| 110 | 
            +
                        parents_people.children.first.aliased_table_name.should eq 'parents_people_2'
         | 
| 111 | 
            +
                      elsif activerecord_version_at_least('4.1.0')
         | 
| 112 | 
            +
                        @jd.join_constraints([]).should have(3).joins
         | 
| 113 | 
            +
                        @jd.join_constraints([]).each do |join|
         | 
| 114 | 
            +
                          join.class.should eq Squeel::InnerJoin
         | 
| 115 | 
            +
                        end
         | 
| 116 | 
            +
                        (children_people = @jd.join_root.children.first).aliased_table_name.should eq 'children_people'
         | 
| 117 | 
            +
                        (parents_people = children_people.children.first).aliased_table_name.should eq 'parents_people'
         | 
| 118 | 
            +
                        parents_people.children.first.aliased_table_name.should eq 'parents_people_2'
         | 
| 119 | 
            +
                      else
         | 
| 120 | 
            +
                        @jd.join_associations.should have(3).associations
         | 
| 121 | 
            +
                        @jd.join_associations.each do |association|
         | 
| 122 | 
            +
                          association.join_type.should eq Squeel::InnerJoin
         | 
| 123 | 
            +
                        end
         | 
| 124 | 
            +
                        @jd.join_associations[0].aliased_table_name.should eq 'children_people'
         | 
| 125 | 
            +
                        @jd.join_associations[1].aliased_table_name.should eq 'parents_people'
         | 
| 126 | 
            +
                        @jd.join_associations[2].aliased_table_name.should eq 'parents_people_2'
         | 
| 51 127 | 
             
                      end
         | 
| 52 | 
            -
                      @jd.join_associations[0].aliased_table_name.should eq 'children_people'
         | 
| 53 | 
            -
                      @jd.join_associations[1].aliased_table_name.should eq 'parents_people'
         | 
| 54 | 
            -
                      @jd.join_associations[2].aliased_table_name.should eq 'parents_people_2'
         | 
| 55 128 | 
             
                    end
         | 
| 56 129 |  | 
| 57 130 | 
             
                    it 'joins using outer joins' do
         | 
| 58 | 
            -
                      @jd | 
| 59 | 
            -
             | 
| 60 | 
            -
                       | 
| 61 | 
            -
                         | 
| 131 | 
            +
                      @jd = new_join_dependency(Person, { :articles.outer => :comments.outer }, [])
         | 
| 132 | 
            +
             | 
| 133 | 
            +
                      if activerecord_version_at_least('4.2.0')
         | 
| 134 | 
            +
                        @jd.join_constraints([]).should have(2).join_info
         | 
| 135 | 
            +
                        @jd.join_constraints([]).map(&:joins).flatten.each do |join|
         | 
| 136 | 
            +
                          join.class.should eq Squeel::OuterJoin
         | 
| 137 | 
            +
                        end
         | 
| 138 | 
            +
                      elsif activerecord_version_at_least('4.1.0')
         | 
| 139 | 
            +
                        @jd.join_constraints([]).should have(2).joins
         | 
| 140 | 
            +
                        @jd.join_constraints([]).each do |join|
         | 
| 141 | 
            +
                          join.class.should eq Squeel::OuterJoin
         | 
| 142 | 
            +
                        end
         | 
| 143 | 
            +
                      else
         | 
| 144 | 
            +
                        @jd.join_associations.should have(2).associations
         | 
| 145 | 
            +
                        @jd.join_associations.each do |association|
         | 
| 146 | 
            +
                          association.join_type.should eq Squeel::OuterJoin
         | 
| 147 | 
            +
                        end
         | 
| 62 148 | 
             
                      end
         | 
| 63 149 | 
             
                    end
         | 
| 64 | 
            -
             | 
| 65 150 | 
             
                  end
         | 
| 66 151 | 
             
                end
         | 
| 67 152 | 
             
              end
         | 
| 68 | 
            -
            end
         | 
| 153 | 
            +
            end
         | 
| @@ -15,8 +15,21 @@ module Squeel | |
| 15 15 | 
             
                        queries = queries_for do
         | 
| 16 16 | 
             
                          Person.find_by_id('')
         | 
| 17 17 | 
             
                        end
         | 
| 18 | 
            -
                         | 
| 19 | 
            -
             | 
| 18 | 
            +
                        if activerecord_version_at_least('3.1.0')
         | 
| 19 | 
            +
                          queries.should have(1).query
         | 
| 20 | 
            +
                        else
         | 
| 21 | 
            +
                          puts 'skips count of queries expectation'
         | 
| 22 | 
            +
                        end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                        if activerecord_version_at_least('4.2.0')
         | 
| 25 | 
            +
                          if PG_ENV
         | 
| 26 | 
            +
                            queries.last.should match /#{Q}people#{Q}.#{Q}id#{Q} = \$1/
         | 
| 27 | 
            +
                          else
         | 
| 28 | 
            +
                            queries.last.should match /#{Q}people#{Q}.#{Q}id#{Q} = ?/
         | 
| 29 | 
            +
                          end
         | 
| 30 | 
            +
                        else
         | 
| 31 | 
            +
                          queries.last.should match /#{Q}people#{Q}.#{Q}id#{Q} = 0/
         | 
| 32 | 
            +
                        end
         | 
| 20 33 | 
             
                      end
         | 
| 21 34 |  | 
| 22 35 | 
             
                    end
         | 
| @@ -34,8 +47,12 @@ module Squeel | |
| 34 47 |  | 
| 35 48 | 
             
                        arel = relation.build_arel
         | 
| 36 49 |  | 
| 37 | 
            -
                         | 
| 38 | 
            -
             | 
| 50 | 
            +
                        if activerecord_version_at_least('4.1.0')
         | 
| 51 | 
            +
                          relation.join_dependency.join_constraints([]).should have(4).items
         | 
| 52 | 
            +
                        else
         | 
| 53 | 
            +
                          relation.join_dependency.join_associations.should have(4).items
         | 
| 54 | 
            +
                        end
         | 
| 55 | 
            +
                        arel.to_sql.should match /INNER JOIN #{Q}people#{Q} #{Q}parents_people_2#{Q} ON #{Q}parents_people_2#{Q}.#{Q}id#{Q} = #{Q}parents_people#{Q}.#{Q}parent_id#{Q}/
         | 
| 39 56 | 
             
                      end
         | 
| 40 57 |  | 
| 41 58 | 
             
                      it 'joins associations with custom join types' do
         | 
| @@ -49,9 +66,13 @@ module Squeel | |
| 49 66 |  | 
| 50 67 | 
             
                        arel = relation.build_arel
         | 
| 51 68 |  | 
| 52 | 
            -
                         | 
| 53 | 
            -
             | 
| 54 | 
            -
                         | 
| 69 | 
            +
                        if activerecord_version_at_least('4.1.0')
         | 
| 70 | 
            +
                          relation.join_dependency.join_constraints([]).should have(4).items
         | 
| 71 | 
            +
                        else
         | 
| 72 | 
            +
                          relation.join_dependency.join_associations.should have(4).items
         | 
| 73 | 
            +
                        end
         | 
| 74 | 
            +
                        arel.to_sql.should match /LEFT OUTER JOIN #{Q}people#{Q} #{Q}children_people#{Q}/
         | 
| 75 | 
            +
                        arel.to_sql.should match /LEFT OUTER JOIN #{Q}people#{Q} #{Q}parents_people_2#{Q} ON #{Q}parents_people_2#{Q}.#{Q}id#{Q} = #{Q}parents_people#{Q}.#{Q}parent_id#{Q}/
         | 
| 55 76 | 
             
                      end
         | 
| 56 77 |  | 
| 57 78 | 
             
                      it 'only joins an association once, even if two overlapping joins_values hashes are given' do
         | 
| @@ -70,8 +91,12 @@ module Squeel | |
| 70 91 | 
             
                        })
         | 
| 71 92 |  | 
| 72 93 | 
             
                        arel = relation.build_arel
         | 
| 73 | 
            -
                         | 
| 74 | 
            -
             | 
| 94 | 
            +
                        if activerecord_version_at_least('4.1.0')
         | 
| 95 | 
            +
                          relation.join_dependency.join_constraints([]).should have(6).items
         | 
| 96 | 
            +
                        else
         | 
| 97 | 
            +
                          relation.join_dependency.join_associations.should have(6).items
         | 
| 98 | 
            +
                        end
         | 
| 99 | 
            +
                        arel.to_sql.should match /INNER JOIN #{Q}people#{Q} #{Q}parents_people_3#{Q} ON #{Q}parents_people_3#{Q}.#{Q}id#{Q} = #{Q}children_people_3#{Q}.#{Q}parent_id#{Q}/
         | 
| 75 100 | 
             
                      end
         | 
| 76 101 |  | 
| 77 102 | 
             
                      it 'respects :uniq option on associations' do
         | 
| @@ -81,15 +106,15 @@ module Squeel | |
| 81 106 | 
             
                      it 'visits wheres with a PredicateVisitor, converting them to Arel nodes' do
         | 
| 82 107 | 
             
                        relation = Person.where(:name.matches => '%bob%')
         | 
| 83 108 | 
             
                        arel = relation.build_arel
         | 
| 84 | 
            -
                        arel.to_sql.should match  | 
| 109 | 
            +
                        arel.to_sql.should match /#{Q}people#{Q}.#{Q}name#{Q} [I]*LIKE '%bob%'/
         | 
| 85 110 | 
             
                      end
         | 
| 86 111 |  | 
| 87 | 
            -
             | 
| 88 | 
            -
             | 
| 89 | 
            -
             | 
| 90 | 
            -
             | 
| 91 | 
            -
             | 
| 92 | 
            -
             | 
| 112 | 
            +
                      it 'handles multiple wheres using a keypath' do
         | 
| 113 | 
            +
                         relation = Person.joins{articles}.where{articles.title == 'Hello'}.
         | 
| 114 | 
            +
                                           where{articles.body == 'World'}
         | 
| 115 | 
            +
                         arel = relation.build_arel
         | 
| 116 | 
            +
                         arel.to_sql.should match /articles/
         | 
| 117 | 
            +
                      end
         | 
| 93 118 |  | 
| 94 119 | 
             
                      it 'maps wheres inside a hash to their appropriate association table' do
         | 
| 95 120 | 
             
                        relation = Person.joins({
         | 
| @@ -109,15 +134,14 @@ module Squeel | |
| 109 134 | 
             
                        })
         | 
| 110 135 |  | 
| 111 136 | 
             
                        arel = relation.build_arel
         | 
| 112 | 
            -
             | 
| 113 | 
            -
                        arel.to_sql.should match /"parents_people_2"."name" = 'bob'/
         | 
| 137 | 
            +
                        arel.to_sql.should match /#{Q}parents_people_2#{Q}.#{Q}name#{Q} = 'bob'/
         | 
| 114 138 | 
             
                      end
         | 
| 115 139 |  | 
| 116 140 | 
             
                      it 'combines multiple conditions of the same type against the same column with AND' do
         | 
| 117 141 | 
             
                        relation = Person.where(:name.matches => '%bob%')
         | 
| 118 142 | 
             
                        relation = relation.where(:name.matches => '%joe%')
         | 
| 119 143 | 
             
                        arel = relation.build_arel
         | 
| 120 | 
            -
                        arel.to_sql.should match  | 
| 144 | 
            +
                        arel.to_sql.should match /#{Q}people#{Q}.#{Q}name#{Q} [I]*LIKE '%bob%' AND #{Q}people#{Q}.#{Q}name#{Q} [I]*LIKE '%joe%'/
         | 
| 121 145 | 
             
                      end
         | 
| 122 146 |  | 
| 123 147 | 
             
                      it 'handles ORs between predicates' do
         | 
| @@ -129,7 +153,7 @@ module Squeel | |
| 129 153 | 
             
                      it 'maintains groupings as given' do
         | 
| 130 154 | 
             
                        relation = Person.where(dsl{(name == 'Ernie') | ((name =~ 'Bob%') & (name =~ '%by'))})
         | 
| 131 155 | 
             
                        arel = relation.build_arel
         | 
| 132 | 
            -
                        arel.to_sql.should match  | 
| 156 | 
            +
                        arel.to_sql.should match /#{Q}people#{Q}.#{Q}name#{Q} = 'Ernie' OR \(#{Q}people#{Q}.#{Q}name#{Q} [I]*LIKE 'Bob%' AND #{Q}people#{Q}.#{Q}name#{Q} [I]*LIKE '%by'\)/
         | 
| 133 157 | 
             
                      end
         | 
| 134 158 |  | 
| 135 159 | 
             
                      it 'maps havings inside a hash to their appropriate association table' do
         | 
| @@ -150,8 +174,7 @@ module Squeel | |
| 150 174 | 
             
                        })
         | 
| 151 175 |  | 
| 152 176 | 
             
                        arel = relation.build_arel
         | 
| 153 | 
            -
             | 
| 154 | 
            -
                        arel.to_sql.should match /HAVING "parents_people_2"."name" = 'joe'/
         | 
| 177 | 
            +
                        arel.to_sql.should match /HAVING #{Q}parents_people_2#{Q}.#{Q}name#{Q} = 'joe'/
         | 
| 155 178 | 
             
                      end
         | 
| 156 179 |  | 
| 157 180 | 
             
                      it 'maps orders inside a hash to their appropriate association table' do
         | 
| @@ -173,8 +196,7 @@ module Squeel | |
| 173 196 | 
             
                          })
         | 
| 174 197 |  | 
| 175 198 | 
             
                          arel = relation.build_arel
         | 
| 176 | 
            -
             | 
| 177 | 
            -
                          arel.to_sql.should match /ORDER BY "parents_people_2"."id" ASC/
         | 
| 199 | 
            +
                          arel.to_sql.should match /ORDER BY #{Q}parents_people_2#{Q}.#{Q}id#{Q} ASC/
         | 
| 178 200 | 
             
                        else
         | 
| 179 201 | 
             
                          pending 'Unsupported in ActiveRecord 4.0.0+'
         | 
| 180 202 | 
             
                        end
         | 
| @@ -191,7 +213,6 @@ module Squeel | |
| 191 213 |  | 
| 192 214 | 
             
                      it 'reverses order of Arel::Attributes when #last is called' do
         | 
| 193 215 | 
             
                        sorted_people = Person.all.to_a.sort {|a, b| a.name.downcase <=> b.name.downcase}
         | 
| 194 | 
            -
             | 
| 195 216 | 
             
                        Person.order{name}.last.should eq sorted_people.last
         | 
| 196 217 | 
             
                      end
         | 
| 197 218 |  | 
| @@ -245,46 +266,77 @@ module Squeel | |
| 245 266 |  | 
| 246 267 | 
             
                      it 'eager loads belongs_to associations' do
         | 
| 247 268 | 
             
                        queries = queries_for do
         | 
| 248 | 
            -
                           | 
| 249 | 
            -
             | 
| 269 | 
            +
                          if activerecord_version_at_least('4.1.0')
         | 
| 270 | 
            +
                            Article.includes(:person).references(:person).
         | 
| 271 | 
            +
                                    where{person.name == 'Ernie'}.to_a
         | 
| 272 | 
            +
                          else
         | 
| 273 | 
            +
                            Article.includes(:person).
         | 
| 274 | 
            +
                                    where{person.name == 'Ernie'}.to_a
         | 
| 275 | 
            +
                          end
         | 
| 250 276 | 
             
                        end
         | 
| 251 | 
            -
             | 
| 252 | 
            -
                         | 
| 253 | 
            -
             | 
| 277 | 
            +
             | 
| 278 | 
            +
                        if activerecord_version_at_least('4.1.0')
         | 
| 279 | 
            +
                          queries.should have(1).item
         | 
| 280 | 
            +
                        else
         | 
| 281 | 
            +
                          puts 'skips count of queries expectation.'
         | 
| 282 | 
            +
                        end
         | 
| 283 | 
            +
             | 
| 284 | 
            +
                        queries.last.should match /LEFT OUTER JOIN #{Q}people#{Q}/
         | 
| 285 | 
            +
                        queries.last.should match /#{Q}people#{Q}.#{Q}name#{Q} = 'Ernie'/
         | 
| 254 286 | 
             
                      end
         | 
| 255 287 |  | 
| 256 288 | 
             
                      it 'eager loads belongs_to associations on models with default_scopes' do
         | 
| 257 289 | 
             
                        queries = queries_for do
         | 
| 258 | 
            -
                           | 
| 259 | 
            -
             | 
| 290 | 
            +
                          if activerecord_version_at_least('4.1.0')
         | 
| 291 | 
            +
                            PersonNamedBill.includes(:parent).references(:parent).
         | 
| 292 | 
            +
                                            where{parent.name == 'Ernie'}.to_a
         | 
| 293 | 
            +
                          else
         | 
| 294 | 
            +
                            PersonNamedBill.includes(:parent).
         | 
| 295 | 
            +
                                            where{parent.name == 'Ernie'}.to_a
         | 
| 296 | 
            +
                          end
         | 
| 297 | 
            +
             | 
| 298 | 
            +
                        end
         | 
| 299 | 
            +
             | 
| 300 | 
            +
                        if activerecord_version_at_least('4.1.0')
         | 
| 301 | 
            +
                          queries.should have(1).item
         | 
| 302 | 
            +
                        else
         | 
| 303 | 
            +
                          puts 'skips count of queries expectation.'
         | 
| 260 304 | 
             
                        end
         | 
| 261 | 
            -
             | 
| 262 | 
            -
                        queries. | 
| 263 | 
            -
                        queries. | 
| 264 | 
            -
                        queries. | 
| 305 | 
            +
             | 
| 306 | 
            +
                        queries.last.should match /LEFT OUTER JOIN #{Q}people#{Q}/
         | 
| 307 | 
            +
                        queries.last.should match /#{Q}people#{Q}.#{Q}name#{Q} = 'Bill'/
         | 
| 308 | 
            +
                        queries.last.should match /#{Q}parents_people#{Q}.#{Q}name#{Q} = 'Ernie'/
         | 
| 265 309 | 
             
                      end
         | 
| 266 310 |  | 
| 267 311 | 
             
                      it 'eager loads polymorphic belongs_to associations' do
         | 
| 268 312 | 
             
                        relation = Note.includes{notable(Article)}.where{{notable(Article) => {title => 'hey'}}}
         | 
| 269 | 
            -
                        relation.debug_sql.should match  | 
| 313 | 
            +
                        relation.debug_sql.should match /#{Q}notes#{Q}.#{Q}notable_type#{Q} = 'Article'/
         | 
| 270 314 | 
             
                      end
         | 
| 271 315 |  | 
| 272 316 | 
             
                      it 'eager loads multiple polymorphic belongs_to associations' do
         | 
| 273 317 | 
             
                        relation = Note.includes{[notable(Article), notable(Person)]}.
         | 
| 274 318 | 
             
                                        where{{notable(Article) => {title => 'hey'}}}.
         | 
| 275 319 | 
             
                                        where{{notable(Person) => {name => 'joe'}}}
         | 
| 276 | 
            -
                        relation.debug_sql.should match  | 
| 277 | 
            -
                        relation.debug_sql.should match  | 
| 320 | 
            +
                        relation.debug_sql.should match /#{Q}notes#{Q}.#{Q}notable_type#{Q} = 'Article'/
         | 
| 321 | 
            +
                        relation.debug_sql.should match /#{Q}notes#{Q}.#{Q}notable_type#{Q} = 'Person'/
         | 
| 278 322 | 
             
                      end
         | 
| 279 323 |  | 
| 280 | 
            -
                      it  | 
| 324 | 
            +
                      it 'only includes once, even if two join types are used' do
         | 
| 281 325 | 
             
                        relation = Person.includes(:articles.inner, :articles.outer).where(:articles => {:title => 'hey'})
         | 
| 282 | 
            -
                         | 
| 326 | 
            +
                        if activerecord_version_at_least('4.1.0')
         | 
| 327 | 
            +
                          pending ":article != :article.inner != :article.outer, you shouldn't pass two same tables into includes again"
         | 
| 328 | 
            +
                        else
         | 
| 329 | 
            +
                          relation.debug_sql.scan("JOIN").size.should eq 1
         | 
| 330 | 
            +
                        end
         | 
| 283 331 | 
             
                      end
         | 
| 284 332 |  | 
| 285 333 | 
             
                      it 'includes a keypath' do
         | 
| 286 | 
            -
                         | 
| 287 | 
            -
             | 
| 334 | 
            +
                        if activerecord_version_at_least('4.1.0')
         | 
| 335 | 
            +
                          relation = Note.includes{notable(Article).person.children}.references(:all).where{notable(Article).person.children.name == 'Ernie'}
         | 
| 336 | 
            +
                        else
         | 
| 337 | 
            +
                          relation = Note.includes{notable(Article).person.children}.where{notable(Article).person.children.name == 'Ernie'}
         | 
| 338 | 
            +
                        end
         | 
| 339 | 
            +
                        relation.debug_sql.should match /SELECT #{Q}notes#{Q}.* FROM #{Q}notes#{Q} LEFT OUTER JOIN #{Q}articles#{Q} ON #{Q}articles#{Q}.#{Q}id#{Q} = #{Q}notes#{Q}.#{Q}notable_id#{Q} AND #{Q}notes#{Q}.#{Q}notable_type#{Q} = 'Article' LEFT OUTER JOIN #{Q}people#{Q} ON #{Q}people#{Q}.#{Q}id#{Q} = #{Q}articles#{Q}.#{Q}person_id#{Q} LEFT OUTER JOIN #{Q}people#{Q} #{Q}children_people#{Q} ON #{Q}children_people#{Q}.#{Q}parent_id#{Q} = #{Q}people#{Q}.#{Q}id#{Q} WHERE #{Q}children_people#{Q}.#{Q}name#{Q} = 'Ernie'/
         | 
| 288 340 | 
             
                      end
         | 
| 289 341 |  | 
| 290 342 | 
             
                    end
         | 
| @@ -311,7 +363,6 @@ module Squeel | |
| 311 363 | 
             
                        }}
         | 
| 312 364 |  | 
| 313 365 | 
             
                        queries_for {relation.to_a}.should have(4).items
         | 
| 314 | 
            -
             | 
| 315 366 | 
             
                        queries_for {
         | 
| 316 367 | 
             
                          relation.first.articles
         | 
| 317 368 | 
             
                          relation.first.articles.first.comments
         | 
| @@ -327,8 +378,12 @@ module Squeel | |
| 327 378 | 
             
                        standard = Person.eager_load(:children => :children)
         | 
| 328 379 | 
             
                        block = Person.eager_load{{children => children}}
         | 
| 329 380 | 
             
                        block.debug_sql.should eq standard.debug_sql
         | 
| 330 | 
            -
                         | 
| 331 | 
            -
             | 
| 381 | 
            +
                        if activerecord_version_at_least('3.2.0')
         | 
| 382 | 
            +
                          queries_for {block.to_a}.should have(1).item
         | 
| 383 | 
            +
                          queries_for {block.first.children}.should have(0).items
         | 
| 384 | 
            +
                        else
         | 
| 385 | 
            +
                          puts 'skips count of queries expectation.'
         | 
| 386 | 
            +
                        end
         | 
| 332 387 | 
             
                      end
         | 
| 333 388 |  | 
| 334 389 | 
             
                      it 'eager loads multiple top-level associations with a block' do
         | 
| @@ -339,23 +394,27 @@ module Squeel | |
| 339 394 |  | 
| 340 395 | 
             
                      it 'eager loads polymorphic belongs_to associations' do
         | 
| 341 396 | 
             
                        relation = Note.eager_load{notable(Article)}
         | 
| 342 | 
            -
                        relation.debug_sql.should match  | 
| 397 | 
            +
                        relation.debug_sql.should match /#{Q}notes#{Q}.#{Q}notable_type#{Q} = 'Article'/
         | 
| 343 398 | 
             
                      end
         | 
| 344 399 |  | 
| 345 400 | 
             
                      it 'eager loads multiple polymorphic belongs_to associations' do
         | 
| 346 401 | 
             
                        relation = Note.eager_load{[notable(Article), notable(Person)]}
         | 
| 347 | 
            -
                        relation.debug_sql.should match  | 
| 348 | 
            -
                        relation.debug_sql.should match  | 
| 402 | 
            +
                        relation.debug_sql.should match /#{Q}notes#{Q}.#{Q}notable_type#{Q} = 'Article'/
         | 
| 403 | 
            +
                        relation.debug_sql.should match /#{Q}notes#{Q}.#{Q}notable_type#{Q} = 'Person'/
         | 
| 349 404 | 
             
                      end
         | 
| 350 405 |  | 
| 351 406 | 
             
                      it "only eager_load once, even if two join types are used" do
         | 
| 352 407 | 
             
                        relation = Person.eager_load(:articles.inner, :articles.outer)
         | 
| 353 | 
            -
                         | 
| 408 | 
            +
                        if activerecord_version_at_least('4.1.0')
         | 
| 409 | 
            +
                          pending ":article != :article.inner != :article.outer, you shouldn't pass two same tables into eager_load again"
         | 
| 410 | 
            +
                        else
         | 
| 411 | 
            +
                          relation.debug_sql.scan("JOIN").size.should eq 1
         | 
| 412 | 
            +
                        end
         | 
| 354 413 | 
             
                      end
         | 
| 355 414 |  | 
| 356 415 | 
             
                      it 'eager_load a keypath' do
         | 
| 357 416 | 
             
                        relation = Note.eager_load{notable(Article).person.children}
         | 
| 358 | 
            -
                        relation.debug_sql.should match /SELECT  | 
| 417 | 
            +
                        relation.debug_sql.should match /SELECT #{Q}notes#{Q}.* FROM #{Q}notes#{Q} LEFT OUTER JOIN #{Q}articles#{Q} ON #{Q}articles#{Q}.#{Q}id#{Q} = #{Q}notes#{Q}.#{Q}notable_id#{Q} AND #{Q}notes#{Q}.#{Q}notable_type#{Q} = 'Article' LEFT OUTER JOIN #{Q}people#{Q} ON #{Q}people#{Q}.#{Q}id#{Q} = #{Q}articles#{Q}.#{Q}person_id#{Q} LEFT OUTER JOIN #{Q}people#{Q} #{Q}children_people#{Q} ON #{Q}children_people#{Q}.#{Q}parent_id#{Q} = #{Q}people#{Q}.#{Q}id#{Q}/
         | 
| 359 418 | 
             
                      end
         | 
| 360 419 |  | 
| 361 420 | 
             
                    end
         | 
| @@ -385,39 +444,52 @@ module Squeel | |
| 385 444 |  | 
| 386 445 | 
             
                      it 'behaves as normal with standard parameters' do
         | 
| 387 446 | 
             
                        people = Person.select(:id)
         | 
| 388 | 
            -
                        people.should have( | 
| 389 | 
            -
                         | 
| 447 | 
            +
                        people.should have(10).people
         | 
| 448 | 
            +
                        if ::ActiveRecord::VERSION::MAJOR == 3 && ::ActiveRecord::VERSION::MINOR == 0 && RUBY_VERSION >= '2.0.0'
         | 
| 449 | 
            +
                          people.first.name.should be_nil
         | 
| 450 | 
            +
                        else
         | 
| 451 | 
            +
                          expect { people.first.name }.to raise_error ActiveModel::MissingAttributeError
         | 
| 452 | 
            +
                        end
         | 
| 390 453 | 
             
                      end
         | 
| 391 454 |  | 
| 392 455 | 
             
                      it 'works with multiple fields in select' do
         | 
| 393 | 
            -
                        Article.select("title, body"). | 
| 456 | 
            +
                        Article.select("title, body").size.should eq 31
         | 
| 394 457 | 
             
                      end
         | 
| 395 458 |  | 
| 396 459 | 
             
                      it 'allows a function in the select values via Symbol#func' do
         | 
| 397 | 
            -
                        relation = Person.select(:max.func(:id).as('max_id'))
         | 
| 398 | 
            -
                        relation.first.max_id.should eq  | 
| 460 | 
            +
                        relation = Person.select(:max.func(:id).as('max_id')).order('max_id')
         | 
| 461 | 
            +
                        relation.first.max_id.to_i.should eq 10
         | 
| 399 462 | 
             
                      end
         | 
| 400 463 |  | 
| 401 464 | 
             
                      it 'allows a function in the select values via block' do
         | 
| 402 | 
            -
                        relation = Person.select{max(id).as(max_id)}
         | 
| 403 | 
            -
                        relation.first.max_id.should eq  | 
| 465 | 
            +
                        relation = Person.select{max(id).as(max_id)}.order('max_id')
         | 
| 466 | 
            +
                        relation.first.max_id.to_i.should eq 10
         | 
| 404 467 | 
             
                      end
         | 
| 405 468 |  | 
| 406 469 | 
             
                      it 'allows an operation in the select values via block' do
         | 
| 407 | 
            -
                        relation = | 
| 408 | 
            -
             | 
| 470 | 
            +
                        relation =
         | 
| 471 | 
            +
                          if SQLITE_ENV
         | 
| 472 | 
            +
                            Person.select{[id, (id + 1).as('id_plus_one')]}.where('id_plus_one = 2')
         | 
| 473 | 
            +
                          else
         | 
| 474 | 
            +
                            Person.select{[id, (id + 1).as('id_plus_one')]}.where{(id + 1) == 2}
         | 
| 475 | 
            +
                          end
         | 
| 476 | 
            +
                          relation.first.id.should eq 1
         | 
| 409 477 | 
             
                      end
         | 
| 410 478 |  | 
| 411 479 | 
             
                      it 'allows custom operators in the select values via block' do
         | 
| 412 | 
            -
                         | 
| 413 | 
            -
             | 
| 480 | 
            +
                        if MYSQL_ENV
         | 
| 481 | 
            +
                          pending "MySQL doesn't support concating string with ||."
         | 
| 482 | 
            +
                        else
         | 
| 483 | 
            +
                          relation = Person.select{name.op('||', '-diddly').as(flanderized_name)}
         | 
| 484 | 
            +
                          relation.first.flanderized_name.should eq Person.first.name + '-diddly'
         | 
| 485 | 
            +
                        end
         | 
| 414 486 | 
             
                      end
         | 
| 415 487 |  | 
| 416 488 | 
             
                      it 'allows a subquery in the select values' do
         | 
| 417 489 | 
             
                        subquery = Article.where(:person_id => 1).select(:id).order{id.desc}.limit(1)
         | 
| 418 490 | 
             
                        relation = Person.where(:id => 1).select{[id, name, subquery.as('last_article_id')]}
         | 
| 419 491 | 
             
                        aric = relation.first
         | 
| 420 | 
            -
                        aric.last_article_id.should eq Article.where(:person_id => 1).last.id
         | 
| 492 | 
            +
                        aric.last_article_id.to_i.should eq Article.where(:person_id => 1).last.id
         | 
| 421 493 | 
             
                      end
         | 
| 422 494 |  | 
| 423 495 | 
             
                    end
         | 
| @@ -425,7 +497,7 @@ module Squeel | |
| 425 497 | 
             
                    describe '#count' do
         | 
| 426 498 |  | 
| 427 499 | 
             
                      it 'works with non-strings in select' do
         | 
| 428 | 
            -
                        Article.select{distinct(title)}.count.should eq  | 
| 500 | 
            +
                        Article.select{distinct(title)}.count.should eq 31
         | 
| 429 501 | 
             
                      end
         | 
| 430 502 |  | 
| 431 503 | 
             
                      it 'works with non-strings in wheres' do
         | 
| @@ -463,17 +535,17 @@ module Squeel | |
| 463 535 |  | 
| 464 536 | 
             
                      it 'builds compound conditions with a block' do
         | 
| 465 537 | 
             
                        block = Person.where{(name == 'bob') & (salary == 100000)}
         | 
| 466 | 
            -
                        block.to_sql.should match  | 
| 538 | 
            +
                        block.to_sql.should match /#{Q}people#{Q}.#{Q}name#{Q} = 'bob'/
         | 
| 467 539 | 
             
                        block.to_sql.should match /AND/
         | 
| 468 | 
            -
                        block.to_sql.should match  | 
| 540 | 
            +
                        block.to_sql.should match /#{Q}people#{Q}.#{Q}salary#{Q} = 100000/
         | 
| 469 541 | 
             
                      end
         | 
| 470 542 |  | 
| 471 543 | 
             
                      it 'allows mixing hash and operator syntax inside a block' do
         | 
| 472 544 | 
             
                        block = Person.joins(:comments).
         | 
| 473 545 | 
             
                                       where{(name == 'bob') & {comments => (body == 'First post!')}}
         | 
| 474 | 
            -
                        block.to_sql.should match  | 
| 546 | 
            +
                        block.to_sql.should match /#{Q}people#{Q}.#{Q}name#{Q} = 'bob'/
         | 
| 475 547 | 
             
                        block.to_sql.should match /AND/
         | 
| 476 | 
            -
                        block.to_sql.should match  | 
| 548 | 
            +
                        block.to_sql.should match /#{Q}comments#{Q}.#{Q}body#{Q} = 'First post!'/
         | 
| 477 549 | 
             
                      end
         | 
| 478 550 |  | 
| 479 551 | 
             
                      it 'allows a condition on a function via block' do
         | 
| @@ -496,6 +568,12 @@ module Squeel | |
| 496 568 | 
             
                        people_and_article_notes.should have(40).items
         | 
| 497 569 | 
             
                      end
         | 
| 498 570 |  | 
| 571 | 
            +
                      it 'maps conditions onto their proper table with a polymorphic belongs_to join followed by a polymorphic has_many join' do
         | 
| 572 | 
            +
                        relation = Note.joins{notable(Article).notes}.
         | 
| 573 | 
            +
                          where{notable(Article).notes.note.eq('zomg')}
         | 
| 574 | 
            +
                        relation.to_sql.should match /#{Q}notes_articles#{Q}\.#{Q}note#{Q} = 'zomg'/
         | 
| 575 | 
            +
                      end
         | 
| 576 | 
            +
             | 
| 499 577 | 
             
                      it 'allows a subquery on the value side of a predicate' do
         | 
| 500 578 | 
             
                        names = [Person.first.name, Person.last.name]
         | 
| 501 579 | 
             
                        old_and_busted = Person.where(:name => names)
         | 
| @@ -504,6 +582,21 @@ module Squeel | |
| 504 582 | 
             
                        old_and_busted.to_a.should eq new_hotness.to_a
         | 
| 505 583 | 
             
                      end
         | 
| 506 584 |  | 
| 585 | 
            +
                      it 'allows a subquery from an association in a hash' do
         | 
| 586 | 
            +
                        scope = Person.first.articles
         | 
| 587 | 
            +
                        articles = scope.where(:id => scope)
         | 
| 588 | 
            +
                        articles.should have(3).articles
         | 
| 589 | 
            +
             | 
| 590 | 
            +
                        articles = Tag.all.second.articles.where(:id => scope)
         | 
| 591 | 
            +
                        articles.should have(1).articles
         | 
| 592 | 
            +
                      end
         | 
| 593 | 
            +
             | 
| 594 | 
            +
                      it 'allows a subquery from an association in a Squeel node' do
         | 
| 595 | 
            +
                        scope = Person.first.articles
         | 
| 596 | 
            +
                        articles = scope.where{id.in scope}
         | 
| 597 | 
            +
                        articles.should have(3).articles
         | 
| 598 | 
            +
                      end
         | 
| 599 | 
            +
             | 
| 507 600 | 
             
                      it 'is backwards-compatible with "where.not"' do
         | 
| 508 601 | 
             
                        if activerecord_version_at_least '4.0.0'
         | 
| 509 602 | 
             
                          name = Person.first.name
         | 
| @@ -517,37 +610,61 @@ module Squeel | |
| 517 610 | 
             
                      it 'allows equality conditions against a belongs_to with an AR::Base value' do
         | 
| 518 611 | 
             
                        first_person = Person.first
         | 
| 519 612 | 
             
                        relation = Article.where { person.eq first_person }
         | 
| 520 | 
            -
                        relation.to_sql.should match  | 
| 613 | 
            +
                        relation.to_sql.should match /#{Q}articles#{Q}.#{Q}person_id#{Q} = #{first_person.id}/
         | 
| 521 614 | 
             
                      end
         | 
| 522 615 |  | 
| 523 616 | 
             
                      it 'allows equality conditions against a polymorphic belongs_to with an AR::Base value' do
         | 
| 524 617 | 
             
                        first_person = Person.first
         | 
| 525 618 | 
             
                        relation = Note.where { notable.eq first_person }
         | 
| 526 | 
            -
                        relation.to_sql.should match  | 
| 619 | 
            +
                        relation.to_sql.should match /#{Q}notes#{Q}.#{Q}notable_id#{Q} = #{first_person.id} AND #{Q}notes#{Q}.#{Q}notable_type#{Q} = 'Person'/
         | 
| 527 620 | 
             
                      end
         | 
| 528 621 |  | 
| 529 622 | 
             
                      it 'allows inequality conditions against a belongs_to with an AR::Base value' do
         | 
| 530 623 | 
             
                        first_person = Person.first
         | 
| 531 624 | 
             
                        relation = Article.where { person.not_eq first_person }
         | 
| 532 | 
            -
                        relation.to_sql.should match  | 
| 625 | 
            +
                        relation.to_sql.should match /#{Q}articles#{Q}.#{Q}person_id#{Q} != #{first_person.id}/
         | 
| 533 626 | 
             
                      end
         | 
| 534 627 |  | 
| 535 628 | 
             
                      it 'allows inequality conditions against a polymorphic belongs_to with an AR::Base value' do
         | 
| 536 629 | 
             
                        first_person = Person.first
         | 
| 537 630 | 
             
                        relation = Note.where { notable.not_eq first_person }
         | 
| 538 | 
            -
                        relation.to_sql.should match /\( | 
| 631 | 
            +
                        relation.to_sql.should match /\(#{Q}notes#{Q}.#{Q}notable_id#{Q} != #{first_person.id} OR #{Q}notes#{Q}.#{Q}notable_type#{Q} != 'Person'\)/
         | 
| 539 632 | 
             
                      end
         | 
| 540 633 |  | 
| 541 634 | 
             
                      it 'allows hash equality conditions against a belongs_to with an AR::Base value' do
         | 
| 542 635 | 
             
                        first_person = Person.first
         | 
| 543 636 | 
             
                        relation = Article.where(:person => first_person)
         | 
| 544 | 
            -
                        relation.to_sql.should match  | 
| 637 | 
            +
                        relation.to_sql.should match /#{Q}articles#{Q}.#{Q}person_id#{Q} = #{first_person.id}/
         | 
| 545 638 | 
             
                      end
         | 
| 546 639 |  | 
| 547 640 | 
             
                      it 'allows hash equality conditions against a polymorphic belongs_to with an AR::Base value' do
         | 
| 548 641 | 
             
                        first_person = Person.first
         | 
| 549 642 | 
             
                        relation = Note.where(:notable => first_person)
         | 
| 550 | 
            -
                        relation.to_sql.should match  | 
| 643 | 
            +
                        relation.to_sql.should match /#{Q}notes#{Q}.#{Q}notable_type#{Q} = 'Person'/
         | 
| 644 | 
            +
                        relation.to_sql.should match /#{Q}notes#{Q}.#{Q}notable_id#{Q} = #{first_person.id}/
         | 
| 645 | 
            +
                      end
         | 
| 646 | 
            +
             | 
| 647 | 
            +
                      it 'keeps original AR hashes behavior' do
         | 
| 648 | 
            +
                        relation = Person.joins(:articles).where(articles: { person_id: Person.first })
         | 
| 649 | 
            +
                        relation.to_sql.should match /SELECT #{Q}people#{Q}.* FROM #{Q}people#{Q} INNER JOIN #{Q}articles#{Q} ON #{Q}articles#{Q}.#{Q}person_id#{Q} = #{Q}people#{Q}.#{Q}id#{Q} WHERE #{Q}articles#{Q}.#{Q}person_id#{Q} = 1/
         | 
| 650 | 
            +
             | 
| 651 | 
            +
                        relation = Person.joins(:articles).where(articles: { person_id: Person.all.to_a })
         | 
| 652 | 
            +
                        relation.to_sql.should match /SELECT #{Q}people#{Q}.\* FROM #{Q}people#{Q} INNER JOIN #{Q}articles#{Q} ON #{Q}articles#{Q}.#{Q}person_id#{Q} = #{Q}people#{Q}.#{Q}id#{Q} WHERE #{Q}articles#{Q}.#{Q}person_id#{Q} IN \(1, 2, 3, 4, 5, 6, 7, 8, 9, 10\)/
         | 
| 653 | 
            +
                      end
         | 
| 654 | 
            +
             | 
| 655 | 
            +
                      it 'returns ActiveRecord::Relation after complex associations, joins and wheres' do
         | 
| 656 | 
            +
                        relation = Note.first.notable.articles.joins(:comments).where{comments.article_id != nil}
         | 
| 657 | 
            +
             | 
| 658 | 
            +
                        relation.should be_kind_of(::ActiveRecord::Relation)
         | 
| 659 | 
            +
                        relation.first.should be_kind_of(Article)
         | 
| 660 | 
            +
                      end
         | 
| 661 | 
            +
             | 
| 662 | 
            +
                      it 'uses Squeel and Arel at the same time' do
         | 
| 663 | 
            +
                        relation = User.where{id.in([1,2,3]) & User.arel_table[:id].not_eq(nil) }
         | 
| 664 | 
            +
                        relation.to_sql.should match /SELECT #{Q}users#{Q}.\* FROM #{Q}users#{Q}\s+WHERE \(\(#{Q}users#{Q}.#{Q}id#{Q} IN \(1, 2, 3\) AND #{Q}users#{Q}.#{Q}id#{Q} IS NOT NULL\)\)/
         | 
| 665 | 
            +
                        relation = User.where{
         | 
| 666 | 
            +
                          (id.in([1,2,3]) | User.arel_table[:id].eq(1)) & ((id == 1) | User.arel_table[:id].not_eq(nil)) }
         | 
| 667 | 
            +
                        relation.to_sql.should match /SELECT #{Q}users#{Q}.\* FROM #{Q}users#{Q}\s+WHERE \(\(\(#{Q}users#{Q}.#{Q}id#{Q} IN \(1, 2, 3\) OR #{Q}users#{Q}.#{Q}id#{Q} = 1\) AND \(#{Q}users#{Q}.#{Q}id#{Q} = 1 OR #{Q}users#{Q}.#{Q}id#{Q} IS NOT NULL\)\)\)/
         | 
| 551 668 | 
             
                      end
         | 
| 552 669 |  | 
| 553 670 | 
             
                    end
         | 
| @@ -577,25 +694,66 @@ module Squeel | |
| 577 694 |  | 
| 578 695 | 
             
                      it 'joins polymorphic belongs_to associations' do
         | 
| 579 696 | 
             
                        relation = Note.joins{notable(Article)}
         | 
| 580 | 
            -
                        relation.to_sql.should match  | 
| 697 | 
            +
                        relation.to_sql.should match /#{Q}notes#{Q}.#{Q}notable_type#{Q} = 'Article'/
         | 
| 581 698 | 
             
                      end
         | 
| 582 699 |  | 
| 583 700 | 
             
                      it 'joins multiple polymorphic belongs_to associations' do
         | 
| 584 701 | 
             
                        relation = Note.joins{[notable(Article), notable(Person)]}
         | 
| 585 | 
            -
                        relation.to_sql.should match  | 
| 586 | 
            -
                        relation.to_sql.should match  | 
| 702 | 
            +
                        relation.to_sql.should match /#{Q}notes#{Q}.#{Q}notable_type#{Q} = 'Article'/
         | 
| 703 | 
            +
                        relation.to_sql.should match /#{Q}notes#{Q}.#{Q}notable_type#{Q} = 'Person'/
         | 
| 587 704 | 
             
                      end
         | 
| 588 705 |  | 
| 589 706 | 
             
                      it "only joins once, even if two join types are used" do
         | 
| 590 | 
            -
                         | 
| 591 | 
            -
             | 
| 707 | 
            +
                        if activerecord_version_at_least('4.1.0')
         | 
| 708 | 
            +
                          pending "It's unreasonable to join once only, in some cases, we need twice."
         | 
| 709 | 
            +
                        else
         | 
| 710 | 
            +
                          relation = Person.joins(:articles.inner, :articles.outer)
         | 
| 711 | 
            +
                          relation.to_sql.scan("JOIN").size.should eq 1
         | 
| 712 | 
            +
                        end
         | 
| 592 713 | 
             
                      end
         | 
| 593 714 |  | 
| 594 715 | 
             
                      it 'joins a keypath' do
         | 
| 595 716 | 
             
                        relation = Note.joins{notable(Article).person.children}
         | 
| 596 | 
            -
                        relation.to_sql.should match /SELECT  | 
| 717 | 
            +
                        relation.to_sql.should match /SELECT #{Q}notes#{Q}.* FROM #{Q}notes#{Q} INNER JOIN #{Q}articles#{Q} ON #{Q}articles#{Q}.#{Q}id#{Q} = #{Q}notes#{Q}.#{Q}notable_id#{Q} AND #{Q}notes#{Q}.#{Q}notable_type#{Q} = 'Article' INNER JOIN #{Q}people#{Q} ON #{Q}people#{Q}.#{Q}id#{Q} = #{Q}articles#{Q}.#{Q}person_id#{Q} INNER JOIN #{Q}people#{Q} #{Q}children_people#{Q} ON #{Q}children_people#{Q}.#{Q}parent_id#{Q} = #{Q}people#{Q}.#{Q}id#{Q}/
         | 
| 597 718 | 
             
                      end
         | 
| 598 719 |  | 
| 720 | 
            +
                      it 'validates polymorphic relationship with source type' do
         | 
| 721 | 
            +
                        if activerecord_version_at_least '3.2.7'
         | 
| 722 | 
            +
                          Group.first.users.to_sql.should match /#{Q}memberships#{Q}.#{Q}member_type#{Q} = 'User'/
         | 
| 723 | 
            +
                        else
         | 
| 724 | 
            +
                          Group.first.users.size.should eq 1
         | 
| 725 | 
            +
                        end
         | 
| 726 | 
            +
                      end
         | 
| 727 | 
            +
             | 
| 728 | 
            +
                      it 'joins an ActiveRecord::Relation subquery' do
         | 
| 729 | 
            +
                        subquery = OrderItem.
         | 
| 730 | 
            +
                          group(:orderable_id).
         | 
| 731 | 
            +
                          select { [orderable_id, sum(quantity * unit_price).as(amount)] }
         | 
| 732 | 
            +
             | 
| 733 | 
            +
                        relation = Seat.
         | 
| 734 | 
            +
                          joins { [payment.outer,
         | 
| 735 | 
            +
                                   subquery.as('seat_order_items').on { id == seat_order_items.orderable_id}.outer] }.
         | 
| 736 | 
            +
                          select { [seat_order_items.amount, "seats.*"] }.
         | 
| 737 | 
            +
                          where { seat_order_items.amount > 0 }
         | 
| 738 | 
            +
             | 
| 739 | 
            +
                        relation.debug_sql.should match /SELECT #{Q}seat_order_items#{Q}.#{Q}amount#{Q}, seats.\* FROM #{Q}seats#{Q} LEFT OUTER JOIN #{Q}payments#{Q} ON #{Q}payments#{Q}.#{Q}id#{Q} = #{Q}seats#{Q}.#{Q}payment_id#{Q} LEFT OUTER JOIN \(SELECT #{Q}order_items#{Q}.#{Q}orderable_id#{Q}, sum\(#{Q}order_items#{Q}.#{Q}quantity#{Q} \* #{Q}order_items#{Q}.#{Q}unit_price#{Q}\) AS amount FROM #{Q}order_items#{Q}\s+GROUP BY #{Q}order_items#{Q}.#{Q}orderable_id#{Q}\) seat_order_items ON #{Q}seats#{Q}.#{Q}id#{Q} = #{Q}seat_order_items#{Q}.#{Q}orderable_id#{Q} WHERE #{Q}seat_order_items#{Q}.#{Q}amount#{Q} > 0/
         | 
| 740 | 
            +
                        relation.to_a.should have(10).seats
         | 
| 741 | 
            +
                        relation.to_a.second.amount.to_i.should eq(10)
         | 
| 742 | 
            +
                      end
         | 
| 743 | 
            +
             | 
| 744 | 
            +
                      it 'joins from an association with default scopes' do
         | 
| 745 | 
            +
                        if activerecord_version_at_least('3.1.0')
         | 
| 746 | 
            +
                          if MYSQL_ENV
         | 
| 747 | 
            +
                            User.first.groups.to_sql.should match /#{Q}memberships#{Q}.#{Q}active#{Q} = 1/
         | 
| 748 | 
            +
                          else
         | 
| 749 | 
            +
                            puts User.first.groups.to_sql
         | 
| 750 | 
            +
                            User.first.groups.to_sql.should match /#{Q}memberships#{Q}.#{Q}active#{Q} = 't'/
         | 
| 751 | 
            +
                          end
         | 
| 752 | 
            +
             | 
| 753 | 
            +
                        else
         | 
| 754 | 
            +
                          pending "Rails 3.0.x doesn't support to_sql in an association."
         | 
| 755 | 
            +
                        end
         | 
| 756 | 
            +
                      end
         | 
| 599 757 | 
             
                    end
         | 
| 600 758 |  | 
| 601 759 | 
             
                    describe '#having' do
         | 
| @@ -607,8 +765,12 @@ module Squeel | |
| 607 765 | 
             
                      end
         | 
| 608 766 |  | 
| 609 767 | 
             
                      it 'allows complex conditions on aggregate columns' do
         | 
| 610 | 
            -
                         | 
| 611 | 
            -
             | 
| 768 | 
            +
                        if SQLITE_ENV
         | 
| 769 | 
            +
                          relation = Person.group(:parent_id).having{salary == max(salary)}
         | 
| 770 | 
            +
                          relation.first.name.should eq Person.last.name
         | 
| 771 | 
            +
                        else
         | 
| 772 | 
            +
                          pending "MySQL & PG don't support this type of group & having clauses, don't use it."
         | 
| 773 | 
            +
                        end
         | 
| 612 774 | 
             
                      end
         | 
| 613 775 |  | 
| 614 776 | 
             
                      it 'allows a condition on a function via block' do
         | 
| @@ -627,13 +789,13 @@ module Squeel | |
| 627 789 |  | 
| 628 790 | 
             
                      it 'builds options with a block' do
         | 
| 629 791 | 
             
                        block = Person.order{name}
         | 
| 630 | 
            -
                        block.to_sql.should match /ORDER BY  | 
| 792 | 
            +
                        block.to_sql.should match /ORDER BY #{Q}people#{Q}.#{Q}name#{Q}/
         | 
| 631 793 | 
             
                      end
         | 
| 632 794 |  | 
| 633 795 | 
             
                      it 'allows AR 4.0-style hash options' do
         | 
| 634 796 | 
             
                        if activerecord_version_at_least '4.0.0'
         | 
| 635 797 | 
             
                          block = Person.order(:name => :desc)
         | 
| 636 | 
            -
                          block.to_sql.should match /ORDER BY  | 
| 798 | 
            +
                          block.to_sql.should match /ORDER BY #{Q}people#{Q}.#{Q}name#{Q} DESC/
         | 
| 637 799 | 
             
                        else
         | 
| 638 800 | 
             
                          pending 'Not required in AR versions < 4.0.0'
         | 
| 639 801 | 
             
                        end
         | 
| @@ -641,7 +803,7 @@ module Squeel | |
| 641 803 |  | 
| 642 804 | 
             
                      it 'allows ordering by an attributes of a joined table' do
         | 
| 643 805 | 
             
                        relation = Article.joins(:person).order { person.id.asc }
         | 
| 644 | 
            -
                        relation.to_sql.should match /ORDER BY  | 
| 806 | 
            +
                        relation.to_sql.should match /ORDER BY #{Q}people#{Q}.#{Q}id#{Q} ASC/
         | 
| 645 807 | 
             
                      end
         | 
| 646 808 |  | 
| 647 809 | 
             
                    end
         | 
| @@ -654,7 +816,7 @@ module Squeel | |
| 654 816 | 
             
                      it 'builds options with a block' do
         | 
| 655 817 | 
             
                        block = @standard.reorder{id}
         | 
| 656 818 | 
             
                        block.to_sql.should_not eq @standard.to_sql
         | 
| 657 | 
            -
                        block.to_sql.should match /ORDER BY  | 
| 819 | 
            +
                        block.to_sql.should match /ORDER BY #{Q}people#{Q}.#{Q}id#{Q}/
         | 
| 658 820 | 
             
                      end
         | 
| 659 821 |  | 
| 660 822 | 
             
                      it 'drops order by clause when passed nil' do
         | 
| @@ -673,7 +835,7 @@ module Squeel | |
| 673 835 |  | 
| 674 836 | 
             
                    describe '#from' do
         | 
| 675 837 | 
             
                      it 'creates froms with a block' do
         | 
| 676 | 
            -
                        expected = /SELECT  | 
| 838 | 
            +
                        expected = /SELECT #{Q}sub#{Q}.#{Q}name#{Q} AS aliased_name FROM \(SELECT #{Q}people#{Q}.#{Q}name#{Q} FROM #{Q}people#{Q}\s*\) sub/
         | 
| 677 839 | 
             
                        block = Person.from{Person.select{name}.as('sub')}.
         | 
| 678 840 | 
             
                          select{sub.name.as('aliased_name')}
         | 
| 679 841 | 
             
                        sql = block.to_sql
         | 
| @@ -681,7 +843,7 @@ module Squeel | |
| 681 843 | 
             
                      end
         | 
| 682 844 |  | 
| 683 845 | 
             
                      it 'creates froms from literals' do
         | 
| 684 | 
            -
                        expected = /SELECT  | 
| 846 | 
            +
                        expected = /SELECT #{Q}people#{Q}.* FROM sub/
         | 
| 685 847 | 
             
                        relation = Person.from('sub')
         | 
| 686 848 | 
             
                        sql = relation.to_sql
         | 
| 687 849 | 
             
                        sql.should match expected
         | 
| @@ -689,7 +851,7 @@ module Squeel | |
| 689 851 |  | 
| 690 852 | 
             
                      it 'creates froms from relations' do
         | 
| 691 853 | 
             
                        if activerecord_version_at_least '4.0.0'
         | 
| 692 | 
            -
                          expected = "SELECT  | 
| 854 | 
            +
                          expected = "SELECT #{Q}people#{Q}.* FROM (SELECT #{Q}people#{Q}.* FROM #{Q}people#{Q}) alias"
         | 
| 693 855 | 
             
                          relation = Person.from(Person.all, 'alias')
         | 
| 694 856 | 
             
                          sql = relation.to_sql
         | 
| 695 857 | 
             
                          sql.should == expected
         | 
| @@ -697,6 +859,17 @@ module Squeel | |
| 697 859 | 
             
                          pending 'Unsupported before ActiveRecord 4.0'
         | 
| 698 860 | 
             
                        end
         | 
| 699 861 | 
             
                      end
         | 
| 862 | 
            +
             | 
| 863 | 
            +
                      it 'binds params from CollectionProxy subquery' do
         | 
| 864 | 
            +
                        if activerecord_version_at_least('3.1.0')
         | 
| 865 | 
            +
                          first_article = Article.first
         | 
| 866 | 
            +
                          expected_tags = Tag.where(id: [1,2,3]).order{name}.to_a
         | 
| 867 | 
            +
             | 
| 868 | 
            +
                          expected_tags.should == Tag.from{first_article.tags.as(Tag.table_name)}.order{tags.name}.to_a
         | 
| 869 | 
            +
                        else
         | 
| 870 | 
            +
                          pending "ActiveRecord 3.0.x doesn't support CollectionProxy chain."
         | 
| 871 | 
            +
                        end
         | 
| 872 | 
            +
                      end
         | 
| 700 873 | 
             
                    end
         | 
| 701 874 |  | 
| 702 875 | 
             
                    describe '#build_where' do
         | 
| @@ -718,7 +891,12 @@ module Squeel | |
| 718 891 |  | 
| 719 892 | 
             
                      it 'adds hash where values without converting to Arel predicates' do
         | 
| 720 893 | 
             
                        wheres = Person.where({:name => 'bob'}).where_values
         | 
| 721 | 
            -
                         | 
| 894 | 
            +
                        if activerecord_version_at_least('4.0.0')
         | 
| 895 | 
            +
                          wheres.flatten.should have(1).equality
         | 
| 896 | 
            +
                          wheres.flatten.last.should be_kind_of(Arel::Nodes::Equality)
         | 
| 897 | 
            +
                        else
         | 
| 898 | 
            +
                          wheres.should eq [{:name => 'bob'}]
         | 
| 899 | 
            +
                        end
         | 
| 722 900 | 
             
                      end
         | 
| 723 901 |  | 
| 724 902 | 
             
                    end
         | 
| @@ -729,8 +907,12 @@ module Squeel | |
| 729 907 | 
             
                        relation = Person.includes(:comments, :articles).
         | 
| 730 908 | 
             
                          where(:comments => {:body => 'First post!'}).
         | 
| 731 909 | 
             
                          where(:articles => {:title => 'Hello, world!'})
         | 
| 732 | 
            -
                         | 
| 733 | 
            -
             | 
| 910 | 
            +
                        if activerecord_version_at_least('4.1.0')
         | 
| 911 | 
            +
                          relation.debug_sql.should_not eq relation.arel.to_sql
         | 
| 912 | 
            +
                        else
         | 
| 913 | 
            +
                          relation.debug_sql.should_not eq relation.to_sql
         | 
| 914 | 
            +
                        end
         | 
| 915 | 
            +
                        relation.debug_sql.should match /SELECT #{Q}people#{Q}.#{Q}id#{Q} AS t0_r0/
         | 
| 734 916 | 
             
                      end
         | 
| 735 917 |  | 
| 736 918 | 
             
                    end
         | 
| @@ -802,22 +984,27 @@ module Squeel | |
| 802 984 | 
             
                      it 'merges relations with the same base' do
         | 
| 803 985 | 
             
                        relation = Person.where{name == 'bob'}.merge(Person.where{salary == 100000})
         | 
| 804 986 | 
             
                        sql = relation.to_sql
         | 
| 805 | 
            -
                        sql.should match  | 
| 806 | 
            -
                        sql.should match  | 
| 987 | 
            +
                        sql.should match /#{Q}people#{Q}.#{Q}name#{Q} = 'bob'/
         | 
| 988 | 
            +
                        sql.should match /#{Q}people#{Q}.#{Q}salary#{Q} = 100000/
         | 
| 807 989 | 
             
                      end
         | 
| 808 990 |  | 
| 809 991 | 
             
                      it 'merges relations with a different base' do
         | 
| 810 992 | 
             
                        relation = Person.where{name == 'bob'}.joins(:articles).merge(Article.where{title == 'Hello world!'})
         | 
| 811 993 | 
             
                        sql = relation.to_sql
         | 
| 812 | 
            -
                        sql.should match /INNER JOIN  | 
| 813 | 
            -
                        sql.should match  | 
| 814 | 
            -
                        sql.should match  | 
| 994 | 
            +
                        sql.should match /INNER JOIN #{Q}articles#{Q} ON #{Q}articles#{Q}.#{Q}person_id#{Q} = #{Q}people#{Q}.#{Q}id#{Q}/
         | 
| 995 | 
            +
                        sql.should match /#{Q}people#{Q}.#{Q}name#{Q} = 'bob'/
         | 
| 996 | 
            +
                        sql.should match /#{Q}articles#{Q}.#{Q}title#{Q} = 'Hello world!'/
         | 
| 815 997 | 
             
                      end
         | 
| 816 998 |  | 
| 817 999 | 
             
                      it 'does not break hm:t with conditions' do
         | 
| 818 1000 | 
             
                        relation = Person.first.condition_article_comments
         | 
| 819 | 
            -
                        sql = | 
| 820 | 
            -
             | 
| 1001 | 
            +
                        sql =
         | 
| 1002 | 
            +
                          if activerecord_version_at_least('4.1.0')
         | 
| 1003 | 
            +
                            relation.to_sql
         | 
| 1004 | 
            +
                          else
         | 
| 1005 | 
            +
                            relation.scoped.to_sql
         | 
| 1006 | 
            +
                          end
         | 
| 1007 | 
            +
                        sql.should match /#{Q}articles#{Q}.#{Q}title#{Q} = 'Condition'/
         | 
| 821 1008 | 
             
                      end
         | 
| 822 1009 |  | 
| 823 1010 | 
             
                      it 'uses the last condition in the case of a conflicting where' do
         | 
| @@ -831,7 +1018,13 @@ module Squeel | |
| 831 1018 |  | 
| 832 1019 | 
             
                      it 'uses the given equality condition in the case of a conflicting where from a default scope' do
         | 
| 833 1020 | 
             
                        if activerecord_version_at_least '3.1'
         | 
| 834 | 
            -
                          relation = | 
| 1021 | 
            +
                          relation =
         | 
| 1022 | 
            +
                            if activerecord_version_at_least('4.1.0')
         | 
| 1023 | 
            +
                              PersonNamedBill.rewhere(name: 'Ernie')
         | 
| 1024 | 
            +
                              # Or PersonNamedBill.unscope(where: :name).where { name == 'Ernie' }
         | 
| 1025 | 
            +
                            else
         | 
| 1026 | 
            +
                              PersonNamedBill.where{name == 'Ernie'}
         | 
| 1027 | 
            +
                            end
         | 
| 835 1028 | 
             
                          sql = relation.to_sql
         | 
| 836 1029 | 
             
                          sql.should_not match /Bill/
         | 
| 837 1030 | 
             
                          sql.should match /Ernie/
         | 
| @@ -844,53 +1037,82 @@ module Squeel | |
| 844 1037 | 
             
                        relation = Person.with_article_title('hi').
         | 
| 845 1038 | 
             
                                          with_article_condition_title('yo')
         | 
| 846 1039 | 
             
                        sql = relation.to_sql
         | 
| 847 | 
            -
                        sql.should match  | 
| 848 | 
            -
                        sql.should match  | 
| 1040 | 
            +
                        sql.should match /#{Q}articles#{Q}.#{Q}title#{Q} = 'hi'/
         | 
| 1041 | 
            +
                        sql.should match /#{Q}articles_with_conditions_people#{Q}.#{Q}title#{Q} = 'yo'/
         | 
| 849 1042 | 
             
                      end
         | 
| 850 1043 |  | 
| 851 1044 | 
             
                      it "doesn't ruin everything when a scope returns nil" do
         | 
| 852 1045 | 
             
                        relation = Person.nil_scope
         | 
| 853 | 
            -
                         | 
| 1046 | 
            +
                        if activerecord_version_at_least('4.1.0')
         | 
| 1047 | 
            +
                          relation.should eq Person.all
         | 
| 1048 | 
            +
                        else
         | 
| 1049 | 
            +
                          relation.should eq Person.scoped
         | 
| 1050 | 
            +
                        end
         | 
| 854 1051 | 
             
                      end
         | 
| 855 1052 |  | 
| 856 1053 | 
             
                      it "doesn't ruin everything when a group exists" do
         | 
| 857 | 
            -
                        relation = Person.scoped.merge(Person.group{name})
         | 
| 858 1054 | 
             
                        count_hash = {}
         | 
| 859 | 
            -
                         | 
| 860 | 
            -
             | 
| 1055 | 
            +
                        if activerecord_version_at_least('4.1.0')
         | 
| 1056 | 
            +
                          relation = Person.all.merge(Person.group{name})
         | 
| 1057 | 
            +
                          expect { count_hash = relation.count }.should_not raise_error
         | 
| 1058 | 
            +
                          count_hash.size.should eq Person.all.size
         | 
| 1059 | 
            +
                        else
         | 
| 1060 | 
            +
                          relation = Person.scoped.merge(Person.group{name})
         | 
| 1061 | 
            +
                          expect { count_hash = relation.count }.should_not raise_error
         | 
| 1062 | 
            +
                          count_hash.size.should eq Person.scoped.size
         | 
| 1063 | 
            +
                        end
         | 
| 1064 | 
            +
             | 
| 861 1065 | 
             
                        count_hash.values.all? {|v| v == 1}.should be_true
         | 
| 862 1066 | 
             
                        count_hash.keys.should =~ Person.select{name}.map(&:name)
         | 
| 863 1067 | 
             
                      end
         | 
| 864 1068 |  | 
| 865 1069 | 
             
                      it "doesn't merge the default scope more than once" do
         | 
| 866 | 
            -
                        relation = | 
| 1070 | 
            +
                        relation =
         | 
| 1071 | 
            +
                          if activerecord_version_at_least('4.1.0')
         | 
| 1072 | 
            +
                            PersonNamedBill.all.highly_compensated.ending_with_ill
         | 
| 1073 | 
            +
                          else
         | 
| 1074 | 
            +
                            PersonNamedBill.scoped.highly_compensated.ending_with_ill
         | 
| 1075 | 
            +
                          end
         | 
| 867 1076 | 
             
                        sql = relation.to_sql
         | 
| 868 | 
            -
                        sql.scan( | 
| 869 | 
            -
                        sql.scan( | 
| 870 | 
            -
                        sql.scan( | 
| 871 | 
            -
                        sql.scan( | 
| 1077 | 
            +
                        sql.scan(/#{Q}people#{Q}.#{Q}name#{Q} = 'Bill'/).should have(1).item
         | 
| 1078 | 
            +
                        sql.scan(/#{Q}people#{Q}.#{Q}name#{Q} [I]*LIKE '%ill'/).should have(1).item
         | 
| 1079 | 
            +
                        sql.scan(/#{Q}people#{Q}.#{Q}salary#{Q} > 200000/).should have(1).item
         | 
| 1080 | 
            +
                        sql.scan(/#{Q}people#{Q}.#{Q}id#{Q}/).should have(1).item
         | 
| 872 1081 | 
             
                      end
         | 
| 873 1082 |  | 
| 874 1083 | 
             
                      it "doesn't hijack the table name when merging a relation with different base and default_scope" do
         | 
| 875 | 
            -
                        relation = | 
| 1084 | 
            +
                        relation =
         | 
| 1085 | 
            +
                          if activerecord_version_at_least('4.1.0')
         | 
| 1086 | 
            +
                            Article.joins(:person).merge(PersonNamedBill.all)
         | 
| 1087 | 
            +
                          else
         | 
| 1088 | 
            +
                            Article.joins(:person).merge(PersonNamedBill.scoped)
         | 
| 1089 | 
            +
                          end
         | 
| 876 1090 | 
             
                        sql = relation.to_sql
         | 
| 877 | 
            -
                        sql.scan( | 
| 1091 | 
            +
                        sql.scan(/#{Q}people#{Q}.#{Q}name#{Q} = 'Bill'/).should have(1).item
         | 
| 878 1092 | 
             
                      end
         | 
| 879 1093 |  | 
| 880 1094 | 
             
                      it 'merges scopes that contain functions' do
         | 
| 881 | 
            -
                        relation = | 
| 1095 | 
            +
                        relation =
         | 
| 1096 | 
            +
                          if activerecord_version_at_least('4.1.0')
         | 
| 1097 | 
            +
                            PersonNamedBill.all.with_salary_equal_to(100)
         | 
| 1098 | 
            +
                          else
         | 
| 1099 | 
            +
                            PersonNamedBill.scoped.with_salary_equal_to(100)
         | 
| 1100 | 
            +
                          end
         | 
| 882 1101 | 
             
                        sql = relation.to_sql
         | 
| 883 | 
            -
                        sql.should match /abs\( | 
| 1102 | 
            +
                        sql.should match /abs\(#{Q}people#{Q}.#{Q}salary#{Q}\) = 100/
         | 
| 884 1103 | 
             
                      end
         | 
| 885 1104 |  | 
| 886 1105 | 
             
                      it 'uses last equality when merging two scopes with identical function equalities' do
         | 
| 887 | 
            -
                         | 
| 888 | 
            -
             | 
| 889 | 
            -
                         | 
| 890 | 
            -
             | 
| 891 | 
            -
             | 
| 1106 | 
            +
                        if activerecord_version_at_least('4.1.0')
         | 
| 1107 | 
            +
                          pending "Named Functions can't be unscoped"
         | 
| 1108 | 
            +
                        else
         | 
| 1109 | 
            +
                          relation = PersonNamedBill.scoped.with_salary_equal_to(100).
         | 
| 1110 | 
            +
                                                            with_salary_equal_to(200)
         | 
| 1111 | 
            +
                          sql = relation.to_sql
         | 
| 1112 | 
            +
                          sql.should_not match /abs\(#{Q}people#{Q}.#{Q}salary#{Q}\) = 100/
         | 
| 1113 | 
            +
                          sql.should match /abs\(#{Q}people#{Q}.#{Q}salary#{Q}\) = 200/
         | 
| 1114 | 
            +
                        end
         | 
| 892 1115 | 
             
                      end
         | 
| 893 | 
            -
             | 
| 894 1116 | 
             
                    end
         | 
| 895 1117 |  | 
| 896 1118 | 
             
                    describe '#to_a' do
         | 
| @@ -908,14 +1130,18 @@ module Squeel | |
| 908 1130 | 
             
                        relation = UnidentifiedObject.where{person_id < 120}.includes(:person)
         | 
| 909 1131 | 
             
                        queries = queries_for do
         | 
| 910 1132 | 
             
                          vals = relation.to_a
         | 
| 911 | 
            -
                          vals.should have( | 
| 1133 | 
            +
                          vals.should have(20).items
         | 
| 912 1134 | 
             
                        end
         | 
| 913 1135 |  | 
| 914 | 
            -
                         | 
| 1136 | 
            +
                        if activerecord_version_at_least('3.1.0')
         | 
| 1137 | 
            +
                          queries.should have(2).queries
         | 
| 1138 | 
            +
                        else
         | 
| 1139 | 
            +
                          puts 'skips count of queries expectation'
         | 
| 1140 | 
            +
                        end
         | 
| 915 1141 |  | 
| 916 1142 | 
             
                        matched_ids = queries.last.match(/IN \(([^)]*)/).captures.first
         | 
| 917 1143 | 
             
                        matched_ids = matched_ids.split(/,\s*/).map(&:to_i)
         | 
| 918 | 
            -
                        matched_ids.should =~ [1,  | 
| 1144 | 
            +
                        matched_ids.should =~ [1, 2, 3, 4, 5 ,6 ,7 ,8 ,9 ,10]
         | 
| 919 1145 | 
             
                      end
         | 
| 920 1146 |  | 
| 921 1147 | 
             
                    end
         |