active_hash_relation 1.2.0 → 1.4.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 +43 -14
- data/lib/active_hash_relation/column_filters.rb +95 -19
- data/lib/active_hash_relation/filter_applier.rb +15 -2
- data/lib/active_hash_relation/sort_filters.rb +10 -2
- data/lib/active_hash_relation/version.rb +1 -1
- data/spec/tests/not_filter_spec.rb +105 -0
- data/spec/tests/sorting_spec.rb +225 -15
- metadata +3 -1
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 3ba8d3aaed9463815f83717410dabf1d47fd2959
         | 
| 4 | 
            +
              data.tar.gz: 14e4eea13e73d7f60ada9f9313a0739e3311fb0f
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 608d20958f7fd3f37e121abbe57c7c4aa546af10112edcd27e47cbc05f0e702139e6cc23e3bced226c7af8eee354d886b779ffb7c7cd385b639d063c7609ad35
         | 
| 7 | 
            +
              data.tar.gz: ebfd652d954d006b0fc13eb4b4b146f95dce213821d52a78f661f7b1a5a80f2a3a9f6723893c5440fae771526bbf45afb36348b47b8d329ef1b0f24db1c781d4
         | 
    
        data/README.md
    CHANGED
    
    | @@ -1,36 +1,38 @@ | |
| 1 1 | 
             
            # ActiveHashRelation
         | 
