active_record_extended 1.4.0 → 2.0.0
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 +4 -4
- data/README.md +8 -7
- data/lib/active_record_extended/active_record.rb +1 -10
- data/lib/active_record_extended/active_record/relation_patch.rb +16 -1
- data/lib/active_record_extended/arel.rb +1 -0
- data/lib/active_record_extended/arel/nodes.rb +22 -21
- data/lib/active_record_extended/arel/sql_literal.rb +16 -0
- data/lib/active_record_extended/query_methods/any_of.rb +5 -4
- data/lib/active_record_extended/query_methods/either.rb +1 -1
- data/lib/active_record_extended/query_methods/inet.rb +6 -2
- data/lib/active_record_extended/query_methods/json.rb +13 -16
- data/lib/active_record_extended/query_methods/select.rb +11 -10
- data/lib/active_record_extended/query_methods/unionize.rb +10 -4
- data/lib/active_record_extended/query_methods/where_chain.rb +14 -6
- data/lib/active_record_extended/query_methods/window.rb +4 -3
- data/lib/active_record_extended/query_methods/with_cte.rb +102 -35
- data/lib/active_record_extended/utilities/order_by.rb +9 -28
- data/lib/active_record_extended/utilities/support.rb +8 -15
- data/lib/active_record_extended/version.rb +1 -1
- data/spec/query_methods/any_of_spec.rb +2 -2
- data/spec/query_methods/json_spec.rb +5 -5
- data/spec/query_methods/select_spec.rb +13 -13
- data/spec/query_methods/unionize_spec.rb +5 -5
- data/spec/query_methods/with_cte_spec.rb +12 -2
- data/spec/spec_helper.rb +1 -1
- data/spec/sql_inspections/any_of_sql_spec.rb +2 -2
- data/spec/sql_inspections/contains_sql_queries_spec.rb +8 -8
- data/spec/sql_inspections/either_sql_spec.rb +3 -3
- data/spec/sql_inspections/json_sql_spec.rb +0 -1
- data/spec/sql_inspections/unionize_sql_spec.rb +2 -2
- data/spec/sql_inspections/window_sql_spec.rb +12 -0
- data/spec/sql_inspections/with_cte_sql_spec.rb +30 -1
- metadata +18 -20
- data/lib/active_record_extended/patch/5_0/predicate_builder_decorator.rb +0 -87
- data/lib/active_record_extended/patch/5_0/regex_match.rb +0 -10
| @@ -17,13 +17,13 @@ RSpec.describe "Active Record Union Methods" do | |
| 17 17 |  | 
| 18 18 | 
             
                it "should raise an error if the select statements do not align" do
         | 
| 19 19 | 
             
                  expect { misaligned_cmd.to_a }.to(
         | 
| 20 | 
            -
                    raise_error(ActiveRecord::StatementInvalid, /each [[:alpha:]]+ query must have the same number of columns/) | 
| 20 | 
            +
                    raise_error(ActiveRecord::StatementInvalid, /each [[:alpha:]]+ query must have the same number of columns/)
         | 
| 21 21 | 
             
                  )
         | 
| 22 22 | 
             
                end
         | 
| 23 23 |  | 
| 24 24 | 
             
                it "should raise an argument error if there are less then two union statements" do
         | 
| 25 25 | 
             
                  expect { lacking_union_cmd.to_a }.to(
         | 
| 26 | 
            -
                    raise_error(ArgumentError, "You are required to provide 2 or more unions to join!") | 
| 26 | 
            +
                    raise_error(ArgumentError, "You are required to provide 2 or more unions to join!")
         | 
| 27 27 | 
             
                  )
         | 
| 28 28 | 
             
                end
         | 
| 29 29 | 
             
              end
         | 
| @@ -88,7 +88,7 @@ RSpec.describe "Active Record Union Methods" do | |
| 88 88 | 
             
                  query =
         | 
| 89 89 | 
             
                    User.union.intersect(
         | 
| 90 90 | 
             
                      User.select(:id, "profile_ls.likes").joins(:profile_l).where(profile_ls: { likes: 100 }),
         | 
| 91 | 
            -
                      User.select(:id, "profile_ls.likes").joins(:profile_l).where("profile_ls.likes < 150") | 
| 91 | 
            +
                      User.select(:id, "profile_ls.likes").joins(:profile_l).where("profile_ls.likes < 150")
         | 
| 92 92 | 
             
                    )
         | 
