lhs 21.2.2 → 21.3.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 +208 -107
 - data/lhs.gemspec +1 -1
 - data/lib/lhs.rb +8 -0
 - data/lib/lhs/concerns/autoload_records.rb +20 -3
 - data/lib/lhs/concerns/o_auth.rb +25 -0
 - data/lib/lhs/concerns/record/configuration.rb +28 -11
 - data/lib/lhs/concerns/record/request.rb +29 -8
 - data/lib/lhs/config.rb +1 -1
 - data/lib/lhs/interceptors/auto_oauth/interceptor.rb +33 -0
 - data/lib/lhs/interceptors/auto_oauth/thread_registry.rb +18 -0
 - data/lib/lhs/version.rb +1 -1
 - data/spec/auto_oauth_spec.rb +129 -0
 - data/spec/autoloading_spec.rb +35 -8
 - data/spec/dummy/app/controllers/application_controller.rb +15 -0
 - data/spec/dummy/app/controllers/automatic_authentication_controller.rb +22 -0
 - data/spec/dummy/app/controllers/error_handling_with_chains_controller.rb +2 -2
 - data/spec/dummy/app/controllers/extended_rollbar_controller.rb +2 -2
 - data/spec/dummy/app/controllers/option_blocks_controller.rb +2 -2
 - data/spec/dummy/app/models/dummy_customer.rb +6 -0
 - data/spec/dummy/app/models/{record.rb → dummy_record.rb} +1 -1
 - data/spec/dummy/app/models/dummy_record_with_multiple_oauth_providers1.rb +7 -0
 - data/spec/dummy/app/models/dummy_record_with_multiple_oauth_providers2.rb +7 -0
 - data/spec/dummy/app/models/dummy_record_with_multiple_providers_per_endpoint.rb +6 -0
 - data/spec/dummy/app/models/dummy_record_with_oauth.rb +7 -0
 - data/spec/dummy/app/models/{user.rb → dummy_user.rb} +1 -1
 - data/spec/dummy/app/models/providers/customer_system.rb +7 -0
 - data/spec/dummy/config/routes.rb +4 -0
 - data/spec/option_blocks/ensure_reset_between_requests_spec.rb +2 -1
 - data/spec/record/error_handling_integration_spec.rb +1 -1
 - data/spec/record/includes_spec.rb +41 -0
 - data/spec/request_cycle_cache_spec.rb +3 -3
 - data/spec/support/reset.rb +31 -9
 - metadata +29 -10
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA256:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: cadb661567a1a911f12d612030d14ca963216bc6cca0874525b50ec9afe6d2c1
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: f110c85be3c7ff12f00797f1268f14ba9376c235e1d8dbe9665fb51515f7c0b2
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: ed5dc79199bd8563b951f0131dbb4965e7133898f703104f054cbffe52953ed2c6d9526d046d2077d7b1420ba15e6a3c1ef6ac8168a8087c62d9cc50e227a8cc
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 2cf77b9a2955eac7cf408f3f35174863b6b773133149b77e0aea47a74808d5d43ab43d99e00cd7bdab4a1c41e8c59c831d31dfae64f8f5d3723f65102288aa06
         
     | 
    
        data/README.md
    CHANGED
    
    | 
         @@ -39,113 +39,116 @@ record.review # "Lunch was great 
     | 
|
| 
       39 
39 
     | 
    
         | 
| 
       40 
40 
     | 
    
         
             
            ## Table of contents
         
     | 
| 
       41 