| 2 2 | 
             
            [ ](https://app.codeship.com/projects/200194)
         | 
| 3 3 |  | 
| 4 | 
            +
            ActiveHashRelation is a complete substitute of ActiveRecord::Relation that allows you to run ActiveRecord queries using only regular Hash using a very powerful yet simple API. It was initially built to allow front-end teams to specify from the API exactly what they need withoug bugging the backend developers, eventually emerged into its own little gem.
         | 
| 5 | 
            +
             | 
| 4 6 | 
             
            ## Introduction
         | 
| 5 7 | 
             
            Simple gem that allows you to manipulate ActiveRecord::Relation using JSON. For instance:
         | 
| 6 8 | 
             
            ```ruby
         | 
| 7 | 
            -
            apply_filters( | 
| 9 | 
            +
            apply_filters(User.all, {name: 'filippos', created_at: {leq: "2016-10-19"}, role: 'regular', email: {like: 'vasilakis'}})
         | 
| 8 10 | 
             
            ```
         | 
| 9 | 
            -
            filter a resource based on it's associations:
         | 
| 11 | 
            +
            filter a resource based on it's associations using a NOT filter:
         | 
| 10 12 | 
             
            ```ruby
         | 
| 11 | 
            -
            apply_filters( | 
| 13 | 
            +
            apply_filters(Microposts.all, {updated_at: { geq: "2014-11-2 14:25:04"}, user: {not: {email: vasilakisfil@gmail.com}})
         | 
| 12 14 | 
             
            ```
         | 
| 13 | 
            -
            or even filter a resource based on it's associations' associations:
         | 
| 15 | 
            +
            or even filter a resource based on it's associations' associations using an OR filter:
         | 
| 14 16 | 
             
            ```ruby
         | 
| 15 | 
            -
            apply_filters( | 
| 17 | 
            +
            apply_filters(Comments.all, {updated_at: { geq: "2014-11-2 14:25:04"}, user: {id: 9, units: {or: [{id: 22}, {id: 21}]} }})
         | 
| 16 18 | 
             
            ```
         | 
| 17 | 
            -
            and the list could go on.. Basically  | 
| 19 | 
            +
            and the list could go on.. Basically you can run anything ActiveRecord supports, except from groupping. It's perfect for filtering a collection of resources on APIs.
         | 
| 18 20 |  | 
| 19 21 | 
             
            It should be noted that `apply_filters` calls `ActiveHashRelation::FilterApplier` class
         | 
| 20 22 | 
             
            underneath with the same params.
         | 
| 21 23 |  | 
| 22 | 
            -
             | 
| 24 | 
            +
            You can also do [__aggregation queries__](#aggregation-queries), like `sum`, `avg`, `min` and `max` on any column.
         | 
| 25 | 
            +
             | 
| 26 | 
            +
            _\*A user could retrieve resources based
         | 
| 23 27 | 
             
            on unknown attributes (attributes not returned from the API) by brute forcing
         | 
| 24 | 
            -
            which might or might not be a security issue. If you don't like that check
         | 
| 25 | 
            -
            [whitelisting](#whitelisting)._
         | 
| 28 | 
            +
            which might or might not be a security issue. If you don't like that check you can specify from the `params` exactly what is allowed and what is not allowed. For more information check: [whitelisting](#whitelisting)._
         | 
| 26 29 |  | 
| 27 | 
            -
            *New*! You can now do [__aggregation queries__](#aggregation-queries).
         | 
| 28 30 |  | 
| 29 31 | 
             
            ## Installation
         | 
| 30 32 |  | 
| 31 33 | 
             
            Add this line to your application's Gemfile:
         | 
| 32 34 |  | 
| 33 | 
            -
                gem 'active_hash_relation', '~> 1. | 
| 35 | 
            +
                gem 'active_hash_relation', '~> 1.3.0
         | 
| 34 36 |  | 
| 35 37 | 
             
            And then execute:
         | 
| 36 38 |  | 
| @@ -61,7 +63,8 @@ class Api::V1::ResourceController < Api::V1::BaseController | |
| 61 63 | 
             
            end
         | 
| 62 64 | 
             
            ```
         | 
| 63 65 |  | 
| 64 | 
            -
            If you **need to enable filtering on scopes**, you need to specify that explicitly from the initializer.  | 
| 66 | 
            +
            If you **need to enable filtering on scopes**, you need to specify that explicitly from the initializer. Please run:
         | 
| 67 | 
            +
            `bundle exec rails g active_hash_relation:initialize` which will create an initializer with the following content:
         | 
| 65 68 |  | 
| 66 69 | 
             
            ```ruby
         | 
| 67 70 | 
             
            ActiveHashRelation.configure do |config|
         | 
| @@ -79,6 +82,7 @@ end | |
| 79 82 | 
             
              #requires monkeyparched scopes, optional if you don't enable them
         | 
| 80 83 | 
             
              ActiveHashRelation.initialize!
         | 
| 81 84 | 
             
            ```
         | 
| 85 | 
            +
            If you are not using Rails, just add the code above in your equivelant initialize block.
         | 
| 82 86 |  | 
| 83 87 | 
             
            ## The API
         | 
| 84 88 | 
             
            ### Columns
         | 
| @@ -140,8 +144,20 @@ However I would strongly advice you to use a pagination gem like Kaminari, and u | |
| 140 144 |  | 
| 141 145 |  | 
| 142 146 | 
             
            ### Sorting
         | 
| 147 | 
            +
            You can apply sorting using the property as the key of the hash and order as the value. For instance:
         | 
| 148 | 
            +
            * `{sort: {created_at: desc}}`
         | 
| 149 | 
            +
             | 
| 150 | 
            +
            You can also order by multiple attributes:
         | 
| 151 | 
            +
            * `{sort: {created_at: desc, microposts_count: :asc}}`
         | 
| 152 | 
            +
             | 
| 153 | 
            +
            If there is no column named after the property value, sorting is skipped.
         | 
| 154 | 
            +
             | 
| 155 | 
            +
            #### Deprecated API (will be removed in version 2.0)
         | 
| 143 156 | 
             
            You can apply sorting using the `property` and `order` attributes. For instance:
         | 
| 144 | 
            -
            * `{sort: {property:  | 
| 157 | 
            +
            * `{sort: {property: :created_at, order: :desc}}`
         | 
| 158 | 
            +
             | 
| 159 | 
            +
            You can also order by multiple attributes:
         | 
| 160 | 
            +
            * `{sort: [{property: :created_at, order: :desc}, {property: :created_at, order: :desc}]}`
         | 
| 145 161 |  | 
| 146 162 | 
             
            If there is no column named after the property value, sorting is skipped.
         | 
| 147 163 |  | 
| @@ -174,8 +190,21 @@ You can apply an `OR` on associations as well or even nested ones, there isn't m | |
| 174 190 | 
             
            I suggest you though to take a look on the [tests](spec/tests/or_filter_spec.rb), cause the syntax gets a bit complex after a while ;)
         | 
| 175 191 |  | 
| 176 192 |  | 
| 193 | 
            +
            ### NOT Filter
         | 
| 194 | 
            +
            You can apply an SQL `NOT` (for ActiveRecord 4+) using the following syntax:
         | 
| 195 | 
            +
            `{not: {name: 'Filippos', email: {ends_with: '@gmail.com'}}}`
         | 
| 196 | 
            +
             | 
| 197 | 
            +
            It will generate: `WHERE (NOT (users.name = 'Filippos')) AND (NOT (users.email LIKE '%@gmail.com'))`
         | 
| 198 | 
            +
             | 
| 199 | 
            +
            You can apply an `NOT` on associations as well or even nested ones, there isn't much limitation on that.
         | 
| 200 | 
            +
            I suggest you to also take a look on the [tests](spec/tests/not_filter_spec.rb).
         | 
| 201 | 
            +
             | 
| 202 | 
            +
            Also I should note that you need to add specific (partial) queries if you don't want
         | 
| 203 | 
            +
            to have performance issues on tables with millions of rows.
         | 
| 204 | 
            +
             | 
| 205 | 
            +
             | 
| 177 206 | 
             
            ### Scopes
         | 
| 178 | 
            -
            **Filtering on scopes is not enabled by default | 
| 207 | 
            +
            **Filtering on scopes is not enabled by default. You need to add the initializer mentioned in the beginning of the [How to use](#how-to-use) section.**.
         | 
| 179 208 |  | 
| 180 209 | 
             
            Scopes are supported via a tiny monkeypatch in the ActiveRecord's scope class method which holds the name of each scope.
         | 
| 181 210 | 
             
            The monkey patch is as gentle as it can be: it aliases the method, adds some sugar and executes it.
         | 
| @@ -2,7 +2,11 @@ module ActiveHashRelation::ColumnFilters | |
| 2 2 | 
             
              def filter_integer(resource, column, table_name, param)
         | 
| 3 3 | 
             
                if param.is_a? Array
         | 
| 4 4 | 
             
                  n_param = param.to_s.gsub("\"","'").gsub("[","").gsub("]","") #fix this!
         | 
| 5 | 
            -
                   | 
| 5 | 
            +
                  if @is_not
         | 
| 6 | 
            +
                    return resource.where.not("#{table_name}.#{column} IN (#{n_param})")
         | 
| 7 | 
            +
                  else
         | 
| 8 | 
            +
                    return resource.where("#{table_name}.#{column} IN (#{n_param})")
         | 
| 9 | 
            +
                  end
         | 
| 6 10 | 
             
                elsif param.is_a? Hash
         | 
| 7 11 | 
             
                  if !param[:null].nil?
         | 
| 8 12 | 
             
                    return null_filters(resource, table_name, column, param)
         | 
| @@ -10,7 +14,11 @@ module ActiveHashRelation::ColumnFilters | |
| 10 14 | 
             
                    return apply_leq_geq_le_ge_filters(resource, table_name, column, param)
         | 
| 11 15 | 
             
                  end
         | 
| 12 16 | 
             
                else
         | 
| 13 | 
            -
                   | 
| 17 | 
            +
                  if @is_not
         | 
| 18 | 
            +
                    return resource.where.not("#{table_name}.#{column} = ?", param)
         | 
| 19 | 
            +
                  else
         | 
| 20 | 
            +
                    return resource.where("#{table_name}.#{column} = ?", param)
         | 
| 21 | 
            +
                  end
         | 
| 14 22 | 
             
                end
         | 
| 15 23 | 
             
              end
         | 
| 16 24 |  | 
| @@ -25,7 +33,11 @@ module ActiveHashRelation::ColumnFilters | |
| 25 33 | 
             
              def filter_string(resource, column, table_name, param)
         | 
| 26 34 | 
             
                if param.is_a? Array
         | 
| 27 35 | 
             
                  n_param = param.to_s.gsub("\"","'").gsub("[","").gsub("]","") #fix this!
         | 
| 28 | 
            -
                   | 
| 36 | 
            +
                  if @is_not
         | 
| 37 | 
            +
                    return resource.where.not("#{table_name}.#{column} IN (#{n_param})")
         | 
| 38 | 
            +
                  else
         | 
| 39 | 
            +
                    return resource.where("#{table_name}.#{column} IN (#{n_param})")
         | 
| 40 | 
            +
                  end
         | 
| 29 41 | 
             
                elsif param.is_a? Hash
         | 
| 30 42 | 
             
                  if !param[:null].nil?
         | 
| 31 43 | 
             
                    return null_filters(resource, table_name, column, param)
         | 
| @@ -33,7 +45,11 @@ module ActiveHashRelation::ColumnFilters | |
| 33 45 | 
             
                    return apply_like_filters(resource, table_name, column, param)
         | 
| 34 46 | 
             
                  end
         | 
| 35 47 | 
             
                else
         | 
| 36 | 
            -
                   | 
| 48 | 
            +
                  if @is_not
         | 
| 49 | 
            +
                    return resource.where.not("#{table_name}.#{column} = ?", param)
         | 
| 50 | 
            +
                  else
         | 
| 51 | 
            +
                    return resource.where("#{table_name}.#{column} = ?", param)
         | 
| 52 | 
            +
                  end
         | 
| 37 53 | 
             
                end
         | 
| 38 54 | 
             
              end
         | 
| 39 55 |  | 
| @@ -44,7 +60,11 @@ module ActiveHashRelation::ColumnFilters | |
| 44 60 | 
             
              def filter_date(resource, column, table_name, param)
         | 
| 45 61 | 
             
                if param.is_a? Array
         | 
| 46 62 | 
             
                  n_param = param.to_s.gsub("\"","'").gsub("[","").gsub("]","") #fix this!
         | 
| 47 | 
            -
                   | 
| 63 | 
            +
                  if @is_not
         | 
| 64 | 
            +
                    return resource.where.not("#{table_name}.#{column} IN (#{n_param})")
         | 
| 65 | 
            +
                  else
         | 
| 66 | 
            +
                    return resource.where("#{table_name}.#{column} IN (#{n_param})")
         | 
| 67 | 
            +
                  end
         | 
| 48 68 | 
             
                elsif param.is_a? Hash
         | 
| 49 69 | 
             
                  if !param[:null].nil?
         | 
| 50 70 | 
             
                    return null_filters(resource, table_name, column, param)
         | 
| @@ -52,7 +72,11 @@ module ActiveHashRelation::ColumnFilters | |
| 52 72 | 
             
                    return apply_leq_geq_le_ge_filters(resource, table_name, column, param)
         | 
| 53 73 | 
             
                  end
         | 
| 54 74 | 
             
                else
         | 
| 55 | 
            -
                   | 
| 75 | 
            +
                  if @is_not
         | 
| 76 | 
            +
                    resource = resource.where.not(column => param)
         | 
| 77 | 
            +
                  else
         | 
| 78 | 
            +
                    resource = resource.where(column => param)
         | 
| 79 | 
            +
                  end
         | 
| 56 80 | 
             
                end
         | 
| 57 81 |  | 
| 58 82 | 
             
                return resource
         | 
| @@ -61,7 +85,11 @@ module ActiveHashRelation::ColumnFilters | |
| 61 85 | 
             
              def filter_datetime(resource, column, table_name, param)
         | 
| 62 86 | 
             
                if param.is_a? Array
         | 
| 63 87 | 
             
                  n_param = param.to_s.gsub("\"","'").gsub("[","").gsub("]","") #fix this!
         | 
| 64 | 
            -
                   | 
| 88 | 
            +
                  if @is_not
         | 
| 89 | 
            +
                    return resource = resource.where.not("#{table_name}.#{column} IN (#{n_param})")
         | 
| 90 | 
            +
                  else
         | 
| 91 | 
            +
                    return resource = resource.where("#{table_name}.#{column} IN (#{n_param})")
         | 
| 92 | 
            +
                  end
         | 
| 65 93 | 
             
                elsif param.is_a? Hash
         | 
| 66 94 | 
             
                  if !param[:null].nil?
         | 
| 67 95 | 
             
                    return null_filters(resource, table_name, column, param)
         | 
| @@ -69,7 +97,11 @@ module ActiveHashRelation::ColumnFilters | |
| 69 97 | 
             
                    return apply_leq_geq_le_ge_filters(resource, table_name, column, param)
         | 
| 70 98 | 
             
                  end
         | 
| 71 99 | 
             
                else
         | 
| 72 | 
            -
                   | 
| 100 | 
            +
                  if @is_not
         | 
| 101 | 
            +
                    resource = resource.where.not(column => param)
         | 
| 102 | 
            +
                  else
         | 
| 103 | 
            +
                    resource = resource.where(column => param)
         | 
| 104 | 
            +
                  end
         | 
| 73 105 | 
             
                end
         | 
| 74 106 |  | 
| 75 107 | 
             
                return resource
         | 
| @@ -85,7 +117,11 @@ module ActiveHashRelation::ColumnFilters | |
| 85 117 | 
             
                    b_param = ActiveRecord::Type::Boolean.new.type_cast_from_database(param)
         | 
| 86 118 | 
             
                  end
         | 
| 87 119 |  | 
| 88 | 
            -
                   | 
| 120 | 
            +
                  if @is_not
         | 
| 121 | 
            +
                    resource = resource.where.not(column => b_param)
         | 
| 122 | 
            +
                  else
         | 
| 123 | 
            +
                    resource = resource.where(column => b_param)
         | 
| 124 | 
            +
                  end
         | 
| 89 125 | 
             
                end
         | 
| 90 126 | 
             
              end
         | 
| 91 127 |  | 
| @@ -95,15 +131,31 @@ module ActiveHashRelation::ColumnFilters | |
| 95 131 | 
             
                return resource.where("#{table_name}.#{column} = ?", param[:eq]) if param[:eq]
         | 
| 96 132 |  | 
| 97 133 | 
             
                if !param[:leq].blank?
         | 
| 98 | 
            -
                   | 
| 134 | 
            +
                  if @is_not
         | 
| 135 | 
            +
                    resource = resource.where.not("#{table_name}.#{column} <= ?", param[:leq])
         | 
| 136 | 
            +
                  else
         | 
| 137 | 
            +
                    resource = resource.where("#{table_name}.#{column} <= ?", param[:leq])
         | 
| 138 | 
            +
                  end
         | 
| 99 139 | 
             
                elsif !param[:le].blank?
         | 
| 100 | 
            -
                   | 
| 140 | 
            +
                  if @is_not
         | 
| 141 | 
            +
                    resource = resource.where.not("#{table_name}.#{column} < ?", param[:le])
         | 
| 142 | 
            +
                  else
         | 
| 143 | 
            +
                    resource = resource.where("#{table_name}.#{column} < ?", param[:le])
         | 
| 144 | 
            +
                  end
         | 
| 101 145 | 
             
                end
         | 
| 102 146 |  | 
| 103 147 | 
             
                if !param[:geq].blank?
         | 
| 104 | 
            -
                   | 
| 148 | 
            +
                  if @is_not
         | 
| 149 | 
            +
                    resource = resource.where.not("#{table_name}.#{column} >= ?", param[:geq])
         | 
| 150 | 
            +
                  else
         | 
| 151 | 
            +
                    resource = resource.where("#{table_name}.#{column} >= ?", param[:geq])
         | 
| 152 | 
            +
                  end
         | 
| 105 153 | 
             
                elsif !param[:ge].blank?
         | 
| 106 | 
            -
                   | 
| 154 | 
            +
                  if @is_not
         | 
| 155 | 
            +
                    resource = resource.where.not("#{table_name}.#{column} > ?", param[:ge])
         | 
| 156 | 
            +
                  else
         | 
| 157 | 
            +
                    resource = resource.where("#{table_name}.#{column} > ?", param[:ge])
         | 
| 158 | 
            +
                  end
         | 
| 107 159 | 
             
                end
         | 
| 108 160 |  | 
| 109 161 | 
             
                return resource
         | 
| @@ -114,19 +166,35 @@ module ActiveHashRelation::ColumnFilters | |
| 114 166 | 
             
                like_method = "ILIKE" if param[:with_ilike]
         | 
| 115 167 |  | 
| 116 168 | 
             
                if !param[:starts_with].blank?
         | 
| 117 | 
            -
                   | 
| 169 | 
            +
                  if @is_not
         | 
| 170 | 
            +
                    resource = resource.where.not("#{table_name}.#{column} #{like_method} ?", "#{param[:starts_with]}%")
         | 
| 171 | 
            +
                  else
         | 
| 172 | 
            +
                    resource = resource.where("#{table_name}.#{column} #{like_method} ?", "#{param[:starts_with]}%")
         | 
| 173 | 
            +
                  end
         | 
| 118 174 | 
             
                end
         | 
| 119 175 |  | 
| 120 176 | 
             
                if !param[:ends_with].blank?
         | 
| 121 | 
            -
                   | 
| 177 | 
            +
                  if @is_not
         | 
| 178 | 
            +
                    resource = resource.where.not("#{table_name}.#{column} #{like_method} ?", "%#{param[:ends_with]}")
         | 
| 179 | 
            +
                  else
         | 
| 180 | 
            +
                    resource = resource.where("#{table_name}.#{column} #{like_method} ?", "%#{param[:ends_with]}")
         | 
| 181 | 
            +
                  end
         | 
| 122 182 | 
             
                end
         | 
| 123 183 |  | 
| 124 184 | 
             
                if !param[:like].blank?
         | 
| 125 | 
            -
                   | 
| 185 | 
            +
                  if @is_not
         | 
| 186 | 
            +
                    resource = resource.where.not("#{table_name}.#{column} #{like_method} ?", "%#{param[:like]}%")
         | 
| 187 | 
            +
                  else
         | 
| 188 | 
            +
                    resource = resource.where("#{table_name}.#{column} #{like_method} ?", "%#{param[:like]}%")
         | 
| 189 | 
            +
                  end
         | 
| 126 190 | 
             
                end
         | 
| 127 191 |  | 
| 128 192 | 
             
                if !param[:eq].blank?
         | 
| 129 | 
            -
                   | 
| 193 | 
            +
                  if @is_not
         | 
| 194 | 
            +
                    resource = resource.where.not("#{table_name}.#{column} = ?", param[:eq])
         | 
| 195 | 
            +
                  else
         | 
| 196 | 
            +
                    resource = resource.where("#{table_name}.#{column} = ?", param[:eq])
         | 
| 197 | 
            +
                  end
         | 
| 130 198 | 
             
                end
         | 
| 131 199 |  | 
| 132 200 | 
             
                return resource
         | 
| @@ -134,11 +202,19 @@ module ActiveHashRelation::ColumnFilters | |
| 134 202 |  | 
| 135 203 | 
             
              def null_filters(resource, table_name, column, param)
         | 
| 136 204 | 
             
                if param[:null] == true
         | 
| 137 | 
            -
                   | 
| 205 | 
            +
                  if @is_not
         | 
| 206 | 
            +
                    resource = resource.where.not("#{table_name}.#{column} IS NULL")
         | 
| 207 | 
            +
                  else
         | 
| 208 | 
            +
                    resource = resource.where("#{table_name}.#{column} IS NULL")
         | 
| 209 | 
            +
                  end
         | 
| 138 210 | 
             
                end
         | 
| 139 211 |  | 
| 140 212 | 
             
                if param[:null] == false
         | 
| 141 | 
            -
                   | 
| 213 | 
            +
                  if @is_not
         | 
| 214 | 
            +
                    resource = resource.where.not("#{table_name}.#{column} IS NOT NULL")
         | 
| 215 | 
            +
                  else
         | 
| 216 | 
            +
                    resource = resource.where("#{table_name}.#{column} IS NOT NULL")
         | 
| 217 | 
            +
                  end
         | 
| 142 218 | 
             
                end
         | 
| 143 219 |  | 
| 144 220 | 
             
                return resource
         | 
| @@ -9,7 +9,7 @@ module ActiveHashRelation | |
| 9 9 |  | 
| 10 10 | 
             
                attr_reader :configuration
         | 
| 11 11 |  | 
| 12 | 
            -
                def initialize(resource, params, include_associations: false, model: nil)
         | 
| 12 | 
            +
                def initialize(resource, params, include_associations: false, model: nil, is_not: false)
         | 
| 13 13 | 
             
                  @configuration = Module.nesting.last.configuration
         | 
| 14 14 | 
             
                  @resource = resource
         | 
| 15 15 | 
             
                  if params.respond_to?(:to_unsafe_h)
         | 
| @@ -19,10 +19,12 @@ module ActiveHashRelation | |
| 19 19 | 
             
                  end
         | 
| 20 20 | 
             
                  @include_associations = include_associations
         | 
| 21 21 | 
             
                  @model = find_model(model)
         | 
| 22 | 
            +
                  is_not ? @is_not = true : @is_not = false
         | 
| 22 23 | 
             
                end
         | 
| 23 24 |  | 
| 24 25 | 
             
                def apply_filters
         | 
| 25 26 | 
             
                  run_or_filters
         | 
| 27 | 
            +
                  run_not_filters
         | 
| 26 28 |  | 
| 27 29 | 
             
                  table_name = @model.table_name
         | 
| 28 30 | 
             
                  @model.columns.each do |c|
         | 
| @@ -68,7 +70,7 @@ module ActiveHashRelation | |
| 68 70 | 
             
                def run_or_filters
         | 
| 69 71 | 
             
                  if @params[:or].is_a?(Array)
         | 
| 70 72 | 
             
                    if ActiveRecord::VERSION::MAJOR < 5
         | 
| 71 | 
            -
                      return Rails.logger.warn("OR query is supported on ActiveRecord 5+") | 
| 73 | 
            +
                      return Rails.logger.warn("OR query is supported on ActiveRecord 5+")
         | 
| 72 74 | 
             
                    end
         | 
| 73 75 |  | 
| 74 76 | 
             
                    if @params[:or].length >= 2
         | 
| @@ -83,5 +85,16 @@ module ActiveHashRelation | |
| 83 85 | 
             
                    end
         | 
| 84 86 | 
             
                  end
         | 
| 85 87 | 
             
                end
         | 
| 88 | 
            +
             | 
| 89 | 
            +
                def run_not_filters
         | 
| 90 | 
            +
                  if @params[:not].is_a?(Hash) && !@params[:not].blank?
         | 
| 91 | 
            +
                    @resource = self.class.new(
         | 
| 92 | 
            +
                      @resource,
         | 
| 93 | 
            +
                      @params[:not],
         | 
| 94 | 
            +
                      include_associations: @include_associations,
         | 
| 95 | 
            +
                      is_not: true
         | 
| 96 | 
            +
                    ).apply_filters
         | 
| 97 | 
            +
                  end
         | 
| 98 | 
            +
                end
         | 
| 86 99 | 
             
              end
         | 
| 87 100 | 
             
            end
         | 
| @@ -12,8 +12,16 @@ module ActiveHashRelation::SortFilters | |
| 12 12 | 
             
              end
         | 
| 13 13 |  | 
| 14 14 | 
             
              def apply_hash_sort(resource, params, model = nil)
         | 
| 15 | 
            -
                if  | 
| 16 | 
            -
                   | 
| 15 | 
            +
                if not params[:property].blank?
         | 
| 16 | 
            +
                  if model.columns.map(&:name).include?(params[:property].to_s)
         | 
| 17 | 
            +
                    resource = resource.order(params[:property] => (params[:order] || :desc) )
         | 
| 18 | 
            +
                  end
         | 
| 19 | 
            +
                else
         | 
| 20 | 
            +
                  params.each do |property, order|
         | 
| 21 | 
            +
                    if model.columns.map(&:name).include?(property.to_s)
         | 
| 22 | 
            +
                      resource = resource.order(property => (order || :desc) )
         | 
| 23 | 
            +
                    end
         | 
| 24 | 
            +
                  end
         | 
| 17 25 | 
             
                end
         | 
| 18 26 |  | 
| 19 27 | 
             
                return resource
         | 
| @@ -0,0 +1,105 @@ | |
| 1 | 
            +
            describe ActiveHashRelation do
         | 
| 2 | 
            +
              include Helpers
         | 
| 3 | 
            +
             | 
| 4 | 
            +
              context 'NOT filter' do
         | 
| 5 | 
            +
                it "one NOT clause" do
         | 
| 6 | 
            +
                  hash = {not: {name: 'Filippos'}}
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                  query = HelperClass.new.apply_filters(User.all, hash).to_sql
         | 
| 9 | 
            +
                  expected_query = q(
         | 
| 10 | 
            +
                    "SELECT users.* FROM users WHERE (NOT (users.name = 'Filippos'))"
         | 
| 11 | 
            +
                  )
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                  expect(strip(query)).to eq expected_query.to_s
         | 
| 14 | 
            +
                end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                it "multiple NOT clauses" do
         | 
| 17 | 
            +
                  hash = {not: {name: 'Filippos', email: 'vasilakisfil@gmail.com'}}
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                  query = HelperClass.new.apply_filters(User.all, hash).to_sql
         | 
| 20 | 
            +
                  expected_query = q(
         | 
| 21 | 
            +
                    "SELECT users.* FROM users WHERE",
         | 
| 22 | 
            +
                    "(NOT (users.name = 'Filippos'))",
         | 
| 23 | 
            +
                    "AND",
         | 
| 24 | 
            +
                    "(NOT (users.email = 'vasilakisfil@gmail.com'))"
         | 
| 25 | 
            +
                  )
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                  expect(strip(query)).to eq expected_query.to_s
         | 
| 28 | 
            +
                end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                if ActiveRecord::VERSION::MAJOR >= 5
         | 
| 31 | 
            +
                  it "NOT clause inside OR clause" do
         | 
| 32 | 
            +
                    hash = {or: [{not: {name: 'Filippos', token: '123'}}, {not: {name: 'Vasilis'}}]}
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                    query = HelperClass.new.apply_filters(User.all, hash).to_sql
         | 
| 35 | 
            +
                    expected_query = q(
         | 
| 36 | 
            +
                      "SELECT users.* FROM users",
         | 
| 37 | 
            +
                      "WHERE",
         | 
| 38 | 
            +
                      "(",
         | 
| 39 | 
            +
                        "(NOT (users.name = 'Filippos')) AND (NOT (users.token = '123'))",
         | 
| 40 | 
            +
                        "OR",
         | 
| 41 | 
            +
                        "(NOT (users.name = 'Vasilis'))",
         | 
| 42 | 
            +
                      ")"
         | 
| 43 | 
            +
                    )
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                    expect(strip(query)).to eq expected_query.to_s
         | 
| 46 | 
            +
                  end
         | 
| 47 | 
            +
                end
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                it "complex NOT clause" do
         | 
| 50 | 
            +
                  hash = {not: {name: 'Filippos', email: {ends_with: '@gmail.com'}}}
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                  query = HelperClass.new.apply_filters(User.all, hash).to_sql
         | 
| 53 | 
            +
                  expected_query = q(
         | 
| 54 | 
            +
                    "SELECT users.* FROM users",
         | 
| 55 | 
            +
                    "WHERE",
         | 
| 56 | 
            +
                    "(NOT (users.name = 'Filippos'))",
         | 
| 57 | 
            +
                    "AND",
         | 
| 58 | 
            +
                    "(NOT (users.email LIKE '%@gmail.com'))",
         | 
| 59 | 
            +
                  )
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                  expect(strip(query)).to eq expected_query.to_s
         | 
| 62 | 
            +
                end
         | 
| 63 | 
            +
             | 
| 64 | 
            +
                context "on NULL" do
         | 
| 65 | 
            +
                  it "NOT clause on null" do
         | 
| 66 | 
            +
                    hash = {not: {name: {null: true}}}
         | 
| 67 | 
            +
             | 
| 68 | 
            +
                    query = HelperClass.new.apply_filters(User.all, hash).to_sql
         | 
| 69 | 
            +
                    expected_query = q(
         | 
| 70 | 
            +
                      "SELECT users.* FROM users WHERE (NOT (users.name IS NULL))"
         | 
| 71 | 
            +
                    )
         | 
| 72 | 
            +
             | 
| 73 | 
            +
                    expect(strip(query)).to eq expected_query.to_s
         | 
| 74 | 
            +
                  end
         | 
| 75 | 
            +
             | 
| 76 | 
            +
                  it "NOT clause on not null" do
         | 
| 77 | 
            +
                    hash = {not: {name: {null: false}}}
         | 
| 78 | 
            +
             | 
| 79 | 
            +
                    query = HelperClass.new.apply_filters(User.all, hash).to_sql
         | 
| 80 | 
            +
                    expected_query = q(
         | 
| 81 | 
            +
                      "SELECT users.* FROM users WHERE (NOT (users.name IS NOT NULL))"
         | 
| 82 | 
            +
                    )
         | 
| 83 | 
            +
             | 
| 84 | 
            +
                    expect(strip(query)).to eq expected_query.to_s
         | 
| 85 | 
            +
                  end
         | 
| 86 | 
            +
                end
         | 
| 87 | 
            +
             | 
| 88 | 
            +
                it "NOT clause on associations" do
         | 
| 89 | 
            +
                    hash = {microposts: {not: {content: 'Sveavägen 4', id: 1}}}
         | 
| 90 | 
            +
             | 
| 91 | 
            +
                    query = HelperClass.new.apply_filters(User.all, hash, include_associations: true).to_sql
         | 
| 92 | 
            +
                    expected_query = q(
         | 
| 93 | 
            +
                      "SELECT users.* FROM users",
         | 
| 94 | 
            +
                      "INNER JOIN microposts ON microposts.user_id = users.id",
         | 
| 95 | 
            +
                      "WHERE",
         | 
| 96 | 
            +
                      "(NOT (microposts.id = 1))",
         | 
| 97 | 
            +
                      "AND",
         | 
| 98 | 
            +
                      "(NOT (microposts.content = 'Sveavägen 4'))"
         | 
| 99 | 
            +
                    )
         | 
| 100 | 
            +
             | 
| 101 | 
            +
                    expect(strip(query)).to eq expected_query.to_s
         | 
| 102 | 
            +
                end
         | 
| 103 | 
            +
             | 
| 104 | 
            +
              end
         | 
| 105 | 
            +
            end
         | 
    
        data/spec/tests/sorting_spec.rb
    CHANGED
    
    | @@ -2,11 +2,12 @@ describe ActiveHashRelation do | |
| 2 2 | 
             
              include Helpers
         | 
| 3 3 |  | 
| 4 4 | 
             
              context 'sorting' do
         | 
| 5 | 
            +
             | 
| 5 6 | 
             
                context "one where clause" do
         | 
| 6 7 | 
             
                  it "asc" do
         | 
| 7 8 | 
             
                    hash = {
         | 
| 8 9 | 
             
                      microposts_count: 10,
         | 
| 9 | 
            -
                      sort: { | 
| 10 | 
            +
                      sort: {microposts_count: :asc}
         | 
| 10 11 | 
             
                    }
         | 
| 11 12 |  | 
| 12 13 | 
             
                    query = HelperClass.new.apply_filters(User.all, hash).to_sql
         | 
| @@ -19,10 +20,10 @@ describe ActiveHashRelation do | |
| 19 20 | 
             
                    expect(strip(query)).to eq expected_query.to_s
         | 
| 20 21 | 
             
                  end
         | 
| 21 22 |  | 
| 22 | 
            -
                  it " | 
| 23 | 
            +
                  it "desc" do
         | 
| 23 24 | 
             
                      hash = {
         | 
| 24 25 | 
             
                        microposts_count: 10,
         | 
| 25 | 
            -
                        sort: { | 
| 26 | 
            +
                        sort: {microposts_count: :desc}
         | 
| 26 27 | 
             
                      }
         | 
| 27 28 |  | 
| 28 29 | 
             
                      query = HelperClass.new.apply_filters(User.all, hash).to_sql
         | 
| @@ -41,7 +42,7 @@ describe ActiveHashRelation do | |
| 41 42 | 
             
                    hash = {
         | 
| 42 43 | 
             
                      followers_count: {leq: 20},
         | 
| 43 44 | 
             
                      microposts_count: 10,
         | 
| 44 | 
            -
                      sort: { | 
| 45 | 
            +
                      sort: {microposts_count: :asc}
         | 
| 45 46 | 
             
                    }
         | 
| 46 47 |  | 
| 47 48 | 
             
                    query = HelperClass.new.apply_filters(User.all, hash).to_sql
         | 
| @@ -55,11 +56,11 @@ describe ActiveHashRelation do | |
| 55 56 | 
             
                    expect(strip(query)).to eq expected_query.to_s
         | 
| 56 57 | 
             
                  end
         | 
| 57 58 |  | 
| 58 | 
            -
                  it " | 
| 59 | 
            +
                  it "desc" do
         | 
| 59 60 | 
             
                    hash = {
         | 
| 60 61 | 
             
                    followers_count: {leq: 20},
         | 
| 61 62 | 
             
                      microposts_count: 10,
         | 
| 62 | 
            -
                      sort: { | 
| 63 | 
            +
                      sort: {microposts_count: :desc}
         | 
| 63 64 | 
             
                    }
         | 
| 64 65 |  | 
| 65 66 | 
             
                    query = HelperClass.new.apply_filters(User.all, hash).to_sql
         | 
| @@ -75,26 +76,235 @@ describe ActiveHashRelation do | |
| 75 76 | 
             
                end
         | 
| 76 77 |  | 
| 77 78 | 
             
                context "multiple sorting properties" do
         | 
| 78 | 
            -
                   | 
| 79 | 
            +
                  context "as a hashe" do
         | 
| 80 | 
            +
                    it "with single where clause" do
         | 
| 81 | 
            +
                      hash = {
         | 
| 82 | 
            +
                        microposts_count: 10,
         | 
| 83 | 
            +
                        sort: {
         | 
| 84 | 
            +
                          microposts_count: :asc,
         | 
| 85 | 
            +
                          followings_count: :desc
         | 
| 86 | 
            +
                        }
         | 
| 87 | 
            +
                      }
         | 
| 88 | 
            +
             | 
| 89 | 
            +
                      query = HelperClass.new.apply_filters(User.all, hash).to_sql
         | 
| 90 | 
            +
                      expected_query = q(
         | 
| 91 | 
            +
                        "SELECT users.* FROM users",
         | 
| 92 | 
            +
                        "WHERE (users.microposts_count = 10)",
         | 
| 93 | 
            +
                        "ORDER BY users.microposts_count ASC, users.followings_count DESC"
         | 
| 94 | 
            +
                      )
         | 
| 95 | 
            +
             | 
| 96 | 
            +
                      expect(strip(query)).to eq expected_query.to_s
         | 
| 97 | 
            +
                    end
         | 
| 98 | 
            +
             | 
| 99 | 
            +
                    it "when the sorting column does not exist" do
         | 
| 100 | 
            +
                      hash = {
         | 
| 101 | 
            +
                        microposts_count: 10,
         | 
| 102 | 
            +
                        sort: {
         | 
| 103 | 
            +
                          i_do_not_exist: :asc,
         | 
| 104 | 
            +
                          followings_count: :desc
         | 
| 105 | 
            +
                        }
         | 
| 106 | 
            +
                      }
         | 
| 107 | 
            +
             | 
| 108 | 
            +
                      query = HelperClass.new.apply_filters(User.all, hash).to_sql
         | 
| 109 | 
            +
                      expected_query = q(
         | 
| 110 | 
            +
                        "SELECT users.* FROM users",
         | 
| 111 | 
            +
                        "WHERE (users.microposts_count = 10)",
         | 
| 112 | 
            +
                        "ORDER BY users.followings_count DESC"
         | 
| 113 | 
            +
                      )
         | 
| 114 | 
            +
             | 
| 115 | 
            +
                      expect(strip(query)).to eq expected_query.to_s
         | 
| 116 | 
            +
                    end
         | 
| 117 | 
            +
                  end
         | 
| 118 | 
            +
             | 
| 119 | 
            +
                  context "as an array of hashes (not recommended)" do
         | 
| 120 | 
            +
                    it "with single where clause" do
         | 
| 121 | 
            +
                      hash = {
         | 
| 122 | 
            +
                        microposts_count: 10,
         | 
| 123 | 
            +
                        sort: [{
         | 
| 124 | 
            +
                          microposts_count: :asc,
         | 
| 125 | 
            +
                        }, {
         | 
| 126 | 
            +
                          followings_count: :desc
         | 
| 127 | 
            +
                        }]
         | 
| 128 | 
            +
                      }
         | 
| 129 | 
            +
             | 
| 130 | 
            +
                      query = HelperClass.new.apply_filters(User.all, hash).to_sql
         | 
| 131 | 
            +
                      expected_query = q(
         | 
| 132 | 
            +
                        "SELECT users.* FROM users",
         | 
| 133 | 
            +
                        "WHERE (users.microposts_count = 10)",
         | 
| 134 | 
            +
                        "ORDER BY users.microposts_count ASC, users.followings_count DESC"
         | 
| 135 | 
            +
                      )
         | 
| 136 | 
            +
             | 
| 137 | 
            +
                      expect(strip(query)).to eq expected_query.to_s
         | 
| 138 | 
            +
                    end
         | 
| 139 | 
            +
             | 
| 140 | 
            +
                    it "when the sorting column does not exist" do
         | 
| 141 | 
            +
                      hash = {
         | 
| 142 | 
            +
                        microposts_count: 10,
         | 
| 143 | 
            +
                        sort: [{
         | 
| 144 | 
            +
                          i_do_not_exist: :asc,
         | 
| 145 | 
            +
                        }, {
         | 
| 146 | 
            +
                          followings_count: :desc
         | 
| 147 | 
            +
                        }]
         | 
| 148 | 
            +
                      }
         | 
| 149 | 
            +
             | 
| 150 | 
            +
                      query = HelperClass.new.apply_filters(User.all, hash).to_sql
         | 
| 151 | 
            +
                      expected_query = q(
         | 
| 152 | 
            +
                        "SELECT users.* FROM users",
         | 
| 153 | 
            +
                        "WHERE (users.microposts_count = 10)",
         | 
| 154 | 
            +
                        "ORDER BY users.followings_count DESC"
         | 
| 155 | 
            +
                      )
         | 
| 156 | 
            +
             | 
| 157 | 
            +
                      expect(strip(query)).to eq expected_query.to_s
         | 
| 158 | 
            +
                    end
         | 
| 159 | 
            +
                  end
         | 
| 160 | 
            +
             | 
| 161 | 
            +
                  it "when the sorting column does not exist" do
         | 
| 79 162 | 
             
                    hash = {
         | 
| 80 163 | 
             
                      microposts_count: 10,
         | 
| 81 | 
            -
                      sort:  | 
| 82 | 
            -
                        property: :microposts_count, order: :asc,
         | 
| 83 | 
            -
                      }, {
         | 
| 84 | 
            -
                        property: :followings_count, order: :desc
         | 
| 85 | 
            -
                      }]
         | 
| 164 | 
            +
                      sort: {i_do_not_exist: :asc}
         | 
| 86 165 | 
             
                    }
         | 
| 87 166 |  | 
| 88 167 | 
             
                    query = HelperClass.new.apply_filters(User.all, hash).to_sql
         | 
| 89 168 | 
             
                    expected_query = q(
         | 
| 90 169 | 
             
                      "SELECT users.* FROM users",
         | 
| 91 | 
            -
                      "WHERE (users.microposts_count = 10)" | 
| 92 | 
            -
                      "ORDER BY users.microposts_count ASC, users.followings_count DESC"
         | 
| 170 | 
            +
                      "WHERE (users.microposts_count = 10)"
         | 
| 93 171 | 
             
                    )
         | 
| 94 172 |  | 
| 95 173 | 
             
                    expect(strip(query)).to eq expected_query.to_s
         | 
| 174 | 
            +
             | 
| 96 175 | 
             
                  end
         | 
| 97 176 | 
             
                end
         | 
| 98 | 
            -
              end
         | 
| 99 177 |  | 
| 178 | 
            +
                context "deprecated API" do
         | 
| 179 | 
            +
                  context "one where clause" do
         | 
| 180 | 
            +
                    it "asc" do
         | 
| 181 | 
            +
                      hash = {
         | 
| 182 | 
            +
                        microposts_count: 10,
         | 
| 183 | 
            +
                        sort: {property: :microposts_count, order: :asc}
         | 
| 184 | 
            +
                      }
         | 
| 185 | 
            +
             | 
| 186 | 
            +
                      query = HelperClass.new.apply_filters(User.all, hash).to_sql
         | 
| 187 | 
            +
                      expected_query = q(
         | 
| 188 | 
            +
                        "SELECT users.* FROM users",
         | 
| 189 | 
            +
                        "WHERE (users.microposts_count = 10)",
         | 
| 190 | 
            +
                        "ORDER BY users.microposts_count ASC"
         | 
| 191 | 
            +
                      )
         | 
| 192 | 
            +
             | 
| 193 | 
            +
                      expect(strip(query)).to eq expected_query.to_s
         | 
| 194 | 
            +
                    end
         | 
| 195 | 
            +
             | 
| 196 | 
            +
                    it "desc" do
         | 
| 197 | 
            +
                        hash = {
         | 
| 198 | 
            +
                          microposts_count: 10,
         | 
| 199 | 
            +
                          sort: {property: :microposts_count, order: :desc}
         | 
| 200 | 
            +
                        }
         | 
| 201 | 
            +
             | 
| 202 | 
            +
                        query = HelperClass.new.apply_filters(User.all, hash).to_sql
         | 
| 203 | 
            +
                        expected_query = q(
         | 
| 204 | 
            +
                          "SELECT users.* FROM users",
         | 
| 205 | 
            +
                          "WHERE (users.microposts_count = 10)",
         | 
| 206 | 
            +
                          "ORDER BY users.microposts_count DESC"
         | 
| 207 | 
            +
                        )
         | 
| 208 | 
            +
             | 
| 209 | 
            +
                        expect(strip(query)).to eq expected_query.to_s
         | 
| 210 | 
            +
                    end
         | 
| 211 | 
            +
                  end
         | 
| 212 | 
            +
             | 
| 213 | 
            +
                  context "multiple where clauses" do
         | 
| 214 | 
            +
                    it "asc" do
         | 
| 215 | 
            +
                      hash = {
         | 
| 216 | 
            +
                        followers_count: {leq: 20},
         | 
| 217 | 
            +
                        microposts_count: 10,
         | 
| 218 | 
            +
                        sort: {property: :microposts_count, order: :asc}
         | 
| 219 | 
            +
                      }
         | 
| 220 | 
            +
             | 
| 221 | 
            +
                      query = HelperClass.new.apply_filters(User.all, hash).to_sql
         | 
| 222 | 
            +
                      expected_query = q(
         | 
| 223 | 
            +
                        "SELECT users.* FROM users",
         | 
| 224 | 
            +
                        "WHERE (users.microposts_count = 10)",
         | 
| 225 | 
            +
                        "AND (users.followers_count <= 20)",
         | 
| 226 | 
            +
                        "ORDER BY users.microposts_count ASC"
         | 
| 227 | 
            +
                      )
         | 
| 228 | 
            +
             | 
| 229 | 
            +
                      expect(strip(query)).to eq expected_query.to_s
         | 
| 230 | 
            +
                    end
         | 
| 231 | 
            +
             | 
| 232 | 
            +
                    it "desc" do
         | 
| 233 | 
            +
                      hash = {
         | 
| 234 | 
            +
                      followers_count: {leq: 20},
         | 
| 235 | 
            +
                        microposts_count: 10,
         | 
| 236 | 
            +
                        sort: {property: :microposts_count, order: :desc}
         | 
| 237 | 
            +
                      }
         | 
| 238 | 
            +
             | 
| 239 | 
            +
                      query = HelperClass.new.apply_filters(User.all, hash).to_sql
         | 
| 240 | 
            +
                      expected_query = q(
         | 
| 241 | 
            +
                        "SELECT users.* FROM users",
         | 
| 242 | 
            +
                        "WHERE (users.microposts_count = 10)",
         | 
| 243 | 
            +
                        "AND (users.followers_count <= 20)",
         | 
| 244 | 
            +
                        "ORDER BY users.microposts_count DESC"
         | 
| 245 | 
            +
                      )
         | 
| 246 | 
            +
             | 
| 247 | 
            +
                      expect(strip(query)).to eq expected_query.to_s
         | 
| 248 | 
            +
                    end
         | 
| 249 | 
            +
                  end
         | 
| 250 | 
            +
             | 
| 251 | 
            +
                  context "multiple sorting properties" do
         | 
| 252 | 
            +
                    it "with single where clause" do
         | 
| 253 | 
            +
                      hash = {
         | 
| 254 | 
            +
                        microposts_count: 10,
         | 
| 255 | 
            +
                        sort: [{
         | 
| 256 | 
            +
                          property: :microposts_count, order: :asc,
         | 
| 257 | 
            +
                        }, {
         | 
| 258 | 
            +
                          property: :followings_count, order: :desc
         | 
| 259 | 
            +
                        }]
         | 
| 260 | 
            +
                      }
         | 
| 261 | 
            +
             | 
| 262 | 
            +
                      query = HelperClass.new.apply_filters(User.all, hash).to_sql
         | 
| 263 | 
            +
                      expected_query = q(
         | 
| 264 | 
            +
                        "SELECT users.* FROM users",
         | 
| 265 | 
            +
                        "WHERE (users.microposts_count = 10)",
         | 
| 266 | 
            +
                        "ORDER BY users.microposts_count ASC, users.followings_count DESC"
         | 
| 267 | 
            +
                      )
         | 
| 268 | 
            +
             | 
| 269 | 
            +
                      expect(strip(query)).to eq expected_query.to_s
         | 
| 270 | 
            +
                    end
         | 
| 271 | 
            +
             | 
| 272 | 
            +
                  it "when the sorting column does not exist" do
         | 
| 273 | 
            +
                      hash = {
         | 
| 274 | 
            +
                        microposts_count: 10,
         | 
| 275 | 
            +
                        sort: [{
         | 
| 276 | 
            +
                          property: :i_do_not_exist, order: :asc,
         | 
| 277 | 
            +
                        }, {
         | 
| 278 | 
            +
                          property: :followings_count, order: :desc
         | 
| 279 | 
            +
                        }]
         | 
| 280 | 
            +
                      }
         | 
| 281 | 
            +
             | 
| 282 | 
            +
                      query = HelperClass.new.apply_filters(User.all, hash).to_sql
         | 
| 283 | 
            +
                      expected_query = q(
         | 
| 284 | 
            +
                        "SELECT users.* FROM users",
         | 
| 285 | 
            +
                        "WHERE (users.microposts_count = 10)",
         | 
| 286 | 
            +
                        "ORDER BY users.followings_count DESC"
         | 
| 287 | 
            +
                      )
         | 
| 288 | 
            +
             | 
| 289 | 
            +
                      expect(strip(query)).to eq expected_query.to_s
         | 
| 290 | 
            +
                    end
         | 
| 291 | 
            +
                  end
         | 
| 292 | 
            +
             | 
| 293 | 
            +
                  it "when the sorting column does not exist" do
         | 
| 294 | 
            +
                    hash = {
         | 
| 295 | 
            +
                      microposts_count: 10,
         | 
| 296 | 
            +
                      sort: {property: :i_do_not_exist, order: :asc}
         | 
| 297 | 
            +
                    }
         | 
| 298 | 
            +
             | 
| 299 | 
            +
                    query = HelperClass.new.apply_filters(User.all, hash).to_sql
         | 
| 300 | 
            +
                    expected_query = q(
         | 
| 301 | 
            +
                      "SELECT users.* FROM users",
         | 
| 302 | 
            +
                      "WHERE (users.microposts_count = 10)"
         | 
| 303 | 
            +
                    )
         | 
| 304 | 
            +
             | 
| 305 | 
            +
                    expect(strip(query)).to eq expected_query.to_s
         | 
| 306 | 
            +
             | 
| 307 | 
            +
                  end
         | 
| 308 | 
            +
                end
         | 
| 309 | 
            +
              end
         | 
| 100 310 | 
             
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: active_hash_relation
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 1. | 
| 4 | 
            +
              version: 1.4.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Filippos Vasilakis
         | 
| @@ -331,6 +331,7 @@ files: | |
| 331 331 | 
             
            - spec/tests/associations/has_one_spec.rb
         | 
| 332 332 | 
             
            - spec/tests/booleans_spec.rb
         | 
| 333 333 | 
             
            - spec/tests/limit_spec.rb
         | 
| 334 | 
            +
            - spec/tests/not_filter_spec.rb
         | 
| 334 335 | 
             
            - spec/tests/null_spec.rb
         | 
| 335 336 | 
             
            - spec/tests/numbers_spec.rb
         | 
| 336 337 | 
             
            - spec/tests/or_filter_spec.rb
         | 
| @@ -472,6 +473,7 @@ test_files: | |
| 472 473 | 
             
            - spec/tests/associations/has_one_spec.rb
         | 
| 473 474 | 
             
            - spec/tests/booleans_spec.rb
         | 
| 474 475 | 
             
            - spec/tests/limit_spec.rb
         | 
| 476 | 
            +
            - spec/tests/not_filter_spec.rb
         | 
| 475 477 | 
             
            - spec/tests/null_spec.rb
         | 
| 476 478 | 
             
            - spec/tests/numbers_spec.rb
         | 
| 477 479 | 
             
            - spec/tests/or_filter_spec.rb
         |