query_helper 0.0.0 → 0.1.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/Gemfile.lock +1 -1
- data/README.md +117 -268
- data/lib/query_helper/filter.rb +5 -2
- data/lib/query_helper/query_helper_concern.rb +1 -2
- data/lib/query_helper/sql_manipulator.rb +8 -7
- data/lib/query_helper/sql_sort.rb +4 -1
- data/lib/query_helper/version.rb +1 -1
- data/lib/query_helper.rb +19 -3
- metadata +2 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 93112cb7974e069da9db1dbf08d4a0f3511076a6991195e669747567f2d2caa7
         | 
| 4 | 
            +
              data.tar.gz: a242199dcea3eaa67c50792cf0b76cbe9fc9826a81f231649c81120969923cc9
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: ab24ee9a256fbb9282e3adbe79db6436235000a7be0e1f166b570d6b413c412a9f3e2d5b285938630671db1efadd7e4ed9bf13e4aa84326fb28efb060b4d2df7
         | 
| 7 | 
            +
              data.tar.gz: c08788615159a1da5fb4a218095ca5b7497360dbf7a074522d9f5f46cdffcca96cb40b4b9ba27ce905112b909dae0de42e8682292af0f0840d807b32831456d0
         | 
    
        data/Gemfile.lock
    CHANGED
    
    
    
        data/README.md
    CHANGED
    
    | @@ -2,7 +2,7 @@ | |