| 93 93 |  | 
| 94 94 | 
             
                  expect(query.pluck(:id)).to have_attributes(size: 1).and(eq([user_one_pl.id]))
         | 
| @@ -129,7 +129,7 @@ RSpec.describe "Active Record Union Methods" do | |
| 129 129 | 
             
                  query =
         | 
| 130 130 | 
             
                    User.union.all(
         | 
| 131 131 | 
             
                      User.where(id: user_one.id),
         | 
| 132 | 
            -
                      User.where(id: user_three.id) | 
| 132 | 
            +
                      User.where(id: user_three.id)
         | 
| 133 133 | 
             
                    ).order_union(id: :desc)
         | 
| 134 134 |  | 
| 135 135 | 
             
                  expect(query).to eq([user_three, user_one])
         | 
| @@ -144,7 +144,7 @@ RSpec.describe "Active Record Union Methods" do | |
| 144 144 | 
             
                  query =
         | 
| 145 145 | 
             
                    User.union.intersect(
         | 
| 146 146 | 
             
                      User.where("id < ?", user_three.id),
         | 
| 147 | 
            -
                      User.where("id >= ?", user_one.id) | 
| 147 | 
            +
                      User.where("id >= ?", user_one.id)
         | 
| 148 148 | 
             
                    ).order_union(id: :desc)
         | 
| 149 149 |  | 
| 150 150 | 
             
                  expect(query).to eq([user_two, user_one])
         | 
| @@ -3,8 +3,8 @@ | |
| 3 3 | 
             
            require "spec_helper"
         | 
| 4 4 |  | 
| 5 5 | 
             
            RSpec.describe "Active Record With CTE Query Methods" do
         | 
| 6 | 
            -
              let!(:user_one) | 
| 7 | 
            -
              let!(:user_two) | 
| 6 | 
            +
              let!(:user_one)    { User.create! }
         | 
| 7 | 
            +
              let!(:user_two)    { User.create! }
         | 
| 8 8 | 
             
              let!(:profile_one) { ProfileL.create!(user_id: user_one.id, likes: 200) }
         | 
| 9 9 | 
             
              let!(:profile_two) { ProfileL.create!(user_id: user_two.id, likes: 500) }
         | 
| 10 10 |  | 
| @@ -35,6 +35,16 @@ RSpec.describe "Active Record With CTE Query Methods" do | |
| 35 35 |  | 
| 36 36 | 
             
                    expect(query).to match_array([user_one])
         | 
| 37 37 | 
             
                  end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                  it "should contain a unique list of ordered CTE keys when merging in multiple children" do
         | 
| 40 | 
            +
                    x     = User.with(profile: ProfileL.where("likes < 300"))
         | 
| 41 | 
            +
                    y     = User.with(profile: ProfileL.where("likes > 400"))
         | 
| 42 | 
            +
                    z     = y.merge(x).joins("JOIN profile ON profile.id = users.id") # Y should reject X's CTE (FIFO)
         | 
| 43 | 
            +
                    query = User.with(my_profile: z).joins("JOIN my_profile ON my_profile.id = users.id")
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                    expect(query.cte.with_keys).to eq([:profile, :my_profile])
         | 
| 46 | 
            +
                    expect(query).to match_array([user_two])
         | 
| 47 | 
            +
                  end
         | 
| 38 48 | 
             
                end
         | 
| 39 49 | 
             
              end
         | 
| 40 50 | 
             
            end
         | 
    
        data/spec/spec_helper.rb
    CHANGED
    
    | @@ -13,7 +13,7 @@ end | |
| 13 13 | 
             
            ActiveRecord::Base.establish_connection(ENV["DATABASE_URL"])
         | 
| 14 14 |  | 
| 15 15 | 
             
            Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require File.expand_path(f) }
         | 
| 16 | 
            -
            Dir["#{File.dirname(__FILE__)}/**/*examples.rb"].each { |f| require f }
         | 
| 16 | 
            +
            Dir["#{File.dirname(__FILE__)}/**/*examples.rb"].sort.each { |f| require f }
         | 
| 17 17 |  | 
| 18 18 | 
             
            RSpec.configure do |config|
         | 
| 19 19 | 
             
              # Enable flags like --only-failures and --next-failure
         | 