41 
     | 
    
         
             
               * [LHS](#lhs)
         
     | 
| 
       42 
     | 
    
         
            -
             
     | 
| 
       43 
     | 
    
         
            -
             
     | 
| 
       44 
     | 
    
         
            -
             
     | 
| 
       45 
     | 
    
         
            -
             
     | 
| 
       46 
     | 
    
         
            -
             
     | 
| 
       47 
     | 
    
         
            -
             
     | 
| 
       48 
     | 
    
         
            -
             
     | 
| 
       49 
     | 
    
         
            -
             
     | 
| 
       50 
     | 
    
         
            -
             
     | 
| 
       51 
     | 
    
         
            -
             
     | 
| 
       52 
     | 
    
         
            -
             
     | 
| 
       53 
     | 
    
         
            -
             
     | 
| 
       54 
     | 
    
         
            -
             
     | 
| 
       55 
     | 
    
         
            -
             
     | 
| 
       56 
     | 
    
         
            -
             
     | 
| 
       57 
     | 
    
         
            -
             
     | 
| 
       58 
     | 
    
         
            -
             
     | 
| 
       59 
     | 
    
         
            -
             
     | 
| 
       60 
     | 
    
         
            -
             
     | 
| 
       61 
     | 
    
         
            -
             
     | 
| 
       62 
     | 
    
         
            -
             
     | 
| 
       63 
     | 
    
         
            -
             
     | 
| 
       64 
     | 
    
         
            -
             
     | 
| 
       65 
     | 
    
         
            -
             
     | 
| 
       66 
     | 
    
         
            -
             
     | 
| 
       67 
     | 
    
         
            -
             
     | 
| 
       68 
     | 
    
         
            -
             
     | 
| 
       69 
     | 
    
         
            -
             
     | 
| 
       70 
     | 
    
         
            -
             
     | 
| 
       71 
     | 
    
         
            -
             
     | 
| 
       72 
     | 
    
         
            -
             
     | 
| 
       73 
     | 
    
         
            -
             
     | 
| 
       74 
     | 
    
         
            -
             
     | 
| 
       75 
     | 
    
         
            -
             
     | 
| 
       76 
     | 
    
         
            -
             
     | 
| 
       77 
     | 
    
         
            -
             
     | 
| 
       78 
     | 
    
         
            -
             
     | 
| 
       79 
     | 
    
         
            -
             
     | 
| 
       80 
     | 
    
         
            -
             
     | 
| 
       81 
     | 
    
         
            -
             
     | 
| 
       82 
     | 
    
         
            -
             
     | 
| 
       83 
     | 
    
         
            -
             
     | 
| 
       84 
     | 
    
         
            -
             
     | 
| 
       85 
     | 
    
         
            -
             
     | 
| 
       86 
     | 
    
         
            -
             
     | 
| 
       87 
     | 
    
         
            -
             
     | 
| 
       88 
     | 
    
         
            -
             
     | 
| 
       89 
     | 
    
         
            -
             
     | 
| 
       90 
     | 
    
         
            -
             
     | 
| 
       91 
     | 
    
         
            -
             
     | 
| 
       92 
     | 
    
         
            -
             
     | 
| 
       93 
     | 
    
         
            -
             
     | 
| 
       94 
     | 
    
         
            -
             
     | 
| 
       95 
     | 
    
         
            -
             
     | 
| 
       96 
     | 
    
         
            -
             
     | 
| 
       97 
     | 
    
         
            -
             
     | 
| 
       98 
     | 
    
         
            -
             
     | 
| 
       99 
     | 
    
         
            -
             
     | 
| 
       100 
     | 
    
         
            -
             
     | 
| 
       101 
     | 
    
         
            -
             
     | 
| 
       102 
     | 
    
         
            -
             
     | 
| 
       103 
     | 
    
         
            -
             
     | 
| 
       104 
     | 
    
         
            -
             
     | 
| 
       105 
     | 
    
         
            -
             
     | 
| 
       106 
     | 
    
         
            -
             
     | 
| 
       107 
     | 
    
         
            -
             
     | 
| 
       108 
     | 
    
         
            -
             
     | 
| 
       109 
     | 
    
         
            -
             
     | 
| 
       110 
     | 
    
         
            -
             
     | 
| 
       111 
     | 
    
         
            -
             
     | 
| 
       112 
     | 
    
         
            -
             
     | 
| 
       113 
     | 
    
         
            -
             
     | 
| 
       114 
     | 
    
         
            -
             
     | 
| 
       115 
     | 
    
         
            -
             
     | 
| 
       116 
     | 
    
         
            -
             
     | 
| 
       117 
     | 
    
         
            -
             
     | 
| 
       118 
     | 
    
         
            -
             
     | 
| 
       119 
     | 
    
         
            -
             
     | 
| 
       120 
     | 
    
         
            -
             
     | 
| 
       121 
     | 
    
         
            -
             
     | 
| 
       122 
     | 
    
         
            -
             
     | 
| 
       123 
     | 
    
         
            -
             
     | 
| 
       124 
     | 
    
         
            -
             
     | 
| 
       125 
     | 
    
         
            -
             
     | 
| 
       126 
     | 
    
         
            -
             
     | 
| 
       127 
     | 
    
         
            -
             
     | 
| 
       128 
     | 
    
         
            -
             
     | 
| 
       129 
     | 
    
         
            -
             
     | 
| 
       130 
     | 
    
         
            -
             
     | 
| 
       131 
     | 
    
         
            -
             
     | 
| 
       132 
     | 
    
         
            -
             
     | 
| 
       133 
     | 
    
         
            -
             
     | 
| 
       134 
     | 
    
         
            -
             
     | 
| 
       135 
     | 
    
         
            -
             
     | 
| 
       136 
     | 
    
         
            -
             
     | 
| 
       137 
     | 
    
         
            -
             
     | 
| 
       138 
     | 
    
         
            -
             
     | 
| 
       139 
     | 
    
         
            -
             
     | 
| 
       140 
     | 
    
         
            -
             
     | 
| 
       141 
     | 
    
         
            -
             
     | 
| 
       142 
     | 
    
         
            -
             
     | 
| 
       143 
     | 
    
         
            -
             
     | 
| 
       144 
     | 
    
         
            -
             
     | 
| 
       145 
     | 
    
         
            -
             
     | 
| 
       146 
     | 
    
         
            -
             
     | 
| 
       147 
     | 
    
         
            -
             
     | 
| 
       148 
     | 
    
         
            -
             
     | 
| 
      
 42 
     | 
    
         
            +
              * [Quickstart](#quickstart)
         
     | 
| 
      
 43 
     | 
    
         
            +
              * [Installation/Startup checklist](#installationstartup-checklist)
         
     | 
| 
      
 44 
     | 
    
         
            +
              * [Record](#record)
         
     | 
| 
      
 45 
     | 
    
         
            +
                 * [Endpoints](#endpoints)
         
     | 
| 
      
 46 
     | 
    
         
            +
                    * [Configure endpoint hosts](#configure-endpoint-hosts)
         
     | 
| 
      
 47 
     | 
    
         
            +
                    * [Endpoint Priorities](#endpoint-priorities)
         
     | 
| 
      
 48 
     | 
    
         
            +
                 * [Provider](#provider)
         
     | 
| 
      
 49 
     | 
    
         
            +
                 * [Record inheritance](#record-inheritance)
         
     | 
| 
      
 50 
     | 
    
         
            +
                 * [Find multiple records](#find-multiple-records)
         
     | 
| 
      
 51 
     | 
    
         
            +
                    * [fetch](#fetch)
         
     | 
| 
      
 52 
     | 
    
         
            +
                    * [where](#where)
         
     | 
| 
      
 53 
     | 
    
         
            +
                    * [Reuse/Dry where statements: Use scopes](#reusedry-where-statements-use-scopes)
         
     | 
| 
      
 54 
     | 
    
         
            +
                    * [all](#all)
         
     | 
| 
      
 55 
     | 
    
         
            +
                    * [all with unpaginated endpoints](#all-with-unpaginated-endpoints)
         
     | 
| 
      
 56 
     | 
    
         
            +
                    * [Retrieve the amount of a collection of items: count vs. length](#retrieve-the-amount-of-a-collection-of-items-count-vs-length)
         
     | 
| 
      
 57 
     | 
    
         
            +
                 * [Find single records](#find-single-records)
         
     | 
| 
      
 58 
     | 
    
         
            +
                    * [find](#find)
         
     | 
| 
      
 59 
     | 
    
         
            +
                    * [find_by](#find_by)
         
     | 
| 
      
 60 
     | 
    
         
            +
                    * [first](#first)
         
     | 
| 
      
 61 
     | 
    
         
            +
                    * [last](#last)
         
     | 
| 
      
 62 
     | 
    
         
            +
                 * [Work with retrieved data](#work-with-retrieved-data)
         
     | 
| 
      
 63 
     | 
    
         
            +
                    * [Automatic detection/conversion of collections](#automatic-detectionconversion-of-collections)
         
     | 
| 
      
 64 
     | 
    
         
            +
                    * [Map complex data for easy access](#map-complex-data-for-easy-access)
         
     | 
| 
      
 65 
     | 
    
         
            +
                    * [Access and identify nested records](#access-and-identify-nested-records)
         
     | 
| 
      
 66 
     | 
    
         
            +
                       * [Relations / Associations](#relations--associations)
         
     | 
| 
      
 67 
     | 
    
         
            +
                          * [has_many](#has_many)
         
     | 
| 
      
 68 
     | 
    
         
            +
                          * [has_one](#has_one)
         
     | 
| 
      
 69 
     | 
    
         
            +
                    * [Unwrap nested items from the response body](#unwrap-nested-items-from-the-response-body)
         
     | 
| 
      
 70 
     | 
    
         
            +
                    * [Determine collections from the response body](#determine-collections-from-the-response-body)
         
     | 
| 
      
 71 
     | 
    
         
            +
                    * [Load additional data based on retrieved data](#load-additional-data-based-on-retrieved-data)
         
     | 
| 
      
 72 
     | 
    
         
            +
                 * [Chain complex queries](#chain-complex-queries)
         
     | 
| 
      
 73 
     | 
    
         
            +
                    * [Chain where queries](#chain-where-queries)
         
     | 
| 
      
 74 
     | 
    
         
            +
                    * [Expand plain collections of links: expanded](#expand-plain-collections-of-links-expanded)
         
     | 
| 
      
 75 
     | 
    
         
            +
                    * [Error handling with chains](#error-handling-with-chains)
         
     | 
| 
      
 76 
     | 
    
         
            +
                    * [Resolve chains: fetch](#resolve-chains-fetch)
         
     | 
| 
      
 77 
     | 
    
         
            +
                    * [Add request options to a query chain: options](#add-request-options-to-a-query-chain-options)
         
     | 
| 
      
 78 
     | 
    
         
            +
                    * [Control pagination within a query chain](#control-pagination-within-a-query-chain)
         
     | 
| 
      
 79 
     | 
    
         
            +
                 * [Record pagination](#record-pagination)
         
     | 
| 
      
 80 
     | 
    
         
            +
                    * [Pagination strategy](#pagination-strategy)
         
     | 
| 
      
 81 
     | 
    
         
            +
                       * [Pagination strategy: offset (default)](#pagination-strategy-offset-default)
         
     | 
| 
      
 82 
     | 
    
         
            +
                       * [Pagination strategy: page](#pagination-strategy-page)
         
     | 
| 
      
 83 
     | 
    
         
            +
                       * [Pagination strategy: start](#pagination-strategy-start)
         
     | 
| 
      
 84 
     | 
    
         
            +
                       * [Pagination strategy: link](#pagination-strategy-link)
         
     | 
| 
      
 85 
     | 
    
         
            +
                    * [Pagination keys](#pagination-keys)
         
     | 
| 
      
 86 
     | 
    
         
            +
                       * [limit_key](#limit_key)
         
     | 
| 
      
 87 
     | 
    
         
            +
                       * [pagination_key](#pagination_key)
         
     | 
| 
      
 88 
     | 
    
         
            +
                       * [total_key](#total_key)
         
     | 
| 
      
 89 
     | 
    
         
            +
                    * [Pagination links](#pagination-links)
         
     | 
| 
      
 90 
     | 
    
         
            +
                       * [next?](#next)
         
     | 
| 
      
 91 
     | 
    
         
            +
                       * [previous?](#previous)
         
     | 
| 
      
 92 
     | 
    
         
            +
                    * [Kaminari support (limited)](#kaminari-support-limited)
         
     | 
| 
      
 93 
     | 
    
         
            +
                 * [Build, create and update records](#build-create-and-update-records)
         
     | 
| 
      
 94 
     | 
    
         
            +
                    * [Create new records](#create-new-records)
         
     | 
| 
      
 95 
     | 
    
         
            +
                       * [create](#create)
         
     | 
| 
      
 96 
     | 
    
         
            +
                          * [Unwrap nested data when creation response nests created record data](#unwrap-nested-data-when-creation-response-nests-created-record-data)
         
     | 
| 
      
 97 
     | 
    
         
            +
                          * [Create records through associations: Nested sub resources](#create-records-through-associations-nested-sub-resources)
         
     | 
| 
      
 98 
     | 
    
         
            +
                    * [Start building new records](#start-building-new-records)
         
     | 
| 
      
 99 
     | 
    
         
            +
                    * [Change/Update existing records](#changeupdate-existing-records)
         
     | 
| 
      
 100 
     | 
    
         
            +
                       * [save](#save)
         
     | 
| 
      
 101 
     | 
    
         
            +
                       * [update](#update)
         
     | 
| 
      
 102 
     | 
    
         
            +
                       * [partial_update](#partial_update)
         
     | 
| 
      
 103 
     | 
    
         
            +
                    * [Endpoint url parameter injection during record creation/change](#endpoint-url-parameter-injection-during-record-creationchange)
         
     | 
| 
      
 104 
     | 
    
         
            +
                    * [Record validation](#record-validation)
         
     | 
| 
      
 105 
     | 
    
         
            +
                       * [Configure record validations](#configure-record-validations)
         
     | 
| 
      
 106 
     | 
    
         
            +
                       * [HTTP Status Codes for validation errors](#http-status-codes-for-validation-errors)
         
     | 
| 
      
 107 
     | 
    
         
            +
                       * [Reset validation errors](#reset-validation-errors)
         
     | 
| 
      
 108 
     | 
    
         
            +
                       * [Add validation errors](#add-validation-errors)
         
     | 
| 
      
 109 
     | 
    
         
            +
                       * [Validation errors for nested data](#validation-errors-for-nested-data)
         
     | 
| 
      
 110 
     | 
    
         
            +
                       * [Translation of validation errors](#translation-of-validation-errors)
         
     | 
| 
      
 111 
     | 
    
         
            +
                       * [Validation error types: errors vs. warnings](#validation-error-types-errors-vs-warnings)
         
     | 
| 
      
 112 
     | 
    
         
            +
                          * [Persistance failed: errors](#persistance-failed-errors)
         
     | 
| 
      
 113 
     | 
    
         
            +
                          * [Persistance succeeded: warnings](#persistance-succeeded-warnings)
         
     | 
| 
      
 114 
     | 
    
         
            +
                       * [Using ActiveModel::Validations none the less](#using-activemodelvalidations-none-the-less)
         
     | 
| 
      
 115 
     | 
    
         
            +
                    * [Use form_helper to create and update records](#use-form_helper-to-create-and-update-records)
         
     | 
| 
      
 116 
     | 
    
         
            +
                 * [Destroy records](#destroy-records)
         
     | 
| 
      
 117 
     | 
    
         
            +
                 * [Record getters and setters](#record-getters-and-setters)
         
     | 
| 
      
 118 
     | 
    
         
            +
                    * [Record setters](#record-setters)
         
     | 
| 
      
 119 
     | 
    
         
            +
                    * [Record getters](#record-getters)
         
     | 
| 
      
 120 
     | 
    
         
            +
                 * [Include linked resources (hyperlinks and hypermedia)](#include-linked-resources-hyperlinks-and-hypermedia)
         
     | 
| 
      
 121 
     | 
    
         
            +
                    * [Generate links from parameters](#generate-links-from-parameters)
         
     | 
| 
      
 122 
     | 
    
         
            +
                    * [Ensure the whole linked collection is included: includes_all](#ensure-the-whole-linked-collection-is-included-includes_all)
         
     | 
| 
      
 123 
     | 
    
         
            +
                    * [Include the first linked page or single item is included: include](#include-the-first-linked-page-or-single-item-is-included-include)
         
     | 
| 
      
 124 
     | 
    
         
            +
                    * [Include various levels of linked data](#include-various-levels-of-linked-data)
         
     | 
| 
      
 125 
     | 
    
         
            +
                    * [Identify and cast known records when including records](#identify-and-cast-known-records-when-including-records)
         
     | 
| 
      
 126 
     | 
    
         
            +
                    * [Apply options for requests performed to fetch included records](#apply-options-for-requests-performed-to-fetch-included-records)
         
     | 
| 
      
 127 
     | 
    
         
            +
                 * [Record batch processing](#record-batch-processing)
         
     | 
| 
      
 128 
     | 
    
         
            +
                    * [all](#all-1)
         
     | 
| 
      
 129 
     | 
    
         
            +
                       * [Using all, when endpoint does not implement response pagination meta data](#using-all-when-endpoint-does-not-implement-response-pagination-meta-data)
         
     | 
| 
      
 130 
     | 
    
         
            +
                    * [find_each](#find_each)
         
     | 
| 
      
 131 
     | 
    
         
            +
                    * [find_in_batches](#find_in_batches)
         
     | 
| 
      
 132 
     | 
    
         
            +
                 * [Convert/Cast specific record types: becomes](#convertcast-specific-record-types-becomes)
         
     | 
| 
      
 133 
     | 
    
         
            +
                 * [Assign attributes](#assign-attributes)
         
     | 
| 
      
 134 
     | 
    
         
            +
              * [Request Cycle Cache](#request-cycle-cache)
         
     | 
| 
      
 135 
     | 
    
         
            +
                 * [Change store for LHS' request cycle cache](#change-store-for-lhs-request-cycle-cache)
         
     | 
| 
      
 136 
     | 
    
         
            +
                 * [Disable request cycle cache](#disable-request-cycle-cache)
         
     | 
| 
      
 137 
     | 
    
         
            +
              * [Automatic Authentication (OAuth)](#automatic-authentication-oauth)
         
     | 
| 
      
 138 
     | 
    
         
            +
                 * [Configure multiple auth providers (even per endpoint)](#configure-multiple-auth-providers-even-per-endpoint)
         
     | 
| 
      
 139 
     | 
    
         
            +
              * [Option Blocks](#option-blocks)
         
     | 
| 
      
 140 
     | 
    
         
            +
              * [Request tracing](#request-tracing)
         
     | 
| 
      
 141 
     | 
    
         
            +
              * [Extended Rollbar Logging](#extended-rollbar-logging)
         
     | 
| 
      
 142 
     | 
    
         
            +
              * [Testing with LHS](#testing-with-lhs)
         
     | 
| 
      
 143 
     | 
    
         
            +
                 * [Test helper](#test-helper)
         
     | 
| 
      
 144 
     | 
    
         
            +
                    * [Stub](#stub)
         
     | 
| 
      
 145 
     | 
    
         
            +
                       * [stub_all](#stub_all)
         
     | 
| 
      
 146 
     | 
    
         
            +
                 * [Test query chains](#test-query-chains)
         
     | 
| 
      
 147 
     | 
    
         
            +
                    * [By explicitly resolving the chain: fetch](#by-explicitly-resolving-the-chain-fetch)
         
     | 
| 
      
 148 
     | 
    
         
            +
                    * [Without resolving the chain: where_values_hash](#without-resolving-the-chain-where_values_hash)
         
     | 
| 
      
 149 
     | 
    
         
            +
              * [License](#license)
         
     | 
| 
      
 150 
     | 
    
         
            +
             
     | 
| 
      
 151 
     | 
    
         
            +
             
     | 
| 
       149 
152 
     | 
    
         | 
| 
       150 
153 
     | 
    
         
             
            ## Installation/Startup checklist
         
     | 
| 
       151 
154 
     | 
    
         | 
| 
         @@ -2444,6 +2447,104 @@ LHS.configure do |config| 
     | 
|
| 
       2444 
2447 
     | 
    
         
             
            end
         
     | 
| 
       2445 
2448 
     | 
    
         
             
            ```
         
     | 
| 
       2446 
2449 
     | 
    
         | 
| 
      
 2450 
     | 
    
         
            +
            ## Automatic Authentication (OAuth)
         
     | 
| 
      
 2451 
     | 
    
         
            +
             
     | 
| 
      
 2452 
     | 
    
         
            +
            LHS provides a way to have records automatically fetch and use OAuth authentication when performing requests within Rails.
         
     | 
| 
      
 2453 
     | 
    
         
            +
             
     | 
| 
      
 2454 
     | 
    
         
            +
            In order to enable automatic oauth authentication, perform the following steps:
         
     | 
| 
      
 2455 
     | 
    
         
            +
             
     | 
| 
      
 2456 
     | 
    
         
            +
            1. Make sure LHS is configured to perform `auto_oauth`. Provide a block that, when executed in the controller context, returns a valid access_token/bearer_token.
         
     | 
| 
      
 2457 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 2458 
     | 
    
         
            +
            # config/initializers/lhs.rb
         
     | 
| 
      
 2459 
     | 
    
         
            +
             
     | 
| 
      
 2460 
     | 
    
         
            +
            LHS.configure do |config|
         
     | 
| 
      
 2461 
     | 
    
         
            +
              config.auto_oauth = -> { access_token }
         
     | 
| 
      
 2462 
     | 
    
         
            +
            end
         
     | 
| 
      
 2463 
     | 
    
         
            +
            ```
         
     | 
| 
      
 2464 
     | 
    
         
            +
             
     | 
| 
      
 2465 
     | 
    
         
            +
            2. Opt-in records requiring oauth authentication:
         
     | 
| 
      
 2466 
     | 
    
         
            +
             
     | 
| 
      
 2467 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 2468 
     | 
    
         
            +
            # app/models/record.rb
         
     | 
| 
      
 2469 
     | 
    
         
            +
             
     | 
| 
      
 2470 
     | 
    
         
            +
            class Record < LHS::Record
         
     | 
| 
      
 2471 
     | 
    
         
            +
              oauth
         
     | 
| 
      
 2472 
     | 
    
         
            +
              # ...
         
     | 
| 
      
 2473 
     | 
    
         
            +
            end
         
     | 
| 
      
 2474 
     | 
    
         
            +
            ```
         
     | 
| 
      
 2475 
     | 
    
         
            +
             
     | 
| 
      
 2476 
     | 
    
         
            +
            3. Include the `LHS::OAuth` context into your application controller:
         
     | 
| 
      
 2477 
     | 
    
         
            +
             
     | 
| 
      
 2478 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 2479 
     | 
    
         
            +
            # app/controllers/application_controller.rb
         
     | 
| 
      
 2480 
     | 
    
         
            +
             
     | 
| 
      
 2481 
     | 
    
         
            +
            class ApplicationController < ActionController::Base
         
     | 
| 
      
 2482 
     | 
    
         
            +
              include LHS::OAuth
         
     | 
| 
      
 2483 
     | 
    
         
            +
             
     | 
| 
      
 2484 
     | 
    
         
            +
              # ...
         
     | 
| 
      
 2485 
     | 
    
         
            +
            end
         
     | 
| 
      
 2486 
     | 
    
         
            +
            ```
         
     | 
| 
      
 2487 
     | 
    
         
            +
             
     | 
| 
      
 2488 
     | 
    
         
            +
            4. Make sure you have the `LHC::Auth` interceptor enabled:
         
     | 
| 
      
 2489 
     | 
    
         
            +
             
     | 
| 
      
 2490 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 2491 
     | 
    
         
            +
            # config/initializers/lhc.rb
         
     | 
| 
      
 2492 
     | 
    
         
            +
             
     | 
| 
      
 2493 
     | 
    
         
            +
            LHC.configure do |config|
         
     | 
| 
      
 2494 
     | 
    
         
            +
              config.interceptors = [LHC::Auth]
         
     | 
| 
      
 2495 
     | 
    
         
            +
            end
         
     | 
| 
      
 2496 
     | 
    
         
            +
            ```
         
     | 
| 
      
 2497 
     | 
    
         
            +
             
     | 
| 
      
 2498 
     | 
    
         
            +
            Now you can perform requests based on the record that will be auto authenticated from now on:
         
     | 
| 
      
 2499 
     | 
    
         
            +
             
     | 
| 
      
 2500 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 2501 
     | 
    
         
            +
            # app/controllers/some_controller.rb
         
     | 
| 
      
 2502 
     | 
    
         
            +
             
     | 
| 
      
 2503 
     | 
    
         
            +
            Record.find(1)
         
     | 
| 
      
 2504 
     | 
    
         
            +
            ```
         
     | 
| 
      
 2505 
     | 
    
         
            +
            ```
         
     | 
| 
      
 2506 
     | 
    
         
            +
            https://records/1
         
     | 
| 
      
 2507 
     | 
    
         
            +
            Authentication: 'Bearer token-12345'
         
     | 
| 
      
 2508 
     | 
    
         
            +
            ```
         
     | 
| 
      
 2509 
     | 
    
         
            +
             
     | 
| 
      
 2510 
     | 
    
         
            +
            ### Configure multiple auth providers (even per endpoint)
         
     | 
| 
      
 2511 
     | 
    
         
            +
             
     | 
| 
      
 2512 
     | 
    
         
            +
            In case you need to configure multiple auth provider access_tokens within your application,
         
     | 
| 
      
 2513 
     | 
    
         
            +
            make sure you provide a proc returning a hash when configuring `auto_oauth`, 
         
     | 
| 
      
 2514 
     | 
    
         
            +
            naming every single provider and the responsive method to retrieve the access_tokens in the controller context:
         
     | 
| 
      
 2515 
     | 
    
         
            +
             
     | 
| 
      
 2516 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 2517 
     | 
    
         
            +
            # config/initializers/lhs.rb
         
     | 
| 
      
 2518 
     | 
    
         
            +
            LHS.configure do |config|
         
     | 
| 
      
 2519 
     | 
    
         
            +
              config.auto_oauth = proc do
         
     | 
| 
      
 2520 
     | 
    
         
            +
                {
         
     | 
| 
      
 2521 
     | 
    
         
            +
                  provider1: access_token_provider_1,
         
     | 
| 
      
 2522 
     | 
    
         
            +
                  provider2: access_token_provider_2
         
     | 
| 
      
 2523 
     | 
    
         
            +
                }
         
     | 
| 
      
 2524 
     | 
    
         
            +
              end
         
     | 
| 
      
 2525 
     | 
    
         
            +
            end
         
     | 
| 
      
 2526 
     | 
    
         
            +
            ```
         
     | 
| 
      
 2527 
     | 
    
         
            +
             
     | 
| 
      
 2528 
     | 
    
         
            +
            Then make sure you either define which provider to use on a record level:
         
     | 
| 
      
 2529 
     | 
    
         
            +
             
     | 
| 
      
 2530 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 2531 
     | 
    
         
            +
            # model/record.rb
         
     | 
| 
      
 2532 
     | 
    
         
            +
            class Record < LHS::Record
         
     | 
| 
      
 2533 
     | 
    
         
            +
              oauth(:provider1)
         
     | 
| 
      
 2534 
     | 
    
         
            +
              #...
         
     | 
| 
      
 2535 
     | 
    
         
            +
            end
         
     | 
| 
      
 2536 
     | 
    
         
            +
            ```
         
     | 
| 
      
 2537 
     | 
    
         
            +
             
     | 
| 
      
 2538 
     | 
    
         
            +
            or on an endpoint level:
         
     | 
| 
      
 2539 
     | 
    
         
            +
             
     | 
| 
      
 2540 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 2541 
     | 
    
         
            +
            # model/record.rb
         
     | 
| 
      
 2542 
     | 
    
         
            +
            class Record < LHS::Record
         
     | 
| 
      
 2543 
     | 
    
         
            +
              endpoint 'https://service/records', oauth: :provider1
         
     | 
| 
      
 2544 
     | 
    
         
            +
              #...
         
     | 
| 
      
 2545 
     | 
    
         
            +
            end
         
     | 
| 
      
 2546 
     | 
    
         
            +
            ```
         
     | 
| 
      
 2547 
     | 
    
         
            +
             
     | 
| 
       2447 
2548 
     | 
    
         
             
            ## Option Blocks
         
     | 
| 
       2448 
2549 
     | 
    
         | 
| 
       2449 
2550 
     | 
    
         
             
            In order to apply options to all requests performed in a give block, LHS provides option blocks.
         
     | 
    
        data/lhs.gemspec
    CHANGED
    
    | 
         @@ -32,7 +32,7 @@ Gem::Specification.new do |s| 
     | 
|
| 
       32 
32 
     | 
    
         
             
              s.add_development_dependency 'pry'
         
     | 
| 
       33 
33 
     | 
    
         
             
              s.add_development_dependency 'pry-byebug'
         
     | 
| 
       34 
34 
     | 
    
         
             
              s.add_development_dependency 'rails', '>= 4.2.11'
         
     | 
| 
       35 
     | 
    
         
            -
              s.add_development_dependency 'rollbar'
         
     | 
| 
      
 35 
     | 
    
         
            +
              s.add_development_dependency 'rollbar', '<= 2.24.0'
         
     | 
| 
       36 
36 
     | 
    
         
             
              s.add_development_dependency 'rspec-rails', '>= 3.7.0'
         
     | 
| 
       37 
37 
     | 
    
         
             
              s.add_development_dependency 'rubocop', '~> 0.57.1'
         
     | 
| 
       38 
38 
     | 
    
         
             
              s.add_development_dependency 'rubocop-rspec', '~> 1.26.0'
         
     | 
    
        data/lib/lhs.rb
    CHANGED
    
    | 
         @@ -22,6 +22,12 @@ module LHS 
     | 
|
| 
       22 
22 
     | 
    
         
             
              autoload :Inspect,
         
     | 
| 
       23 
23 
     | 
    
         
             
                'lhs/concerns/inspect'
         
     | 
| 
       24 
24 
     | 
    
         
             
              module Interceptors
         
     | 
| 
      
 25 
     | 
    
         
            +
                module AutoOauth
         
     | 
| 
      
 26 
     | 
    
         
            +
                  autoload :ThreadRegistry,
         
     | 
| 
      
 27 
     | 
    
         
            +
                    'lhs/interceptors/auto_oauth/thread_registry'
         
     | 
| 
      
 28 
     | 
    
         
            +
                  autoload :Interceptor,
         
     | 
| 
      
 29 
     | 
    
         
            +
                    'lhs/interceptors/auto_oauth/interceptor'
         
     | 
| 
      
 30 
     | 
    
         
            +
                end
         
     | 
| 
       25 
31 
     | 
    
         
             
                module RequestCycleCache
         
     | 
| 
       26 
32 
     | 
    
         
             
                  autoload :ThreadRegistry,
         
     | 
| 
       27 
33 
     | 
    
         
             
                    'lhs/interceptors/request_cycle_cache/thread_registry'
         
     | 
| 
         @@ -41,6 +47,8 @@ module LHS 
     | 
|
| 
       41 
47 
     | 
    
         
             
                'lhs/concerns/is_href'
         
     | 
| 
       42 
48 
     | 
    
         
             
              autoload :Item,
         
     | 
| 
       43 
49 
     | 
    
         
             
                'lhs/item'
         
     | 
| 
      
 50 
     | 
    
         
            +
              autoload :OAuth,
         
     | 
| 
      
 51 
     | 
    
         
            +
                'lhs/concerns/o_auth.rb'
         
     | 
| 
       44 
52 
     | 
    
         
             
              autoload :OptionBlocks,
         
     | 
| 
       45 
53 
     | 
    
         
             
                'lhs/concerns/option_blocks'
         
     | 
| 
       46 
54 
     | 
    
         
             
              autoload :Pagination,
         
     | 
| 
         @@ -27,11 +27,28 @@ module AutoloadRecords 
     | 
|
| 
       27 
27 
     | 
    
         
             
                      @app.call(env)
         
     | 
| 
       28 
28 
     | 
    
         
             
                    end
         
     | 
| 
       29 
29 
     | 
    
         | 
| 
       30 
     | 
    
         
            -
                    def self. 
     | 
| 
       31 
     | 
    
         
            -
                      Dir.glob(Rails.root.join('app', 'models', '**', '*.rb')) 
     | 
| 
       32 
     | 
    
         
            -
             
     | 
| 
      
 30 
     | 
    
         
            +
                    def self.model_files
         
     | 
| 
      
 31 
     | 
    
         
            +
                      Dir.glob(Rails.root.join('app', 'models', '**', '*.rb'))
         
     | 
| 
      
 32 
     | 
    
         
            +
                    end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                    def self.require_direct_inheritance
         
     | 
| 
      
 35 
     | 
    
         
            +
                      model_files.map do |file|
         
     | 
| 
      
 36 
     | 
    
         
            +
                        next unless File.read(file).match('LHS::Record')
         
     | 
| 
      
 37 
     | 
    
         
            +
                        require_dependency file
         
     | 
| 
      
 38 
     | 
    
         
            +
                        file.split('models/').last.gsub('.rb', '').classify
         
     | 
| 
      
 39 
     | 
    
         
            +
                      end.compact
         
     | 
| 
      
 40 
     | 
    
         
            +
                    end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                    def self.require_inheriting_records(parents)
         
     | 
| 
      
 43 
     | 
    
         
            +
                      model_files.each do |file|
         
     | 
| 
      
 44 
     | 
    
         
            +
                        next if parents.none? { |parent| File.read(file).match(parent) }
         
     | 
| 
      
 45 
     | 
    
         
            +
                        require_dependency file
         
     | 
| 
       33 
46 
     | 
    
         
             
                      end
         
     | 
| 
       34 
47 
     | 
    
         
             
                    end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                    def self.require_records
         
     | 
| 
      
 50 
     | 
    
         
            +
                      require_inheriting_records(require_direct_inheritance)
         
     | 
| 
      
 51 
     | 
    
         
            +
                    end
         
     | 
| 
       35 
52 
     | 
    
         
             
                  end
         
     | 
| 
       36 
53 
     | 
    
         
             
                end
         
     | 
| 
       37 
54 
     | 
    
         
             
              end
         
     | 
| 
         @@ -0,0 +1,25 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'active_support'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module LHS
         
     | 
| 
      
 6 
     | 
    
         
            +
              module OAuth
         
     | 
| 
      
 7 
     | 
    
         
            +
                extend ActiveSupport::Concern
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                included do
         
     | 
| 
      
 10 
     | 
    
         
            +
                  prepend_before_action :lhs_store_oauth_access_token
         
     | 
| 
      
 11 
     | 
    
         
            +
                end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                private
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                def lhs_store_oauth_access_token
         
     | 
| 
      
 16 
     | 
    
         
            +
                  lhs_check_auto_oauth_enabled!
         
     | 
| 
      
 17 
     | 
    
         
            +
                  LHS::Interceptors::AutoOauth::ThreadRegistry.access_token = instance_exec(&LHS.config.auto_oauth)
         
     | 
| 
      
 18 
     | 
    
         
            +
                end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                def lhs_check_auto_oauth_enabled!
         
     | 
| 
      
 21 
     | 
    
         
            +
                  return if LHS.config.auto_oauth.present? && LHS.config.auto_oauth.is_a?(Proc)
         
     | 
| 
      
 22 
     | 
    
         
            +
                  raise 'You have to enable LHS.config.auto_oauth by passing a proc returning an access token!'
         
     | 
| 
      
 23 
     | 
    
         
            +
                end
         
     | 
| 
      
 24 
     | 
    
         
            +
              end
         
     | 
| 
      
 25 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -12,45 +12,62 @@ class LHS::Record 
     | 
|
| 
       12 
12 
     | 
    
         
             
                mattr_accessor :configuration
         
     | 
| 
       13 
13 
     | 
    
         | 
| 
       14 
14 
     | 
    
         
             
                module ClassMethods
         
     | 
| 
       15 
     | 
    
         
            -
                  def configuration(args)
         
     | 
| 
       16 
     | 
    
         
            -
                     
     | 
| 
      
 15 
     | 
    
         
            +
                  def configuration(args = nil)
         
     | 
| 
      
 16 
     | 
    
         
            +
                    if !args.nil?
         
     | 
| 
      
 17 
     | 
    
         
            +
                      @configuration = args
         
     | 
| 
      
 18 
     | 
    
         
            +
                    else
         
     | 
| 
      
 19 
     | 
    
         
            +
                      @configuration || {}
         
     | 
| 
      
 20 
     | 
    
         
            +
                    end
         
     | 
| 
      
 21 
     | 
    
         
            +
                  end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                  def auto_oauth?
         
     | 
| 
      
 24 
     | 
    
         
            +
                    LHS.config.auto_oauth && configuration && auto_oauth
         
     | 
| 
      
 25 
     | 
    
         
            +
                  end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                  def auto_oauth
         
     | 
| 
      
 28 
     | 
    
         
            +
                    configuration.fetch(:auto_oauth, false)
         
     | 
| 
      
 29 
     | 
    
         
            +
                  end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                  def oauth(provider = nil)
         
     | 
| 
      
 32 
     | 
    
         
            +
                    value = provider || true
         
     | 
| 
      
 33 
     | 
    
         
            +
                    configuration.present? ? configuration.merge!(auto_oauth: value) : configuration(auto_oauth: value)
         
     | 
| 
       17 
34 
     | 
    
         
             
                  end
         
     | 
| 
       18 
35 
     | 
    
         | 
| 
       19 
36 
     | 
    
         
             
                  def item_key
         
     | 
| 
       20 
37 
     | 
    
         
             
                    symbolize_unless_complex(
         
     | 
| 
       21 
     | 
    
         
            -
                       
     | 
| 
      
 38 
     | 
    
         
            +
                      configuration.dig(:item_key) || :item
         
     | 
| 
       22 
39 
     | 
    
         
             
                    )
         
     | 
| 
       23 
40 
     | 
    
         
             
                  end
         
     | 
| 
       24 
41 
     | 
    
         | 
| 
       25 
42 
     | 
    
         
             
                  def items_key
         
     | 
| 
       26 
43 
     | 
    
         
             
                    symbolize_unless_complex(
         
     | 
| 
       27 
     | 
    
         
            -
                       
     | 
| 
      
 44 
     | 
    
         
            +
                      configuration.dig(:items_key) || :items
         
     | 
| 
       28 
45 
     | 
    
         
             
                    )
         
     | 
| 
       29 
46 
     | 
    
         
             
                  end
         
     | 
| 
       30 
47 
     | 
    
         | 
| 
       31 
48 
     | 
    
         
             
                  def item_created_key
         
     | 
| 
       32 
49 
     | 
    
         
             
                    symbolize_unless_complex(
         
     | 
| 
       33 
     | 
    
         
            -
                       
     | 
| 
      
 50 
     | 
    
         
            +
                      configuration.dig(:item_created_key)
         
     | 
| 
       34 
51 
     | 
    
         
             
                    )
         
     | 
| 
       35 
52 
     | 
    
         
             
                  end
         
     | 
| 
       36 
53 
     | 
    
         | 
| 
       37 
54 
     | 
    
         
             
                  def limit_key(type = nil)
         
     | 
| 
       38 
55 
     | 
    
         
             
                    symbolize_unless_complex(
         
     | 
| 
       39 
     | 
    
         
            -
                      pagination_parameter( 
     | 
| 
      
 56 
     | 
    
         
            +
                      pagination_parameter(configuration.dig(:limit_key), type) ||
         
     | 
| 
       40 
57 
     | 
    
         
             
                      :limit
         
     | 
| 
       41 
58 
     | 
    
         
             
                    )
         
     | 
| 
       42 
59 
     | 
    
         
             
                  end
         
     | 
| 
       43 
60 
     | 
    
         | 
| 
       44 
61 
     | 
    
         
             
                  def total_key
         
     | 
| 
       45 
62 
     | 
    
         
             
                    symbolize_unless_complex(
         
     | 
| 
       46 
     | 
    
         
            -
                       
     | 
| 
      
 63 
     | 
    
         
            +
                      configuration.dig(:total_key) || :total
         
     | 
| 
       47 
64 
     | 
    
         
             
                    )
         
     | 
| 
       48 
65 
     | 
    
         
             
                  end
         
     | 
| 
       49 
66 
     | 
    
         | 
| 
       50 
67 
     | 
    
         
             
                  # Key used for determine current page
         
     | 
| 
       51 
68 
     | 
    
         
             
                  def pagination_key(type = nil)
         
     | 
| 
       52 
69 
     | 
    
         
             
                    symbolize_unless_complex(
         
     | 
| 
       53 
     | 
    
         
            -
                      pagination_parameter( 
     | 
| 
      
 70 
     | 
    
         
            +
                      pagination_parameter(configuration.dig(:pagination_key), type) ||
         
     | 
| 
       54 
71 
     | 
    
         
             
                      :offset
         
     | 
| 
       55 
72 
     | 
    
         
             
                    )
         
     | 
| 
       56 
73 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -58,15 +75,15 @@ class LHS::Record 
     | 
|
| 
       58 
75 
     | 
    
         
             
                  # Strategy used for calculationg next pages and navigate pages
         
     | 
| 
       59 
76 
     | 
    
         
             
                  def pagination_strategy
         
     | 
| 
       60 
77 
     | 
    
         
             
                    symbolize_unless_complex(
         
     | 
| 
       61 
     | 
    
         
            -
                       
     | 
| 
      
 78 
     | 
    
         
            +
                      configuration.dig(:pagination_strategy) || :offset
         
     | 
| 
       62 
79 
     | 
    
         
             
                    )
         
     | 
| 
       63 
80 
     | 
    
         
             
                  end
         
     | 
| 
       64 
81 
     | 
    
         | 
| 
       65 
82 
     | 
    
         
             
                  # Allows record to be configured as not paginated,
         
     | 
| 
       66 
83 
     | 
    
         
             
                  # as by default it's considered paginated
         
     | 
| 
       67 
84 
     | 
    
         
             
                  def paginated
         
     | 
| 
       68 
     | 
    
         
            -
                    return true if  
     | 
| 
       69 
     | 
    
         
            -
                     
     | 
| 
      
 85 
     | 
    
         
            +
                    return true if configuration.blank?
         
     | 
| 
      
 86 
     | 
    
         
            +
                    configuration.fetch(:paginated, true)
         
     | 
| 
       70 
87 
     | 
    
         
             
                  end
         
     | 
| 
       71 
88 
     | 
    
         | 
| 
       72 
89 
     | 
    
         
             
                  private
         
     |