| 2 2 | 
             
            [](https://travis-ci.org/iserve-products/query_helper)
         | 
| 3 3 | 
             
            [](https://badge.fury.io/rb/query_helper)
         | 
| 4 4 |  | 
| 5 | 
            -
             | 
| 5 | 
            +
            QueryHelper is a ruby gem used to paginate, sort, and filter your API calls in Ruby on Rails using URL params in your HTTP requests.  It currently only supports Postgres.  
         | 
| 6 6 |  | 
| 7 7 | 
             
            ## Installation
         | 
| 8 8 |  | 
| @@ -20,278 +20,118 @@ Or install it yourself as: | |
| 20 20 |  | 
| 21 21 | 
             
                $ gem install query_helper
         | 
| 22 22 |  | 
| 23 | 
            -
            ## Use
         | 
| 23 | 
            +
            ## Quick Use
         | 
| 24 24 |  | 
| 25 | 
            -
            ###  | 
| 25 | 
            +
            ### Step 1: Update Base Controller to use the QueryHelper Concern
         | 
| 26 26 |  | 
| 27 | 
            -
            #### Initialize
         | 
| 28 | 
            -
             | 
| 29 | 
            -
            To create a new sql query object run
         | 
| 30 | 
            -
             | 
| 31 | 
            -
            ```ruby
         | 
| 32 | 
            -
            QueryHelper::Sql.new(
         | 
| 33 | 
            -
              model:,             # required
         | 
| 34 | 
            -
              query:,             # required
         | 
| 35 | 
            -
              query_params: ,     # optional
         | 
| 36 | 
            -
              column_mappings: ,  # optional
         | 
| 37 | 
            -
              filters: ,          # optional
         | 
| 38 | 
            -
              sorts: ,            # optional
         | 
| 39 | 
            -
              page: ,             # optional
         | 
| 40 | 
            -
              per_page: ,         # optional
         | 
| 41 | 
            -
              single_record: ,    # optional, default: false
         | 
| 42 | 
            -
              associations: ,     # optional
         | 
| 43 | 
            -
              as_json_options: ,  # optional
         | 
| 44 | 
            -
              run:                # optional, default: true
         | 
| 45 | 
            -
            )
         | 
| 46 | 
            -
            ```
         | 
| 47 | 
            -
             | 
| 48 | 
            -
            The following arguments are accepted when creating a new objects
         | 
| 49 | 
            -
             | 
| 50 | 
            -
            <table>
         | 
| 51 | 
            -
            <tr>
         | 
| 52 | 
            -
            <th>Argument</th>
         | 
| 53 | 
            -
            <th>Description</th>
         | 
| 54 | 
            -
            <th>Example</th>
         | 
| 55 | 
            -
            </tr>
         | 
| 56 | 
            -
            <tr>
         | 
| 57 | 
            -
            <td>model</td>
         | 
| 58 | 
            -
            <td>the model to run the query against</td>
         | 
| 59 | 
            -
            <td>
         | 
| 60 | 
            -
            <pre lang="ruby">
         | 
| 61 | 
            -
            Parent
         | 
| 62 | 
            -
            </pre>
         | 
| 63 | 
            -
            </td>
         | 
| 64 | 
            -
            </tr>
         | 
| 65 | 
            -
            <tr>
         | 
| 66 | 
            -
            <td>query</td>
         | 
| 67 | 
            -
            <td>the custom sql string to be executed</td>
         | 
| 68 | 
            -
            <td>
         | 
| 69 | 
            -
            <pre lang="ruby">
         | 
| 70 | 
            -
            'select * from parents'
         | 
| 71 | 
            -
            </pre>
         | 
| 72 | 
            -
            </td>
         | 
| 73 | 
            -
            </tr>
         | 
| 74 | 
            -
            <tr>
         | 
| 75 | 
            -
            <td>query_params</td>
         | 
| 76 | 
            -
            <td>a hash of bind variables to be embedded into the sql query</td>
         | 
| 77 | 
            -
            <td>
         | 
| 78 | 
            -
            <pre lang="ruby">
         | 
| 79 | 
            -
            {
         | 
| 80 | 
            -
              age: 20,
         | 
| 81 | 
            -
              name: 'John'
         | 
| 82 | 
            -
            }
         | 
| 83 | 
            -
            </pre>
         | 
| 84 | 
            -
            </td>
         | 
| 85 | 
            -
            </tr>
         | 
| 86 | 
            -
            <tr>
         | 
| 87 | 
            -
            <td>column_mappings</td>
         | 
| 88 | 
            -
            <td>A hash that translates aliases to sql expressions</td>
         | 
| 89 | 
            -
            <td>
         | 
| 90 | 
            -
            <pre lang="ruby">
         | 
| 91 | 
            -
            {
         | 
| 92 | 
            -
              "age" => "parents.age"
         | 
| 93 | 
            -
              "children_count" => {
         | 
| 94 | 
            -
                sql_expression: "count(children.id)",
         | 
| 95 | 
            -
                aggregate: true
         | 
| 96 | 
            -
              }
         | 
| 97 | 
            -
            }
         | 
| 98 | 
            -
            </pre>
         | 
| 99 | 
            -
            </td>
         | 
| 100 | 
            -
            </tr>
         | 
| 101 | 
            -
            <tr>
         | 
| 102 | 
            -
            <td>filters</td>
         | 
| 103 | 
            -
            <td>a list of filters in the form of `{"comparate_alias"=>{"operator_code"=>"value"}}`</td>
         | 
| 104 | 
            -
            <td>
         | 
| 105 | 
            -
            <pre lang="ruby">
         | 
| 106 | 
            -
            {
         | 
| 107 | 
            -
              "age" => { "lt" => 100 },
         | 
| 108 | 
            -
              "children_count" => { "gt" => 0 }
         | 
| 109 | 
            -
            }
         | 
| 110 | 
            -
            </pre>
         | 
| 111 | 
            -
            </td>
         | 
| 112 | 
            -
            </tr>
         | 
| 113 | 
            -
            <tr>
         | 
| 114 | 
            -
            <td>sorts</td>
         | 
| 115 | 
            -
            <td>a comma separated string with a list of sort values</td>
         | 
| 116 | 
            -
            <td>
         | 
| 117 | 
            -
            <pre lang="ruby">
         | 
| 118 | 
            -
            "age:desc,name:asc:lowercase"
         | 
| 119 | 
            -
            </pre>
         | 
| 120 | 
            -
            </td>
         | 
| 121 | 
            -
            </tr>
         | 
| 122 | 
            -
            <tr>
         | 
| 123 | 
            -
            <td>page</td>
         | 
| 124 | 
            -
            <td>the page you want returned</td>
         | 
| 125 | 
            -
            <td>
         | 
| 126 | 
            -
            <pre lang="ruby">
         | 
| 127 | 
            -
            5
         | 
| 128 | 
            -
            </pre>
         | 
| 129 | 
            -
            </td>
         | 
| 130 | 
            -
            </tr>
         | 
| 131 | 
            -
            <tr>
         | 
| 132 | 
            -
            <td>per_page</td>
         | 
| 133 | 
            -
            <td>the number of results per page</td>
         | 
| 134 | 
            -
            <td>
         | 
| 135 | 
            -
            <pre lang="ruby">
         | 
| 136 | 
            -
            20
         | 
| 137 | 
            -
            </pre>
         | 
| 138 | 
            -
            </td>
         | 
| 139 | 
            -
            </tr>
         | 
| 140 | 
            -
            <tr>
         | 
| 141 | 
            -
            <td>single_record</td>
         | 
| 142 | 
            -
            <td>whether or not you expect the record to return a single result, if toggled, only the first result will be returned</td>
         | 
| 143 | 
            -
            <td>
         | 
| 144 | 
            -
            <pre lang="ruby">
         | 
| 145 | 
            -
            false
         | 
| 146 | 
            -
            </pre>
         | 
| 147 | 
            -
            </td>
         | 
| 148 | 
            -
            </tr>
         | 
| 149 | 
            -
            <tr>
         | 
| 150 | 
            -
            <td>associations</td>
         | 
| 151 | 
            -
            <td>a list of activerecord associations you'd like included in the payload </td>
         | 
| 152 | 
            -
            <td>
         | 
| 153 | 
            -
            <pre lang="ruby">
         | 
| 154 | 
            -
             | 
| 155 | 
            -
            </pre>
         | 
| 156 | 
            -
            </td>
         | 
| 157 | 
            -
            </tr>
         | 
| 158 | 
            -
            <tr>
         | 
| 159 | 
            -
            <td>as_json_options</td>
         | 
| 160 | 
            -
            <td>a list of as_json options you'd like run before returning the payload</td>
         | 
| 161 | 
            -
            <td>
         | 
| 162 | 
            -
            <pre lang="ruby">
         | 
| 163 | 
            -
             | 
| 164 | 
            -
            </pre>
         | 
| 165 | 
            -
            </td>
         | 
| 166 | 
            -
            </tr>
         | 
| 167 | 
            -
            <tr>
         | 
| 168 | 
            -
            <td>run</td>
         | 
| 169 | 
            -
            <td>whether or not you'd like to run the query on initilization</td>
         | 
| 170 | 
            -
            <td>
         | 
| 171 | 
            -
            <pre lang="ruby">
         | 
| 172 | 
            -
            false
         | 
| 173 | 
            -
            </pre>
         | 
| 174 | 
            -
            </td>
         | 
| 175 | 
            -
            </tr>
         | 
| 176 | 
            -
            </table>
         | 
| 177 | 
            -
             | 
| 178 | 
            -
            ### Active Record Queries
         | 
| 179 | 
            -
             | 
| 180 | 
            -
            To run an active record query execute
         | 
| 181 27 | 
             
            ```ruby
         | 
| 182 | 
            -
             | 
| 28 | 
            +
            class ApplicationController < ActionController::API
         | 
| 29 | 
            +
              include QueryHelper::QueryHelperConcern
         | 
| 30 | 
            +
              before_action :create_query_helper
         | 
| 31 | 
            +
            end
         | 
| 183 32 | 
             
            ```
         | 
| 184 | 
            -
            active_record_call: Valid active record syntax (i.e. ```Object.where(state: 'Active')```)
         | 
| 185 | 
            -
            query_helpers: See docs below
         | 
| 186 | 
            -
            valid_columns: Default is [].  Pass in an array of columns you want to allow sorting and filtering on.
         | 
| 187 | 
            -
            single_record: Default is false.  Pass in true to format payload as a single object instead of a list of objects
         | 
| 188 33 |  | 
| 34 | 
            +
            Adding this code creates a `QueryHelper` object preloaded with pagination, filtering, sorting, and association information included in the URL.  This object can be accessed by using the `@query_helper` instance variable from within your controllers.
         | 
| 189 35 |  | 
| 190 | 
            -
             | 
| 191 | 
            -
            query: A string containing your custom SQL query
         | 
| 192 | 
            -
            query_params: a symbolized hash of binds to be included in your SQL query
         | 
| 193 | 
            -
            query_helpers: See docs below
         | 
| 194 | 
            -
            valid_columns: Default is [].  Pass in an array of columns you want to allow sorting and filtering on.
         | 
| 195 | 
            -
            single_record: Default is false.  Pass in true to format payload as a single object instead of a list of objects
         | 
| 36 | 
            +
            ### Step 2: Use QueryHelper to run active record and sql queries within your controller
         | 
| 196 37 |  | 
| 197 | 
            -
             | 
| 198 | 
            -
            query_helpers is a symbolized hash passed in with information about pagination, associations, filtering and sorting.
         | 
| 199 | 
            -
             | 
| 200 | 
            -
            ### Pagination
         | 
| 201 | 
            -
            There are two pagination keys you can pass in as part of the query_helpers objects
         | 
| 38 | 
            +
            #### Active Record Example
         | 
| 202 39 |  | 
| 203 40 | 
             
            ```ruby
         | 
| 204 | 
            -
             | 
| 205 | 
            -
              page: 1,
         | 
| 206 | 
            -
              per_page: 20
         | 
| 207 | 
            -
            }
         | 
| 208 | 
            -
            ```
         | 
| 41 | 
            +
            class ResourceController < ApplicationController
         | 
| 209 42 |  | 
| 210 | 
            -
             | 
| 43 | 
            +
              def index
         | 
| 44 | 
            +
                @query_helper.update(
         | 
| 45 | 
            +
                  model: UserNotificationSetting,
         | 
| 46 | 
            +
                  query: "select * from resources r where r.user_id = :user_id",
         | 
| 47 | 
            +
                  bind_variables: { user_id: current_user().id }
         | 
| 48 | 
            +
                )
         | 
| 211 49 |  | 
| 212 | 
            -
             | 
| 213 | 
            -
             | 
| 50 | 
            +
                render json: @query_helper.results()
         | 
| 51 | 
            +
              end
         | 
| 214 52 |  | 
| 215 | 
            -
             | 
| 216 | 
            -
            {
         | 
| 217 | 
            -
                sort: "column_name:sort_direction"
         | 
| 218 | 
            -
            }
         | 
| 53 | 
            +
            end
         | 
| 219 54 | 
             
            ```
         | 
| 220 | 
            -
             | 
| 55 | 
            +
             | 
| 56 | 
            +
            #### Raw SQL Example
         | 
| 57 | 
            +
             | 
| 221 58 | 
             
            ```ruby
         | 
| 222 | 
            -
             | 
| 223 | 
            -
             | 
| 224 | 
            -
             | 
| 59 | 
            +
            class ResourceController < ApplicationController
         | 
| 60 | 
            +
             | 
| 61 | 
            +
              def index
         | 
| 62 | 
            +
                @query_helper.query = Resource.all
         | 
| 63 | 
            +
                render json: @query_helper.results()
         | 
| 64 | 
            +
              end
         | 
| 65 | 
            +
             | 
| 66 | 
            +
            end
         | 
| 225 67 | 
             
            ```
         | 
| 226 68 |  | 
| 227 | 
            -
             | 
| 228 | 
            -
            Filtering is controlled by the `filter` object in the query_helpers hash
         | 
| 69 | 
            +
            You can also use the `@query_helper.update()` method to update the QueryHelper with an ActiveRecord object
         | 
| 229 70 |  | 
| 230 71 | 
             
            ```ruby
         | 
| 231 | 
            -
             | 
| 232 | 
            -
               | 
| 233 | 
            -
             | 
| 234 | 
            -
                  "gte" => 20,
         | 
| 235 | 
            -
                  "lt" => 40
         | 
| 236 | 
            -
                },
         | 
| 237 | 
            -
                "column_2" => {
         | 
| 238 | 
            -
                  "eql" => "my_string"
         | 
| 239 | 
            -
                },
         | 
| 240 | 
            -
                "column_3" => {
         | 
| 241 | 
            -
                  "like" => "my_string%"
         | 
| 242 | 
            -
                },
         | 
| 243 | 
            -
                "column_4" => {
         | 
| 244 | 
            -
                  "in" => "item1,item2,item3"
         | 
| 245 | 
            -
                }
         | 
| 246 | 
            -
            }
         | 