| @@ -5,8 +5,8 @@ require "spec_helper" | |
| 5 5 | 
             
            RSpec.describe "Any / None of SQL Queries" do
         | 
| 6 6 | 
             
              let(:equal_query) { '"users"."personal_id" = 1' }
         | 
| 7 7 | 
             
              let(:or_query)    { 'OR "users"."personal_id" = 2' }
         | 
| 8 | 
            -
              let(:equal_or)    { equal_query  | 
| 9 | 
            -
              let(:join_query)  { /INNER JOIN  | 
| 8 | 
            +
              let(:equal_or)    { "#{equal_query} #{or_query}" }
         | 
| 9 | 
            +
              let(:join_query)  { /INNER JOIN "tags" ON "tags"."user_id" = "users"."id/ }
         | 
| 10 10 |  | 
| 11 11 | 
             
              describe "where.any_of/1" do
         | 
| 12 12 | 
             
                it "should group different column arguments into nested or conditions" do
         | 
| @@ -3,14 +3,14 @@ | |
| 3 3 | 
             
            require "spec_helper"
         | 
| 4 4 |  | 
| 5 5 | 
             
            RSpec.describe "Contains SQL Queries" do
         | 
| 6 | 
            -
              let(:contains_array_regex)      {  | 
| 7 | 
            -
              let(:contains_hstore_regex)     {  | 
| 8 | 
            -
              let(:contains_jsonb_regex)      {  | 
| 9 | 
            -
              let(:contained_in_array_regex)  {  | 
| 10 | 
            -
              let(:contained_in_hstore_regex) {  | 
| 11 | 
            -
              let(:contained_in_jsonb_regex) {  | 
| 12 | 
            -
              let(:contains_equals_regex)     {  | 
| 13 | 
            -
              let(:equality_regex)            {  | 
| 6 | 
            +
              let(:contains_array_regex)      { /"users"\."tag_ids" @> '\{1,2\}'/ }
         | 
| 7 | 
            +
              let(:contains_hstore_regex)     { /"users"\."data" @> '"nickname"=>"Dan"'/ }
         | 
| 8 | 
            +
              let(:contains_jsonb_regex)      { /"users"\."jsonb_data" @> '\{"nickname":"Dan"}'/ }
         | 
| 9 | 
            +
              let(:contained_in_array_regex)  { /"users"\."tag_ids" <@ '\{1,2\}'/ }
         | 
| 10 | 
            +
              let(:contained_in_hstore_regex) { /"users"\."data" <@ '"nickname"=>"Dan"'/ }
         | 
| 11 | 
            +
              let(:contained_in_jsonb_regex) { /"users"\."jsonb_data" <@ '\{"nickname":"Dan"}'/ }
         | 
| 12 | 
            +
              let(:contains_equals_regex)     { /"users"\."ip" >>= '127.0.0.1'/ }
         | 
| 13 | 
            +
              let(:equality_regex)            { /"users"\."tags" = '\{"?working"?\}'/ }
         | 
| 14 14 |  | 
| 15 15 | 
             
              describe ".where.contains(:column => value)" do
         | 
| 16 16 | 
             
                it "generates the appropriate where clause for array columns" do
         | 
| @@ -3,9 +3,9 @@ | |
| 3 3 | 
             
            require "spec_helper"
         | 
| 4 4 |  | 
| 5 5 | 
             
            RSpec.describe "Either Methods SQL Queries" do
         | 
| 6 | 
            -
              let(:contains_array_regex) {  | 
| 7 | 
            -
              let(:profile_l_outer_join) { /LEFT OUTER JOIN  | 
| 8 | 
            -
              let(:profile_r_outer_join) { /LEFT OUTER JOIN  | 
| 6 | 
            +
              let(:contains_array_regex) { /"users"\."tag_ids" @> '\{1,2\}'/ }
         | 
| 7 | 
            +
              let(:profile_l_outer_join) { /LEFT OUTER JOIN "profile_ls" ON "profile_ls"."user_id" = "users"."id"/ }
         | 
| 8 | 
            +
              let(:profile_r_outer_join) { /LEFT OUTER JOIN "profile_rs" ON "profile_rs"."user_id" = "users"."id"/ }
         | 
| 9 9 | 
             
              let(:where_join_case) do
         | 
| 10 10 | 
             
                "WHERE ((CASE WHEN profile_ls.user_id IS NULL"\
         | 
| 11 11 | 
             
                " THEN profile_rs.user_id"\
         | 
| @@ -27,7 +27,6 @@ RSpec.describe "JSON Methods SQL Queries" do | |
| 27 27 | 
             
                context "When adding cast_with: option" do
         | 
| 28 28 | 
             
                  it "should wrap the row_to_json expression with to_jsonb" do
         | 
| 29 29 | 
             
                    query = User.select_row_to_json(User.where(id: 10), cast_with: :to_jsonb, key: :convert_this, as: :results).to_sql
         | 
| 30 | 
            -
                    puts query
         | 
| 31 30 | 
             
                    expect(query).to match_regex(/SELECT \(SELECT TO_JSONB\(ROW_TO_JSON\("convert_this"\)\) FROM \(.+\).+\) AS "results"/)
         | 
| 32 31 | 
             
                  end
         | 
| 33 32 |  | 
| @@ -74,7 +74,7 @@ RSpec.describe "Union SQL Queries" do | |
| 74 74 |  | 
| 75 75 | 
             
                  it "should alias the union from clause to 'happy_users'" do
         | 
| 76 76 | 
             
                    expect(described_method).to match_regex(/FROM \(+.+\) UNION \(.+\)+ happy_users$/)
         | 
| 77 | 
            -
                    expect(described_method).to match_regex(/^SELECT happy_users\.id FROM.+happy_users$/)
         | 
| 77 | 
            +
                    expect(described_method).to match_regex(/^SELECT (happy_users\.id|"happy_users"\."id") FROM.+happy_users$/)
         | 
| 78 78 | 
             
                  end
         | 
| 79 79 | 
             
                end
         | 
| 80 80 |  | 
| @@ -83,7 +83,7 @@ RSpec.describe "Union SQL Queries" do | |
| 83 83 |  | 
| 84 84 | 
             
                  it "should retain the actual class calling table name as the union alias" do
         | 
| 85 85 | 
             
                    expect(described_method).to match_regex(/FROM \(+.+\) UNION \(.+\)+ users$/)
         | 
| 86 | 
            -
                    expect(described_method).to match_regex(/^SELECT  | 
| 86 | 
            +
                    expect(described_method).to match_regex(/^SELECT "users"\."id" FROM.+users$/)
         | 
| 87 87 | 
             
                  end
         | 
| 88 88 | 
             
                end
         | 
| 89 89 | 
             
              end
         | 
| @@ -82,5 +82,17 @@ RSpec.describe "Active Record WINDOW Query inspection" do | |
| 82 82 | 
             
                    end
         | 
| 83 83 | 
             
                  end
         | 
| 84 84 | 
             
                end
         | 
| 85 | 
            +
             | 
| 86 | 
            +
                context "when not providing a partition by value" do
         | 
| 87 | 
            +
                  it "should construct a window function" do
         | 
| 88 | 
            +
                    query =
         | 
| 89 | 
            +
                      Tag
         | 
| 90 | 
            +
                      .define_window(:no_args).partition_by(order_by: { tag_number: :desc })
         | 
| 91 | 
            +
                      .select_window(:row_number, over: :no_args, as: :my_row)
         | 
| 92 | 
            +
                      .to_sql
         | 
| 93 | 
            +
             | 
| 94 | 
            +
                    expect(query).to eq("SELECT (ROW_NUMBER() OVER no_args) AS \"my_row\" FROM \"tags\" WINDOW no_args AS (ORDER BY tag_number DESC)")
         | 
| 95 | 
            +
                  end
         | 
| 96 | 
            +
                end
         | 
| 85 97 | 
             
              end
         | 
| 86 98 | 
             
            end
         | 
| @@ -21,6 +21,20 @@ RSpec.describe "Active Record WITH CTE tables" do | |
| 21 21 | 
             
                expect(query).to match_regex(with_personal_query)
         | 
| 22 22 | 
             
              end
         | 
| 23 23 |  | 
| 24 | 
            +
              it "will pipe Children CTE's into the Parent relation" do
         | 
| 25 | 
            +
                personal_id_one_query = User.where(personal_id: 1)
         | 
| 26 | 
            +
                personal_id_two_query = User.where(personal_id: 2)
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                sub_query       = personal_id_two_query.with(personal_id_one: personal_id_one_query)
         | 
| 29 | 
            +
                query           = User.all.with(personal_id_two: sub_query)
         | 
| 30 | 
            +
                expected_order  = User.with(
         | 
| 31 | 
            +
                  personal_id_one: personal_id_one_query,
         | 
| 32 | 
            +
                  personal_id_two: personal_id_two_query
         | 
| 33 | 
            +
                )
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                expect(query.to_sql).to eq(expected_order.to_sql)
         | 
| 36 | 
            +
              end
         | 
| 37 | 
            +
             | 
| 24 38 | 
             
              context "when multiple CTE's" do
         | 
| 25 39 | 
             
                let(:chained_with) do
         | 
| 26 40 | 
             
                  User.with(personal_id_one: User.where(personal_id: 1))
         | 
| @@ -36,6 +50,7 @@ RSpec.describe "Active Record WITH CTE tables" do | |
| 36 50 | 
             
                      .joins("JOIN personal_id_two ON personal_id_two.id = users.id")
         | 
| 37 51 | 
             
                      .to_sql
         | 
| 38 52 | 
             
                end
         | 
| 53 | 
            +
             | 
| 39 54 | 
             
                it "Should only contain a single WITH statement" do
         | 
| 40 55 | 
             
                  expect(with_arguments.scan(/WITH/).count).to eq(1)
         | 
| 41 56 | 
             
                  expect(with_arguments.scan(/AS/).count).to eq(2)
         | 
| @@ -60,7 +75,21 @@ RSpec.describe "Active Record WITH CTE tables" do | |
| 60 75 | 
             
                end
         | 
| 61 76 |  | 
| 62 77 | 
             
                it "generates an expression with recursive" do
         | 
| 63 | 
            -
                   | 
| 78 | 
            +
                  query = User.with
         | 
| 79 | 
            +
                              .recursive(personal_id_one: User.where(personal_id: 1))
         | 
| 80 | 
            +
                              .joins("JOIN personal_id_one ON personal_id_one.id = users.id")
         | 
| 81 | 
            +
                              .to_sql
         | 
| 82 | 
            +
             | 
| 83 | 
            +
                  expect(query).to match_regex(with_recursive_personal_query)
         | 
| 84 | 
            +
                end
         | 
| 85 | 
            +
             | 
| 86 | 
            +
                it "will maintain the CTE table when merging" do
         | 
| 87 | 
            +
                  sub_query = User.with.recursive(personal_id_one: User.where(personal_id: 1))
         | 
| 88 | 
            +
                  query     = User.merge(sub_query)
         | 
| 89 | 
            +
                                  .joins("JOIN personal_id_one ON personal_id_one.id = users.id")
         | 
| 90 | 
            +
                                  .to_sql
         | 
| 91 | 
            +
             | 
| 92 | 
            +
                  expect(query).to match_regex(with_recursive_personal_query)
         | 
| 64 93 | 
             
                end
         | 
| 65 94 | 
             
              end
         | 
| 66 95 | 
             
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,16 +1,16 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: active_record_extended
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version:  | 
| 4 | 
            +
              version: 2.0.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - George Protacio-Karaszi
         | 
| 8 8 | 
             
            - Dan McClain
         | 
| 9 9 | 
             
            - Olivier El Mekki
         | 
| 10 | 
            -
            autorequire: | 
| 10 | 
            +
            autorequire:
         | 
| 11 11 | 
             
            bindir: bin
         | 
| 12 12 | 
             
            cert_chain: []
         | 
| 13 | 
            -
            date:  | 
| 13 | 
            +
            date: 2020-12-22 00:00:00.000000000 Z
         | 
| 14 14 | 
             
            dependencies:
         | 
| 15 15 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 16 16 | 
             
              name: activerecord
         | 
| @@ -18,20 +18,20 @@ dependencies: | |
| 18 18 | 
             
                requirements:
         | 
| 19 19 | 
             
                - - ">="
         | 
| 20 20 | 
             
                  - !ruby/object:Gem::Version
         | 
| 21 | 
            -
                    version: '5. | 
| 21 | 
            +
                    version: '5.1'
         | 
| 22 22 | 
             
                - - "<"
         | 
| 23 23 | 
             
                  - !ruby/object:Gem::Version
         | 
| 24 | 
            -
                    version: '6. | 
| 24 | 
            +
                    version: '6.2'
         | 
| 25 25 | 
             
              type: :runtime
         | 
| 26 26 | 
             
              prerelease: false
         | 
| 27 27 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 28 28 | 
             
                requirements:
         | 
| 29 29 | 
             
                - - ">="
         | 
| 30 30 | 
             
                  - !ruby/object:Gem::Version
         | 
| 31 | 
            -
                    version: '5. | 
| 31 | 
            +
                    version: '5.1'
         | 
| 32 32 | 
             
                - - "<"
         | 
| 33 33 | 
             
                  - !ruby/object:Gem::Version
         | 
| 34 | 
            -
                    version: '6. | 
| 34 | 
            +
                    version: '6.2'
         | 
| 35 35 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 36 36 | 
             
              name: ar_outer_joins
         | 
| 37 37 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -52,14 +52,14 @@ dependencies: | |
| 52 52 | 
             
                requirements:
         | 
| 53 53 | 
             
                - - "<"
         | 
| 54 54 | 
             
                  - !ruby/object:Gem::Version
         | 
| 55 | 
            -
                    version: ' | 
| 55 | 
            +
                    version: '3.0'
         | 
| 56 56 | 
             
              type: :runtime
         | 
| 57 57 | 
             
              prerelease: false
         | 
| 58 58 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 59 59 | 
             
                requirements:
         | 
| 60 60 | 
             
                - - "<"
         | 
| 61 61 | 
             
                  - !ruby/object:Gem::Version
         | 
| 62 | 
            -
                    version: ' | 
| 62 | 
            +
                    version: '3.0'
         | 
| 63 63 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 64 64 | 
             
              name: bundler
         | 
| 65 65 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -69,7 +69,7 @@ dependencies: | |
| 69 69 | 
             
                    version: '1.16'
         | 
| 70 70 | 
             
                - - "<"
         | 
| 71 71 | 
             
                  - !ruby/object:Gem::Version
         | 
| 72 | 
            -
                    version: ' | 
| 72 | 
            +
                    version: '3.0'
         | 
| 73 73 | 
             
              type: :development
         | 
| 74 74 | 
             
              prerelease: false
         | 
| 75 75 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| @@ -79,7 +79,7 @@ dependencies: | |
| 79 79 | 
             
                    version: '1.16'
         | 
| 80 80 | 
             
                - - "<"
         | 
| 81 81 | 
             
                  - !ruby/object:Gem::Version
         | 
| 82 | 
            -
                    version: ' | 
| 82 | 
            +
                    version: '3.0'
         | 
| 83 83 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 84 84 | 
             
              name: database_cleaner
         | 
| 85 85 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -98,14 +98,14 @@ dependencies: | |
| 98 98 | 
             
              name: rake
         | 
| 99 99 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| 100 100 | 
             
                requirements:
         | 
| 101 | 
            -
                - - " | 
| 101 | 
            +
                - - ">="
         | 
| 102 102 | 
             
                  - !ruby/object:Gem::Version
         | 
| 103 103 | 
             
                    version: '10.0'
         | 
| 104 104 | 
             
              type: :development
         | 
| 105 105 | 
             
              prerelease: false
         | 
| 106 106 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 107 107 | 
             
                requirements:
         | 
| 108 | 
            -
                - - " | 
| 108 | 
            +
                - - ">="
         | 
| 109 109 | 
             
                  - !ruby/object:Gem::Version
         | 
| 110 110 | 
             
                    version: '10.0'
         | 
| 111 111 | 
             
            - !ruby/object:Gem::Dependency
         | 
| @@ -153,9 +153,8 @@ files: | |
| 153 153 | 
             
            - lib/active_record_extended/arel/aggregate_function_name.rb
         | 
| 154 154 | 
             
            - lib/active_record_extended/arel/nodes.rb
         | 
| 155 155 | 
             
            - lib/active_record_extended/arel/predications.rb
         | 
| 156 | 
            +
            - lib/active_record_extended/arel/sql_literal.rb
         | 
| 156 157 | 
             
            - lib/active_record_extended/arel/visitors/postgresql_decorator.rb
         | 
| 157 | 
            -
            - lib/active_record_extended/patch/5_0/predicate_builder_decorator.rb
         | 
| 158 | 
            -
            - lib/active_record_extended/patch/5_0/regex_match.rb
         | 
| 159 158 | 
             
            - lib/active_record_extended/patch/5_1/where_clause.rb
         | 
| 160 159 | 
             
            - lib/active_record_extended/patch/5_2/where_clause.rb
         | 
| 161 160 | 
             
            - lib/active_record_extended/predicate_builder/array_handler_decorator.rb
         | 
| @@ -199,7 +198,7 @@ homepage: https://github.com/georgekaraszi/ActiveRecordExtended | |
| 199 198 | 
             
            licenses:
         | 
| 200 199 | 
             
            - MIT
         | 
| 201 200 | 
             
            metadata: {}
         | 
| 202 | 
            -
            post_install_message: | 
| 201 | 
            +
            post_install_message:
         | 
| 203 202 | 
             
            rdoc_options: []
         | 
| 204 203 | 
             
            require_paths:
         | 
| 205 204 | 
             
            - lib
         | 
| @@ -207,16 +206,15 @@ required_ruby_version: !ruby/object:Gem::Requirement | |
| 207 206 | 
             
              requirements:
         | 
| 208 207 | 
             
              - - ">="
         | 
| 209 208 | 
             
                - !ruby/object:Gem::Version
         | 
| 210 | 
            -
                  version: ' | 
| 209 | 
            +
                  version: '2.4'
         | 
| 211 210 | 
             
            required_rubygems_version: !ruby/object:Gem::Requirement
         | 
| 212 211 | 
             
              requirements:
         | 
| 213 212 | 
             
              - - ">="
         | 
| 214 213 | 
             
                - !ruby/object:Gem::Version
         | 
| 215 214 | 
             
                  version: '0'
         | 
| 216 215 | 
             
            requirements: []
         | 
| 217 | 
            -
             | 
| 218 | 
            -
             | 
| 219 | 
            -
            signing_key: 
         | 
| 216 | 
            +
            rubygems_version: 3.0.6
         | 
| 217 | 
            +
            signing_key:
         | 
| 220 218 | 
             
            specification_version: 4
         | 
| 221 219 | 
             
            summary: Adds extended functionality to Activerecord Postgres implementation
         | 
| 222 220 | 
             
            test_files:
         | 
| @@ -1,87 +0,0 @@ | |
| 1 | 
            -
            # frozen_string_literal: true
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            # Stripped from Rails 5.1.x
         | 
| 4 | 
            -
            # This patch is used so that when querying with hash elements that do not belong to an association,
         | 
| 5 | 
            -
            # but instead a data attribute. It returns the corrected attribute binds back to the query builder.
         | 
| 6 | 
            -
            #
         | 
| 7 | 
            -
            # Without joins
         | 
| 8 | 
            -
            # Before:
         | 
| 9 | 
            -
            #   User.where.contains(data: { nickname: "george" })
         | 
| 10 | 
            -
            #     #=> "SELECT \"people\".* FROM \"people\" WHERE (\"data\".\"nickname\" @> 'george')"
         | 
| 11 | 
            -
            #
         | 
| 12 | 
            -
            # After:
         | 
| 13 | 
            -
            #  User.where.contains(data: { nickname: "george" })
         | 
| 14 | 
            -
            #   #=> "SELECT \"people\".* FROM \"people\" WHERE (\"people\".\"data\" @> '\"nickname\"=>\"george\"')"
         | 
| 15 | 
            -
            #
         | 
| 16 | 
            -
            # With Joins
         | 
| 17 | 
            -
            # Before:
         | 
| 18 | 
            -
            #   Tag.joins(:user).where.contains(people: { data: { nickname: "george" } })
         | 
| 19 | 
            -
            #   #=> NoMethodError: undefined method `type' for nil:NilClass
         | 
| 20 | 
            -
            #
         | 
| 21 | 
            -
            # After:
         | 
| 22 | 
            -
            #  Tag.joins(:user).where.contains(people: { data: { nickname: "george" } })
         | 
| 23 | 
            -
            #  #=> "SELECT \"tags\".* FROM \"tags\" INNER JOIN \"people\" ON \"people\".\"id\" = \"tags\".\"person_id\"
         | 
| 24 | 
            -
            #         WHERE (\"people\".\"data\" @> '\"nickname\"=>\"george\"')"
         | 
| 25 | 
            -
            #
         | 
| 26 | 
            -
            module ActiveRecord
         | 
| 27 | 
            -
              class TableMetadata
         | 
| 28 | 
            -
                def has_column?(column_name) # rubocop:disable Naming/PredicateName
         | 
| 29 | 
            -
                  klass&.columns_hash&.key?(column_name.to_s)
         | 
| 30 | 
            -
                end
         | 
| 31 | 
            -
              end
         | 
| 32 | 
            -
             | 
| 33 | 
            -
              class PredicateBuilder
         | 
| 34 | 
            -
                def create_binds_for_hash(attributes) # rubocop:disable Metrics/PerceivedComplexity, Metrics/AbcSize
         | 
| 35 | 
            -
                  result = attributes.dup
         | 
| 36 | 
            -
                  binds = []
         | 
| 37 | 
            -
             | 
| 38 | 
            -
                  attributes.each do |column_name, value| # rubocop:disable Metrics/BlockLength
         | 
| 39 | 
            -
                    if value.is_a?(Hash) && !table.has_column?(column_name)
         | 
| 40 | 
            -
                      attrs, bvs = associated_predicate_builder(column_name).create_binds_for_hash(value)
         | 
| 41 | 
            -
                      result[column_name] = attrs
         | 
| 42 | 
            -
                      binds += bvs
         | 
| 43 | 
            -
                      next
         | 
| 44 | 
            -
                    elsif value.is_a?(Relation)
         | 
| 45 | 
            -
                      binds += value.bound_attributes
         | 
| 46 | 
            -
                    elsif value.is_a?(Range) && !table.type(column_name).respond_to?(:subtype)
         | 
| 47 | 
            -
                      first = value.begin
         | 
| 48 | 
            -
                      last = value.end
         | 
| 49 | 
            -
                      unless first.respond_to?(:infinite?) && first.infinite?
         | 
| 50 | 
            -
                        binds << build_bind_param(column_name, first)
         | 
| 51 | 
            -
                        first = Arel::Nodes::BindParam.new
         | 
| 52 | 
            -
                      end
         | 
| 53 | 
            -
                      unless last.respond_to?(:infinite?) && last.infinite?
         | 
| 54 | 
            -
                        binds << build_bind_param(column_name, last)
         | 
| 55 | 
            -
                        last = Arel::Nodes::BindParam.new
         | 
| 56 | 
            -
                      end
         | 
| 57 | 
            -
             | 
| 58 | 
            -
                      result[column_name] = RangeHandler::RangeWithBinds.new(first, last, value.exclude_end?)
         | 
| 59 | 
            -
                    elsif can_be_bound?(column_name, value)
         | 
| 60 | 
            -
                      result[column_name] = Arel::Nodes::BindParam.new
         | 
| 61 | 
            -
                      binds << build_bind_param(column_name, value)
         | 
| 62 | 
            -
                    end
         | 
| 63 | 
            -
             | 
| 64 | 
            -
                    # Find the foreign key when using queries such as:
         | 
| 65 | 
            -
                    # Post.where(author: author)
         | 
| 66 | 
            -
                    #
         | 
| 67 | 
            -
                    # For polymorphic relationships, find the foreign key and type:
         | 
| 68 | 
            -
                    # PriceEstimate.where(estimate_of: treasure)
         | 
| 69 | 
            -
                    if table.associated_with?(column_name)
         | 
| 70 | 
            -
                      result[column_name] = AssociationQueryHandler.value_for(table, column_name, value)
         | 
| 71 | 
            -
                    end
         | 
| 72 | 
            -
                  end
         | 
| 73 | 
            -
             | 
| 74 | 
            -
                  [result, binds]
         | 
| 75 | 
            -
                end
         | 
| 76 | 
            -
             | 
| 77 | 
            -
                def can_be_bound?(column_name, value)
         | 
| 78 | 
            -
                  return if table.associated_with?(column_name)
         | 
| 79 | 
            -
                  case value
         | 
| 80 | 
            -
                  when Array, Range
         | 
| 81 | 
            -
                    table.type(column_name).respond_to?(:subtype)
         | 
| 82 | 
            -
                  else
         | 
| 83 | 
            -
                    !value.nil? && handler_for(value).is_a?(BasicObjectHandler)
         | 
| 84 | 
            -
                  end
         | 
| 85 | 
            -
                end
         | 
| 86 | 
            -
              end
         | 
| 87 | 
            -
            end
         |