| 72 | 
            +
            @query_helper.update(
         | 
| 73 | 
            +
              query: Resource.all
         | 
| 74 | 
            +
            )
         | 
| 247 75 | 
             
            ```
         | 
| 248 76 |  | 
| 249 | 
            -
             | 
| 77 | 
            +
            ### Step 3: Paginate, Sort, Filter, and Include Associations using URL params
         | 
| 250 78 |  | 
| 251 | 
            -
             | 
| 252 | 
            -
            “gte”: >=
         | 
| 253 | 
            -
            “lte”: <=
         | 
| 254 | 
            -
            “gt”: >
         | 
| 255 | 
            -
            “lt”: <
         | 
| 256 | 
            -
            “eql”: =
         | 
| 257 | 
            -
            “noteql”: !=
         | 
| 258 | 
            -
            "like": like
         | 
| 259 | 
            -
            “in”: in
         | 
| 260 | 
            -
            “notin” not in
         | 
| 261 | 
            -
            “null”: “is null” or “is not null” (pass in true or false as the value)
         | 
| 262 | 
            -
            ```
         | 
| 79 | 
            +
            #### Pagination
         | 
| 263 80 |  | 
| 264 | 
            -
             | 
| 81 | 
            +
            `page=1`
         | 
| 265 82 |  | 
| 266 | 
            -
             | 
| 83 | 
            +
            `per_page=20`
         | 
| 267 84 |  | 
| 268 | 
            -
             | 
| 269 | 
            -
            {
         | 
| 270 | 
            -
              include: ['associated_object_1', 'associated_object_2']
         | 
| 271 | 
            -
            }
         | 
| 272 | 
            -
            ```
         | 
| 85 | 
            +
            `http://www.example.com/resources?page=1&per_page=25`
         | 
| 273 86 |  | 
| 274 | 
            -
             | 
| 87 | 
            +
            #### Sorting
         | 
| 88 | 
            +
             | 
| 89 | 
            +
            `sort=column:direction`
         | 
| 90 | 
            +
             | 
| 91 | 
            +
            Single Sort: `http://www.example.com/resources?sort=resource_name:desc`
         | 
| 92 | 
            +
             | 
| 93 | 
            +
            Multiple Sorts: `http://www.example.com/resources?sort=resource_name:desc,resource_age:asc`
         | 
| 94 | 
            +
             | 
| 95 | 
            +
            Lowercase Sort: `http://www.example.com/resources?sort=resource_name:desc:lowercase`
         | 
| 96 | 
            +
             | 
| 97 | 
            +
            #### Filtering
         | 
| 98 | 
            +
             | 
| 99 | 
            +
            `filter[column][operator_code]=value`
         | 
| 100 | 
            +
             | 
| 101 | 
            +
            Single Filter: `http://www.example.com/resources?filter[resource_age][gt]=50`
         | 
| 102 | 
            +
             | 
| 103 | 
            +
            Multiple Filters: `http://www.example.com/resources?filter[resource_age][gt]=50&[resource_name][eql]=banana_resource`
         | 
| 104 | 
            +
             | 
| 105 | 
            +
            Operator Code | SQL Operator
         | 
| 106 | 
            +
            --- | ---
         | 
| 107 | 
            +
            gte | >=
         | 
| 108 | 
            +
            lte | <=
         | 
| 109 | 
            +
            gt | >
         | 
| 110 | 
            +
            lt | <
         | 
| 111 | 
            +
            eql | =
         | 
| 112 | 
            +
            noteql | !=
         | 
| 113 | 
            +
            like | like
         | 
| 114 | 
            +
            in | in
         | 
| 115 | 
            +
            notin | not in
         | 
| 116 | 
            +
            null | is null *or* is not null
         | 
| 117 | 
            +
             | 
| 118 | 
            +
            Note: For the null operator code, toggle *is null* operator with true and *is not null* operator with false
         | 
| 119 | 
            +
             | 
| 120 | 
            +
            #### Associations
         | 
| 121 | 
            +
             | 
| 122 | 
            +
            Include ActiveRecord associations in the payload.  The association must be defined in the model.
         | 
| 123 | 
            +
             | 
| 124 | 
            +
            `include=association`
         | 
| 125 | 
            +
             | 
| 126 | 
            +
            Single Association: `http://www.example.com/resources?include=child_resource`
         | 
| 127 | 
            +
             | 
| 128 | 
            +
            Multiple Associations: `http://www.example.com/resources?include[]=child_resource&include[]=parent_resource`
         | 
| 275 129 |  | 
| 276 | 
            -
            The following is an example of a query_helpers object that can be passed into the sql and active record methods
         | 
| 277 130 |  | 
| 278 | 
            -
            ```ruby
         | 
| 279 | 
            -
            query_helpers = {
         | 
| 280 | 
            -
              page: 1,
         | 
| 281 | 
            -
              per_page: 20,
         | 
| 282 | 
            -
              sort: "name:desc"
         | 
| 283 | 
            -
              include: ["child"]
         | 
| 284 | 
            -
              filter: {
         | 
| 285 | 
            -
                "id" => {
         | 
| 286 | 
            -
                  "gte" => 20,
         | 
| 287 | 
            -
                  "lt" => 40
         | 
| 288 | 
            -
                }
         | 
| 289 | 
            -
            }
         | 
| 290 | 
            -
            ```
         | 
| 291 131 |  | 
| 292 132 | 
             
            ## Payload Formats
         | 
| 293 133 |  | 
| 294 | 
            -
            The QueryHelper gem will return  | 
| 134 | 
            +
            The QueryHelper gem will return the following payload
         | 
| 295 135 |  | 
| 296 136 | 
             
            ### Paginated List Payload
         | 
| 297 137 | 
             
            ```json
         | 
| @@ -330,30 +170,39 @@ The QueryHelper gem will return results in one of three formats | |
| 330 170 | 
             
            }
         | 
| 331 171 | 
             
            ```
         | 
| 332 172 |  | 
| 333 | 
            -
             | 
| 334 | 
            -
             | 
| 335 | 
            -
             | 
| 336 | 
            -
             | 
| 337 | 
            -
             | 
| 338 | 
            -
             | 
| 339 | 
            -
             | 
| 340 | 
            -
             | 
| 341 | 
            -
             | 
| 342 | 
            -
             | 
| 343 | 
            -
             | 
| 344 | 
            -
             | 
| 345 | 
            -
             | 
| 346 | 
            -
             | 
| 347 | 
            -
             | 
| 348 | 
            -
             | 
| 349 | 
            -
             | 
| 350 | 
            -
             | 
| 351 | 
            -
             | 
| 352 | 
            -
             | 
| 353 | 
            -
             | 
| 354 | 
            -
             | 
| 355 | 
            -
             | 
| 356 | 
            -
             | 
| 173 | 
            +
            ## Advanced Options
         | 
| 174 | 
            +
             | 
| 175 | 
            +
            ### Associations
         | 
| 176 | 
            +
             | 
| 177 | 
            +
            You can preload additional and include additional associations in your payload besides what's defined in the `include` url parameter.
         | 
| 178 | 
            +
             | 
| 179 | 
            +
            ```ruby
         | 
| 180 | 
            +
            @query_helper.update(
         | 
| 181 | 
            +
              associations: ['association1']
         | 
| 182 | 
            +
            )
         | 
| 183 | 
            +
            ```
         | 
| 184 | 
            +
             | 
| 185 | 
            +
            ### as_json options
         | 
| 186 | 
            +
             | 
| 187 | 
            +
            You can pass in additional as_json options to be included in the payload.
         | 
| 188 | 
            +
             | 
| 189 | 
            +
            ```ruby
         | 
| 190 | 
            +
            @query_helper.update(
         | 
| 191 | 
            +
              as_json_options: { methods: [:last_ran_at] }
         | 
| 192 | 
            +
            )
         | 
| 193 | 
            +
            ```
         | 
| 194 | 
            +
             | 
| 195 | 
            +
            ### Single Record Queries
         | 
| 196 | 
            +
            If you only want to return a single result, but still want to be able to use some of the other functionality of QueryHelper, you can set `single_record` to true in the QueryHelper object.
         | 
| 197 | 
            +
             | 
| 198 | 
            +
            ```ruby
         | 
| 199 | 
            +
            @query_helper.single_record = true
         | 
| 200 | 
            +
            ```
         | 
| 201 | 
            +
            or
         | 
| 202 | 
            +
            ```ruby
         | 
| 203 | 
            +
            @query_helper.update(
         | 
| 204 | 
            +
              single_record: true
         | 
| 205 | 
            +
            )
         | 
| 357 206 | 
             
            ```
         | 
| 358 207 |  | 
| 359 208 | 
             
            ### Single Record Payload
         | 
| @@ -370,7 +219,7 @@ The QueryHelper gem will return results in one of three formats | |
| 370 219 |  | 
| 371 220 | 
             
            ## Contributing
         | 
| 372 221 |  | 
| 373 | 
            -
            Bug reports and pull requests are welcome on GitHub at https://github.com/ | 
| 222 | 
            +
            Bug reports and pull requests are welcome on GitHub at https://github.com/iserve_products/query_helper. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
         | 
| 374 223 |  | 
| 375 224 | 
             
            ## License
         | 
| 376 225 |  | 
    
        data/lib/query_helper/filter.rb
    CHANGED
    
    | @@ -70,10 +70,13 @@ class QueryHelper | |
| 70 70 |  | 
| 71 71 | 
             
                def mofify_criterion
         | 
| 72 72 | 
             
                  # lowercase strings for comparison
         | 
| 73 | 
            -
                  @criterion.downcase! if criterion.class == String && criterion.scan(/[a-zA-Z]/).any?
         | 
| 73 | 
            +
                  @criterion.downcase! if @criterion.class == String && @criterion.scan(/[a-zA-Z]/).any?
         | 
| 74 74 |  | 
| 75 75 | 
             
                  # turn the criterion into an array for in and notin comparisons
         | 
| 76 | 
            -
                  @criterion = criterion.split(",") if ["in", "notin"].include?(operator_code) && criterion.class == String
         | 
| 76 | 
            +
                  @criterion = @criterion.split(",") if ["in", "notin"].include?(@operator_code) && @criterion.class == String
         | 
| 77 | 
            +
             | 
| 78 | 
            +
                  # Add wildcards for like comparisons
         | 
| 79 | 
            +
                  @criterion = "%#{@criterion}%" if @operator_code == "like"
         | 
| 77 80 | 
             
                end
         | 
| 78 81 |  | 
| 79 82 | 
             
                def modify_comparate
         | 
| @@ -1,5 +1,4 @@ | |
| 1 1 | 
             
            require 'active_support/concern'
         | 
| 2 | 
            -
            require "query_helper/sql_filter"
         | 
| 3 2 |  | 
| 4 3 | 
             
            class QueryHelper
         | 
| 5 4 | 
             
              module QueryHelperConcern
         | 
| @@ -24,7 +23,7 @@ class QueryHelper | |
| 24 23 | 
             
                  end
         | 
| 25 24 |  | 
| 26 25 | 
             
                  def create_query_helper_associations
         | 
| 27 | 
            -
             | 
| 26 | 
            +
                    QueryHelper::Associations.process_association_params(params[:include])
         | 
| 28 27 | 
             
                  end
         | 
| 29 28 |  | 
| 30 29 | 
             
                  def query_helper_params
         | 
| @@ -10,7 +10,8 @@ class QueryHelper | |
| 10 10 | 
             
                  where_clauses: nil,
         | 
| 11 11 | 
             
                  having_clauses: nil,
         | 
| 12 12 | 
             
                  order_by_clauses: nil,
         | 
| 13 | 
            -
                  include_limit_clause: false
         | 
| 13 | 
            +
                  include_limit_clause: false,
         | 
| 14 | 
            +
                  additional_select_clauses: []
         | 
| 14 15 | 
             
                )
         | 
| 15 16 | 
             
                  @parser = SqlParser.new(sql)
         | 
| 16 17 | 
             
                  @sql = @parser.sql.dup
         | 
| @@ -18,23 +19,23 @@ class QueryHelper | |
| 18 19 | 
             
                  @having_clauses = having_clauses
         | 
| 19 20 | 
             
                  @order_by_clauses = order_by_clauses
         | 
| 20 21 | 
             
                  @include_limit_clause = include_limit_clause
         | 
| 22 | 
            +
                  @additional_select_clauses = additional_select_clauses
         | 
| 21 23 | 
             
                end
         | 
| 22 24 |  | 
| 23 25 | 
             
                def build
         | 
| 24 26 | 
             
                  insert_having_clauses()
         | 
| 25 27 | 
             
                  insert_where_clauses()
         | 
| 26 | 
            -
                   | 
| 28 | 
            +
                  insert_select_clauses()
         | 
| 27 29 | 
             
                  insert_order_by_and_limit_clause()
         | 
| 28 30 | 
             
                  @sql.squish
         | 
| 29 31 | 
             
                end
         | 
| 30 32 |  | 
| 31 33 | 
             
                private
         | 
| 32 34 |  | 
| 33 | 
            -
                def  | 
| 34 | 
            -
                   | 
| 35 | 
            -
                   | 
| 36 | 
            -
                  @sql.insert(@parser.insert_select_index,  | 
| 37 | 
            -
                  # Potentially update parser here
         | 
| 35 | 
            +
                def insert_select_clauses
         | 
| 36 | 
            +
                  total_count_clause = "count(*) over () as _query_full_count"
         | 
| 37 | 
            +
                  @additional_select_clauses << total_count_clause if @include_limit_clause
         | 
| 38 | 
            +
                  @sql.insert(@parser.insert_select_index, " , #{@additional_select_clauses.join(", ")} ") if @additional_select_clauses.length > 0
         | 
| 38 39 | 
             
                end
         | 
| 39 40 |  | 
| 40 41 | 
             
                def insert_where_clauses
         | 
| @@ -3,11 +3,12 @@ require "query_helper/invalid_query_error" | |
| 3 3 | 
             
            class QueryHelper
         | 
| 4 4 | 
             
              class SqlSort
         | 
| 5 5 |  | 
| 6 | 
            -
                attr_accessor :column_maps
         | 
| 6 | 
            +
                attr_accessor :column_maps, :select_strings
         | 
| 7 7 |  | 
| 8 8 | 
             
                def initialize(sort_string: "", column_maps: [])
         | 
| 9 9 | 
             
                  @sort_string = sort_string
         | 
| 10 10 | 
             
                  @column_maps = column_maps
         | 
| 11 | 
            +
                  @select_strings = []
         | 
| 11 12 | 
             
                end
         | 
| 12 13 |  | 
| 13 14 | 
             
                def parse_sort_string
         | 
| @@ -38,6 +39,8 @@ class QueryHelper | |
| 38 39 | 
             
                    case modifier
         | 
| 39 40 | 
             
                    when "lowercase"
         | 
| 40 41 | 
             
                      sql_expression = "lower(#{sql_expression})"
         | 
| 42 | 
            +
                      # When select distincts are used, the order by clause must be included in the select clause
         | 
| 43 | 
            +
                      @select_strings << sql_expression
         | 
| 41 44 | 
             
                    end
         | 
| 42 45 |  | 
| 43 46 | 
             
                    sql_strings << "#{sql_expression} #{direction}"
         | 
    
        data/lib/query_helper/version.rb
    CHANGED
    
    
    
        data/lib/query_helper.rb
    CHANGED
    
    | @@ -24,7 +24,7 @@ class QueryHelper | |
| 24 24 | 
             
                page: nil, # define the page you want returned
         | 
| 25 25 | 
             
                per_page: nil, # define how many results you want per page
         | 
| 26 26 | 
             
                single_record: false, # whether or not you expect the record to return a single result, if toggled, only the first result will be returned
         | 
| 27 | 
            -
                associations:  | 
| 27 | 
            +
                associations: [], # a list of activerecord associations you'd like included in the payload
         | 
| 28 28 | 
             
                as_json_options: nil, # a list of as_json options you'd like run before returning the payload
         | 
| 29 29 | 
             
                custom_mappings: {}, # custom keyword => sql_expression mappings
         | 
| 30 30 | 
             
                api_payload: false # Return the paginated payload or simply return the result array
         | 
| @@ -52,10 +52,24 @@ class QueryHelper | |
| 52 52 | 
             
                end
         | 
| 53 53 | 
             
              end
         | 
| 54 54 |  | 
| 55 | 
            -
              def  | 
| 55 | 
            +
              def update(
         | 
| 56 | 
            +
                query: nil,
         | 
| 57 | 
            +
                model: nil,
         | 
| 58 | 
            +
                bind_variables: {},
         | 
| 59 | 
            +
                filters: [],
         | 
| 60 | 
            +
                associations: [],
         | 
| 61 | 
            +
                as_json_options: nil,
         | 
| 62 | 
            +
                single_record: nil,
         | 
| 63 | 
            +
                custom_mappings: nil
         | 
| 64 | 
            +
              )
         | 
| 56 65 | 
             
                @model = model if model
         | 
| 57 66 | 
             
                @query = query if query
         | 
| 58 67 | 
             
                @bind_variables.merge!(bind_variables)
         | 
| 68 | 
            +
                filters.each{ |f| add_filter(**f) }
         | 
| 69 | 
            +
                @associations = @associations | associations
         | 
| 70 | 
            +
                @single_record = single_record if single_record
         | 
| 71 | 
            +
                @as_json_options = as_json_options if as_json_options
         | 
| 72 | 
            +
                @custom_mappings = custom_mappings if custom_mappings
         | 
| 59 73 | 
             
              end
         | 
| 60 74 |  | 
| 61 75 | 
             
              def add_filter(operator_code:, criterion:, comparate:)
         | 
| @@ -68,6 +82,7 @@ class QueryHelper | |
| 68 82 |  | 
| 69 83 | 
             
                # Create column maps to be used by the filter and sort objects
         | 
| 70 84 | 
             
                column_maps = create_column_maps()
         | 
| 85 | 
            +
             | 
| 71 86 | 
             
                @sql_filter.column_maps = column_maps
         | 
| 72 87 | 
             
                @sql_sort.column_maps = column_maps
         | 
| 73 88 |  | 
| @@ -83,7 +98,8 @@ class QueryHelper | |
| 83 98 | 
             
                  where_clauses: @sql_filter.where_clauses,
         | 
| 84 99 | 
             
                  having_clauses:  @sql_filter.having_clauses,
         | 
| 85 100 | 
             
                  order_by_clauses: @sql_sort.parse_sort_string,
         | 
| 86 | 
            -
                  include_limit_clause: @page && @per_page ? true : false
         | 
| 101 | 
            +
                  include_limit_clause: @page && @per_page ? true : false,
         | 
| 102 | 
            +
                  additional_select_clauses:  @sql_sort.select_strings
         | 
| 87 103 | 
             
                )
         | 
| 88 104 | 
             
                @executed_query = manipulator.build()
         | 
| 89 105 | 
             
                @results = @model.find_by_sql([@executed_query, @bind_variables]) # Execute Sql Query
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: query_helper
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0. | 
| 4 | 
            +
              version: 0.1.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Evan McDaniel
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: exe
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2019- | 
| 11 | 
            +
            date: 2019-08-01 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: bundler
         |