promoted-ruby-client 0.1.16 → 0.1.20
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/.github/workflows/push-pull-requests_check.yml +16 -0
- data/Gemfile.lock +1 -1
- data/README.md +75 -5
- data/dev.md +1 -1
- data/lib/promoted/ruby/client.rb +22 -14
- data/lib/promoted/ruby/client/constants.rb +7 -0
- data/lib/promoted/ruby/client/faraday_http_client.rb +2 -1
- data/lib/promoted/ruby/client/pager.rb +4 -4
- data/lib/promoted/ruby/client/request_builder.rb +47 -17
- data/lib/promoted/ruby/client/util.rb +26 -3
- data/lib/promoted/ruby/client/version.rb +1 -1
- data/promoted-ruby-client.gemspec +1 -0
- metadata +4 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 340cf31fbc7680c1b9abb8df8dd1226e4a13fed103e21815afb82fb43b85f481
         | 
| 4 | 
            +
              data.tar.gz: d5448efcb375ac090847ac6c37fcda3b57babf0dca6043d82967e8ecdb42ae52
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: df18a2f73308fd9771b55a8762592a4041059b5d5fe72e0de07fa9566eb8627647eef75276a401c6f9da7d03bfc7158deb94bfd6b5824d22635a22b7d11848f0
         | 
| 7 | 
            +
              data.tar.gz: 7ed68c19270dcd13b8ed2347138aa845dd767d19bc257312e1a001f0e858879e75186142b9719b31e9c132d95fc7d48049baaf3e57b442f39f2b969cf2c835b8
         | 
| @@ -0,0 +1,16 @@ | |
| 1 | 
            +
            name: Pull-Requests Check
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            on: [push, pull_request]
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            jobs:
         | 
| 6 | 
            +
              Test:
         | 
| 7 | 
            +
                runs-on: ubuntu-latest
         | 
| 8 | 
            +
                steps:
         | 
| 9 | 
            +
                - uses: actions/checkout@v2
         | 
| 10 | 
            +
                - uses: ruby/setup-ruby@v1
         | 
| 11 | 
            +
                  with:
         | 
| 12 | 
            +
                    ruby-version: 2.5.1
         | 
| 13 | 
            +
                    bundler-cache: true
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                - name: Build and test with rspec
         | 
| 16 | 
            +
                  run: bundle exec rspec spec
         | 
    
        data/Gemfile.lock
    CHANGED
    
    
    
        data/README.md
    CHANGED
    
    | @@ -94,7 +94,73 @@ Field Name | Type | Optional? | Description | |
| 94 94 | 
             
            ```:request_id``` | String | Yes | Generated by the SDK when needed (*do not set*)
         | 
| 95 95 | 
             
            ```:content_id``` | String | No | Identifier for the content to be shown, must be set.
         | 
| 96 96 | 
             
            ```:properties``` | Properties | Yes | Any additional custom properties to associate. For v1 integrations, it is fine not to fill in all the properties.
         | 
| 97 | 
            +
            ---
         | 
| 98 | 
            +
            ### Size
         | 
| 99 | 
            +
            User's screen dimensions.
         | 
| 100 | 
            +
            Field Name | Type | Optional? | Description
         | 
| 101 | 
            +
            ---------- | ---- | --------- | -----------
         | 
| 102 | 
            +
            ```:width``` | Integer | No | Screen width
         | 
| 103 | 
            +
            ```:height``` | Integer | No | Screen height
         | 
| 104 | 
            +
            ---
         | 
| 97 105 |  | 
| 106 | 
            +
            ### Screen
         | 
| 107 | 
            +
            State of the screen including scaling.
         | 
| 108 | 
            +
            Field Name | Type | Optional? | Description
         | 
| 109 | 
            +
            ---------- | ---- | --------- | -----------
         | 
| 110 | 
            +
            ```:size``` | Size | Yes | Screen size
         | 
| 111 | 
            +
            ```:scale``` | Float | Yes | Current screen scaling factor
         | 
| 112 | 
            +
            ---
         | 
| 113 | 
            +
             | 
| 114 | 
            +
            ### ClientHints
         | 
| 115 | 
            +
            Alternative to user-agent strings. See https://raw.githubusercontent.com/snowplow/iglu-central/master/schemas/org.ietf/http_client_hints/jsonschema/1-0-0
         | 
| 116 | 
            +
            Field Name | Type | Optional? | Description
         | 
| 117 | 
            +
            ---------- | ---- | --------- | -----------
         | 
| 118 | 
            +
            ```:is_mobile``` | Boolean | Yes | Mobile flag
         | 
| 119 | 
            +
            ```:brand``` | Array of ClientBrandHint | Yes |
         | 
| 120 | 
            +
            ```:architecture``` | String | Yes |
         | 
| 121 | 
            +
            ```:model``` | String | Yes |
         | 
| 122 | 
            +
            ```:platform``` | String | Yes |
         | 
| 123 | 
            +
            ```:platform_version``` | String | Yes |
         | 
| 124 | 
            +
            ```:ua_full_version``` | String | Yes |
         | 
| 125 | 
            +
             | 
| 126 | 
            +
            ---
         | 
| 127 | 
            +
            ### ClientBrandHint
         | 
| 128 | 
            +
            See https://raw.githubusercontent.com/snowplow/iglu-central/master/schemas/org.ietf/http_client_hints/jsonschema/1-0-0
         | 
| 129 | 
            +
            Field Name | Type | Optional? | Description
         | 
| 130 | 
            +
            ---------- | ---- | --------- | -----------
         | 
| 131 | 
            +
            ```:brand``` | String | Yes | Mobile flag
         | 
| 132 | 
            +
            ```:version``` | String | Yes |
         | 
| 133 | 
            +
             | 
| 134 | 
            +
            ---
         | 
| 135 | 
            +
            ### Location
         | 
| 136 | 
            +
            Information about the user's location.
         | 
| 137 | 
            +
            Field Name | Type | Optional? | Description
         | 
| 138 | 
            +
            ---------- | ---- | --------- | -----------
         | 
| 139 | 
            +
            ```:latitude``` | Float | No | Location latitude
         | 
| 140 | 
            +
            ```:longitude``` | Float | No | Location longitude
         | 
| 141 | 
            +
            ```:accuracy_in_meters``` | Integer | Yes | Location accuracy if available
         | 
| 142 | 
            +
            ---
         | 
| 143 | 
            +
             | 
| 144 | 
            +
            ### Browser
         | 
| 145 | 
            +
            Information about the user's browser.
         | 
| 146 | 
            +
            Field Name | Type | Optional? | Description
         | 
| 147 | 
            +
            ---------- | ---- | --------- | -----------
         | 
| 148 | 
            +
            ```:user_agent``` | String | Yes | Browser user agent string
         | 
| 149 | 
            +
            ```:viewport_size``` | Size | Yes | Size of the browser viewport
         | 
| 150 | 
            +
            ```:client_hints``` | ClientHints | Yes | HTTP client hints structure
         | 
| 151 | 
            +
            ---
         | 
| 152 | 
            +
            ### Device
         | 
| 153 | 
            +
            Information about the user's device.
         | 
| 154 | 
            +
            Field Name | Type | Optional? | Description
         | 
| 155 | 
            +
            ---------- | ---- | --------- | -----------
         | 
| 156 | 
            +
            ```:device_type``` | one of (`UNKNOWN_DEVICE_TYPE`, `DESKTOP`, `MOBILE`, `TABLET`) | Yes | Type of device
         | 
| 157 | 
            +
            ```:brand``` | String | Yes | "Apple, "google", Samsung", etc.
         | 
| 158 | 
            +
            ```:manufacturer``` | String | Yes | "Apple", "HTC", Motorola", "HUAWEI", etc.
         | 
| 159 | 
            +
            ```:identifier``` | String | Yes | Android: android.os.Build.MODEL; iOS: iPhoneXX,YY, etc.
         | 
| 160 | 
            +
            ```:screen``` | Screen | Yes | Screen dimensions
         | 
| 161 | 
            +
            ```:ip_address``` | String | Yes | Originating IP address
         | 
| 162 | 
            +
            ```:location``` | Location | Yes | Location information
         | 
| 163 | 
            +
            ```:browser``` | Browser | Yes | Browser information
         | 
| 98 164 | 
             
            ---
         | 
| 99 165 | 
             
            ### Paging
         | 
| 100 166 | 
             
            #### TODO
         | 
| @@ -108,6 +174,7 @@ Field Name | Type | Optional? | Description | |
| 108 174 | 
             
            ```:use_case``` | String | Yes | One of the use case values, i.e. 'FEED' (see [constants.rb](https://github.com/promotedai/promoted-ruby-client/blob/main/lib/promoted/ruby/client/constants.rb)).
         | 
| 109 175 | 
             
            ```:properties``` | Properties | Yes | Any additional custom properties to associate.
         | 
| 110 176 | 
             
            ```:paging``` | Paging | Yes | Paging parameters (see TODO)
         | 
| 177 | 
            +
            ```:device``` | Device | Yes | Device information (as available)
         | 
| 111 178 | 
             
            ---
         | 
| 112 179 | 
             
            ### MetricsRequest
         | 
| 113 180 | 
             
            Input to ```prepare_for_logging```
         | 
| @@ -142,6 +209,8 @@ Field Name | Type | Optional? | Description | |
| 142 209 | 
             
            ---------- | ---- | --------- | -----------
         | 
| 143 210 | 
             
            ```:insertion``` | [] of Insertion | No | The insertions, which are from Delivery API (when ```deliver``` was called, i.e. we weren't either only-log or part of an experiment) or the input insertions (when the other conditions don't hold).
         | 
| 144 211 | 
             
            ```:log_request``` | LogRequest | Yes | A message suitable for logging to Metrics API via ```send_log_request```. If the call to ```deliver``` was made (i.e. the request was not part of the CONTROL arm of an experiment or marked to only log), ```:log_request``` will not be set, as you can assume logging was performed on the server-side by Promoted.
         | 
| 212 | 
            +
            ```:client_request_id``` | String | Yes | Client-generated request id sent to Delivery API and may be useful for logging and debugging.
         | 
| 213 | 
            +
            ```:execution_server``` | one of 'API' or 'SDK' | Yes | Indicates if response insertions on a delivery request came from the API or the SDK.
         | 
| 145 214 | 
             
            ---
         | 
| 146 215 |  | 
| 147 216 | 
             
            ### PromotedClient
         | 
| @@ -219,12 +288,13 @@ metrics_request = { | |
| 219 288 | 
             
            }
         | 
| 220 289 |  | 
| 221 290 | 
             
            # OPTIONAL: You can pass a custom function to "compact" insertions before metrics logging.
         | 
| 222 | 
            -
            # Note that the PromotedClient has a class method helper,  | 
| 223 | 
            -
             | 
| 224 | 
            -
             | 
| 225 | 
            -
               | 
| 291 | 
            +
            # Note that the PromotedClient has a class method helper, remove_all_properties, that does
         | 
| 292 | 
            +
            # an implementation of this, returning nil to remove ALL properties.
         | 
| 293 | 
            +
            to_compact_metrics_properties_func = Proc.new do |properties|
         | 
| 294 | 
            +
              properties[:struct].delete(:active)
         | 
| 295 | 
            +
              properties
         | 
| 226 296 | 
             
            end
         | 
| 227 | 
            -
            # metrics_request[: | 
| 297 | 
            +
            # metrics_request[:to_compact_metrics_properties_func] = to_compact_metrics_properties_func
         | 
| 228 298 |  | 
| 229 299 | 
             
            # Create a client
         | 
| 230 300 | 
             
            client = Promoted::Ruby::Client::PromotedClient.new
         | 
    
        data/dev.md
    CHANGED
    
    | @@ -4,5 +4,5 @@ | |
| 4 4 | 
             
            2. Get credentials for deployment from 1password.
         | 
| 5 5 | 
             
            3. Modify `promoted-ruby-client.gemspec`'s push block.
         | 
| 6 6 | 
             
            4. Run `gem build promoted-ruby-client.gemspec` to generate `gem`.
         | 
| 7 | 
            -
            5. Run (using new output) `gem push promoted-ruby-client-0.1. | 
| 7 | 
            +
            5. Run (using new output) `gem push promoted-ruby-client-0.1.20.gem`
         | 
| 8 8 | 
             
            6. Update README with new version.
         | 
    
        data/lib/promoted/ruby/client.rb
    CHANGED
    
    | @@ -30,18 +30,16 @@ module Promoted | |
| 30 30 | 
             
                    end
         | 
| 31 31 |  | 
| 32 32 | 
             
                    ##            
         | 
| 33 | 
            -
                    # A common compact method implementation.
         | 
| 34 | 
            -
                    def self. | 
| 35 | 
            -
                      Proc.new do | | 
| 36 | 
            -
                         | 
| 37 | 
            -
                        insertion.delete(:properties)
         | 
| 38 | 
            -
                        insertion
         | 
| 33 | 
            +
                    # A common compact properties method implementation.
         | 
| 34 | 
            +
                    def self.remove_all_properties
         | 
| 35 | 
            +
                      Proc.new do |properties|
         | 
| 36 | 
            +
                        nil
         | 
| 39 37 | 
             
                      end
         | 
| 40 38 | 
             
                    end
         | 
| 41 39 |  | 
| 42 40 | 
             
                    ##
         | 
| 43 41 | 
             
                    # Create and configure a new Promoted client.
         | 
| 44 | 
            -
                    def initialize | 
| 42 | 
            +
                    def initialize(params={})
         | 
| 45 43 | 
             
                      @perform_checks = true
         | 
| 46 44 | 
             
                      if params[:perform_checks] != nil
         | 
| 47 45 | 
             
                        @perform_checks = params[:perform_checks]
         | 
| @@ -115,7 +113,7 @@ module Promoted | |
| 115 113 | 
             
                    ##
         | 
| 116 114 | 
             
                    # Make a delivery request. If @perform_checks is set, input validation will occur and possibly raise errors.
         | 
| 117 115 | 
             
                    def deliver args, headers={}
         | 
| 118 | 
            -
                      args = Promoted::Ruby::Client::Util. | 
| 116 | 
            +
                      args = Promoted::Ruby::Client::Util.translate_hash(args)
         | 
| 119 117 |  | 
| 120 118 | 
             
                      # Respect the enabled state
         | 
| 121 119 | 
             
                      if !@enabled
         | 
| @@ -177,7 +175,7 @@ module Promoted | |
| 177 175 |  | 
| 178 176 | 
             
                          insertions_from_delivery = (response != nil && !deliver_err);
         | 
| 179 177 | 
             
                          response_insertions = delivery_request_builder.fill_details_from_response(
         | 
| 180 | 
            -
                            response  | 
| 178 | 
            +
                            response && response[:insertion] || [])
         | 
| 181 179 | 
             
                        end
         | 
| 182 180 | 
             
                      end
         | 
| 183 181 |  | 
| @@ -212,7 +210,9 @@ module Promoted | |
| 212 210 |  | 
| 213 211 | 
             
                      client_response = {
         | 
| 214 212 | 
             
                        insertion: response_insertions,
         | 
| 215 | 
            -
                        log_request: log_req
         | 
| 213 | 
            +
                        log_request: log_req,
         | 
| 214 | 
            +
                        execution_server: insertions_from_delivery ? Promoted::Ruby::Client::EXECUTION_SERVER['API'] : Promoted::Ruby::Client::EXECUTION_SERVER['SDK'],
         | 
| 215 | 
            +
                        client_request_id: delivery_request_builder.client_request_id
         | 
| 216 216 | 
             
                      }
         | 
| 217 217 | 
             
                      return client_response
         | 
| 218 218 | 
             
                    end
         | 
| @@ -221,7 +221,7 @@ module Promoted | |
| 221 221 | 
             
                    # Generate a log request for a subsequent call to send_log_request
         | 
| 222 222 | 
             
                    # or for logging via alternative means.
         | 
| 223 223 | 
             
                    def prepare_for_logging args, headers={}
         | 
| 224 | 
            -
                      args = Promoted::Ruby::Client::Util. | 
| 224 | 
            +
                      args = Promoted::Ruby::Client::Util.translate_hash(args)
         | 
| 225 225 |  | 
| 226 226 | 
             
                      if !@enabled
         | 
| 227 227 | 
             
                        return {
         | 
| @@ -318,7 +318,7 @@ module Promoted | |
| 318 318 |  | 
| 319 319 | 
             
                        ellapsed_time = Time.now - start_time
         | 
| 320 320 | 
             
                        @logger.debug("Sync send_request completed in #{ellapsed_time.to_f * 1000} ms") if @logger
         | 
| 321 | 
            -
             | 
| 321 | 
            +
                      end
         | 
| 322 322 |  | 
| 323 323 | 
             
                      return resp
         | 
| 324 324 | 
             
                    end
         | 
| @@ -334,9 +334,17 @@ module Promoted | |
| 334 334 | 
             
                      delivery_request_builder = RequestBuilder.new
         | 
| 335 335 | 
             
                      delivery_request_builder.set_request_params args
         | 
| 336 336 |  | 
| 337 | 
            -
                      delivery_request_params = delivery_request_builder.delivery_request_params | 
| 337 | 
            +
                      delivery_request_params = delivery_request_builder.delivery_request_params
         | 
| 338 338 | 
             
                      delivery_request_params[:client_info][:traffic_type] = Promoted::Ruby::Client::TRAFFIC_TYPE['SHADOW']
         | 
| 339 339 |  | 
| 340 | 
            +
                      begin
         | 
| 341 | 
            +
                        @pager.validate_paging(delivery_request_builder.full_insertion, delivery_request_builder.request[:paging])
         | 
| 342 | 
            +
                      rescue InvalidPagingError => err
         | 
| 343 | 
            +
                        # Invalid input, log and skip.
         | 
| 344 | 
            +
                        @logger.warn("Shadow traffic call failed with invalid paging #{err}") if @logger
         | 
| 345 | 
            +
                        return
         | 
| 346 | 
            +
                      end
         | 
| 347 | 
            +
             | 
| 340 348 | 
             
                      # Call Delivery API and log/ignore errors.
         | 
| 341 349 | 
             
                      start_time = Time.now
         | 
| 342 350 | 
             
                      response = nil
         | 
| @@ -349,7 +357,7 @@ module Promoted | |
| 349 357 |  | 
| 350 358 | 
             
                      if !@async_shadow_traffic
         | 
| 351 359 | 
             
                        ellapsed_time = Time.now - start_time
         | 
| 352 | 
            -
                        insertions = response  | 
| 360 | 
            +
                        insertions = response && response[:insertion] || []
         | 
| 353 361 | 
             
                        @logger.info("Shadow traffic call completed in #{ellapsed_time.to_f * 1000} ms with #{insertions.length} insertions") if @logger
         | 
| 354 362 | 
             
                      end
         | 
| 355 363 | 
             
                    end
         | 
| @@ -32,6 +32,13 @@ module Promoted | |
| 32 32 | 
             
                  CLIENT_TYPE = {'UNKNOWN_REQUEST_CLIENT' => 'UNKNOWN_REQUEST_CLIENT',
         | 
| 33 33 | 
             
                                 'PLATFORM_SERVER' => 'PLATFORM_SERVER',
         | 
| 34 34 | 
             
                                 'PLATFORM_CLIENT' => 'PLATFORM_CLIENT'}
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                  EXECUTION_SERVER = {'API' => 'API', 'SDK' => 'SDK'}
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                  DEVICE_TYPE = {'UNKNOWN_DEVICE_TYPE' => 'UNKNOWN_DEVICE_TYPE',
         | 
| 39 | 
            +
                                 'DESKTOP' => 'DESKTOP',
         | 
| 40 | 
            +
                                 'MOBILE' => 'MOBILE',
         | 
| 41 | 
            +
                                 'TABLET' => 'TABLET'}
         | 
| 35 42 | 
             
                end
         | 
| 36 43 | 
             
              end
         | 
| 37 44 | 
             
            end
         | 
| @@ -1,5 +1,6 @@ | |
| 1 1 | 
             
            require 'faraday'
         | 
| 2 2 | 
             
            require 'faraday_middleware'
         | 
| 3 | 
            +
            require 'promoted/ruby/client/util'
         | 
| 3 4 |  | 
| 4 5 | 
             
            module Promoted
         | 
| 5 6 | 
             
                module Ruby
         | 
| @@ -28,7 +29,7 @@ module Promoted | |
| 28 29 |  | 
| 29 30 | 
             
                              norm_headers = response.headers.transform_keys(&:downcase)
         | 
| 30 31 | 
             
                              if norm_headers["content-type"] != nil && norm_headers["content-type"].start_with?("application/json")
         | 
| 31 | 
            -
                                JSON.parse(response.body | 
| 32 | 
            +
                                Promoted::Ruby::Client::Util.translate_hash(JSON.parse(response.body))
         | 
| 32 33 | 
             
                              else
         | 
| 33 34 | 
             
                                response.body
         | 
| 34 35 | 
             
                              end
         | 
| @@ -11,13 +11,13 @@ module Promoted | |
| 11 11 | 
             
                    end
         | 
| 12 12 |  | 
| 13 13 | 
             
                    class Pager
         | 
| 14 | 
            -
                        def validate_paging | 
| 14 | 
            +
                        def validate_paging(insertions, paging)
         | 
| 15 15 | 
             
                          if paging && paging[:offset] && paging[:offset] >= insertions.length
         | 
| 16 16 | 
             
                            raise InvalidPagingError.new("Invalid page offset (insertion size #{insertions.length}, offset #{paging[:offset]})", [])
         | 
| 17 17 | 
             
                          end
         | 
| 18 18 | 
             
                        end
         | 
| 19 19 |  | 
| 20 | 
            -
                        def apply_paging | 
| 20 | 
            +
                        def apply_paging(insertions, insertion_page_type, paging = nil)
         | 
| 21 21 | 
             
                          begin
         | 
| 22 22 | 
             
                            validate_paging(insertions, paging)
         | 
| 23 23 | 
             
                          rescue InvalidPagingError => err
         | 
| @@ -47,7 +47,7 @@ module Promoted | |
| 47 47 | 
             
                            size = insertions.length
         | 
| 48 48 | 
             
                          end
         | 
| 49 49 |  | 
| 50 | 
            -
                          final_insertion_size = [size, insertions.length].min
         | 
| 50 | 
            +
                          final_insertion_size = [size, insertions.length - index].min
         | 
| 51 51 | 
             
                          insertion_page = Array.new(final_insertion_size)
         | 
| 52 52 | 
             
                          0.upto(final_insertion_size - 1) {|i|
         | 
| 53 53 | 
             
                            insertion = insertions[index]
         | 
| @@ -63,5 +63,5 @@ module Promoted | |
| 63 63 | 
             
                        end
         | 
| 64 64 | 
             
                    end
         | 
| 65 65 | 
             
                  end
         | 
| 66 | 
            -
             | 
| 66 | 
            +
                end
         | 
| 67 67 | 
             
            end
         | 
| @@ -2,9 +2,9 @@ module Promoted | |
| 2 2 | 
             
              module Ruby
         | 
| 3 3 | 
             
                module Client
         | 
| 4 4 | 
             
                  class RequestBuilder
         | 
| 5 | 
            -
                    attr_reader   :session_id, :only_log, :experiment, :client_info,
         | 
| 6 | 
            -
                                  :view_id, :insertion, : | 
| 7 | 
            -
                                  :request_id, :full_insertion, :use_case, :request, : | 
| 5 | 
            +
                    attr_reader   :session_id, :only_log, :experiment, :client_info, :device,
         | 
| 6 | 
            +
                                  :view_id, :insertion, :to_compact_delivery_properties_func,
         | 
| 7 | 
            +
                                  :request_id, :full_insertion, :use_case, :request, :to_compact_metrics_properties_func
         | 
| 8 8 |  | 
| 9 9 | 
             
                    attr_accessor :timing, :user_info, :platform_id
         | 
| 10 10 |  | 
| @@ -24,13 +24,14 @@ module Promoted | |
| 24 24 | 
             
                      @session_id              = request[:session_id]
         | 
| 25 25 | 
             
                      @platform_id             = request[:platform_id]
         | 
| 26 26 | 
             
                      @client_info             = request[:client_info] || {}
         | 
| 27 | 
            +
                      @device                  = request[:device] || {}
         | 
| 27 28 | 
             
                      @view_id                 = request[:view_id]
         | 
| 28 29 | 
             
                      @use_case                = Promoted::Ruby::Client::USE_CASES[request[:use_case]] || Promoted::Ruby::Client::USE_CASES['UNKNOWN_USE_CASE']
         | 
| 29 30 | 
             
                      @full_insertion          = args[:full_insertion]
         | 
| 30 31 | 
             
                      @user_info               = request[:user_info] || { :user_id => nil, :log_user_id => nil}
         | 
| 31 32 | 
             
                      @timing                  = request[:timing] || { :client_log_timestamp => Time.now.to_i }
         | 
| 32 | 
            -
                      @ | 
| 33 | 
            -
                      @ | 
| 33 | 
            +
                      @to_compact_metrics_properties_func       = args[:to_compact_metrics_properties_func]
         | 
| 34 | 
            +
                      @to_compact_delivery_properties_func      = args[:to_compact_delivery_properties_func]
         | 
| 34 35 |  | 
| 35 36 | 
             
                      # If the user didn't create a client request id, we do it for them.
         | 
| 36 37 | 
             
                      request[:client_request_id] = request[:client_request_id] || @id_generator.newID
         | 
| @@ -52,11 +53,12 @@ module Promoted | |
| 52 53 | 
             
                    end
         | 
| 53 54 |  | 
| 54 55 | 
             
                    # Only used in delivery
         | 
| 55 | 
            -
                    def delivery_request_params | 
| 56 | 
            +
                    def delivery_request_params
         | 
| 56 57 | 
             
                      params = {
         | 
| 57 58 | 
             
                        user_info: user_info,
         | 
| 58 59 | 
             
                        timing: timing,
         | 
| 59 60 | 
             
                        client_info: @client_info.merge({ :client_type => Promoted::Ruby::Client::CLIENT_TYPE['PLATFORM_SERVER'] }),
         | 
| 61 | 
            +
                        device: @device,
         | 
| 60 62 | 
             
                        platform_id: @platform_id,
         | 
| 61 63 | 
             
                        view_id: @view_id,
         | 
| 62 64 | 
             
                        session_id: @session_id,
         | 
| @@ -64,9 +66,9 @@ module Promoted | |
| 64 66 | 
             
                        search_query: request[:search_query],
         | 
| 65 67 | 
             
                        properties: request[:properties],
         | 
| 66 68 | 
             
                        paging: request[:paging],
         | 
| 67 | 
            -
                        client_request_id:  | 
| 69 | 
            +
                        client_request_id: client_request_id
         | 
| 68 70 | 
             
                      }
         | 
| 69 | 
            -
                      params[:insertion] =  | 
| 71 | 
            +
                      params[:insertion] = insertions_with_compact_props(@to_compact_delivery_properties_func)
         | 
| 70 72 |  | 
| 71 73 | 
             
                      params.clean!
         | 
| 72 74 | 
             
                    end
         | 
| @@ -76,11 +78,14 @@ module Promoted | |
| 76 78 | 
             
                    # to the responses.
         | 
| 77 79 | 
             
                    def fill_details_from_response response_insertions
         | 
| 78 80 | 
             
                      if !response_insertions then
         | 
| 79 | 
            -
                        response_insertions =  | 
| 81 | 
            +
                        response_insertions = []
         | 
| 80 82 | 
             
                      end
         | 
| 81 83 |  | 
| 82 84 | 
             
                      props = @full_insertion.each_with_object({}) do |insertion, hash|
         | 
| 83 | 
            -
                         | 
| 85 | 
            +
                        if insertion.has_key?(:properties)
         | 
| 86 | 
            +
                          # Don't add nil properties to response insertions.
         | 
| 87 | 
            +
                          hash[insertion[:content_id]] = insertion[:properties]
         | 
| 88 | 
            +
                        end
         | 
| 84 89 | 
             
                      end
         | 
| 85 90 |  | 
| 86 91 | 
             
                      filled_in_copy = []
         | 
| @@ -99,7 +104,8 @@ module Promoted | |
| 99 104 | 
             
                      params = {
         | 
| 100 105 | 
             
                        user_info: user_info,
         | 
| 101 106 | 
             
                        timing: timing,
         | 
| 102 | 
            -
                        client_info: @client_info
         | 
| 107 | 
            +
                        client_info: @client_info,
         | 
| 108 | 
            +
                        device: @device
         | 
| 103 109 | 
             
                      }
         | 
| 104 110 |  | 
| 105 111 | 
             
                      if @experiment
         | 
| @@ -113,18 +119,38 @@ module Promoted | |
| 113 119 | 
             
                      end
         | 
| 114 120 |  | 
| 115 121 | 
             
                      if include_insertions
         | 
| 116 | 
            -
                        params[:insertion] =  | 
| 122 | 
            +
                        params[:insertion] = compact_metrics_properties if include_insertions
         | 
| 117 123 | 
             
                        add_missing_ids_on_insertions! request, params[:insertion]
         | 
| 118 124 | 
             
                      end
         | 
| 119 125 |  | 
| 120 126 | 
             
                      params.clean!
         | 
| 121 127 | 
             
                    end
         | 
| 122 128 |  | 
| 123 | 
            -
                    def  | 
| 124 | 
            -
                      if  | 
| 129 | 
            +
                    def compact_one_insertion(insertion, compact_func)
         | 
| 130 | 
            +
                      return insertion if (!compact_func || !insertion[:properties])
         | 
| 131 | 
            +
             | 
| 132 | 
            +
                      # Only need a copy if there are properties to compact.
         | 
| 133 | 
            +
                      compact_insertion = insertion.dup
         | 
| 134 | 
            +
             | 
| 135 | 
            +
                      # Let the custom function work with a deep copy of the properties.
         | 
| 136 | 
            +
                      # There's really no way to work with a shallow copy and still be able
         | 
| 137 | 
            +
                      # to restore the correct insertion properties after a call to delivery.
         | 
| 138 | 
            +
                      new_props =  Marshal.load(Marshal.dump(insertion[:properties]))
         | 
| 139 | 
            +
                      compact_insertion[:properties] = compact_func.call(new_props)
         | 
| 140 | 
            +
                      compact_insertion.clean!
         | 
| 141 | 
            +
                      return compact_insertion
         | 
| 142 | 
            +
                    end
         | 
| 143 | 
            +
             | 
| 144 | 
            +
                    def insertions_with_compact_props(compact_func)
         | 
| 145 | 
            +
                      if !compact_func
         | 
| 146 | 
            +
                        # Nothing to do, avoid copying the whole array.
         | 
| 125 147 | 
             
                        full_insertion
         | 
| 126 148 | 
             
                      else
         | 
| 127 | 
            -
                         | 
| 149 | 
            +
                        compact_insertions = Array.new(full_insertion.length)
         | 
| 150 | 
            +
                        full_insertion.each_with_index {|insertion, index|
         | 
| 151 | 
            +
                          compact_insertions[index] = compact_one_insertion(insertion, compact_func)
         | 
| 152 | 
            +
                        }
         | 
| 153 | 
            +
                        compact_insertions
         | 
| 128 154 | 
             
                      end
         | 
| 129 155 | 
             
                    end
         | 
| 130 156 |  | 
| @@ -135,7 +161,7 @@ module Promoted | |
| 135 161 | 
             
                    end
         | 
| 136 162 |  | 
| 137 163 | 
             
                    # TODO: This looks overly complicated.
         | 
| 138 | 
            -
                    def  | 
| 164 | 
            +
                    def compact_metrics_properties
         | 
| 139 165 | 
             
                      @insertion            = [] # insertion should be set according to the compact insertion
         | 
| 140 166 | 
             
                      paging                = request[:paging] || {}
         | 
| 141 167 | 
             
                      size                  = paging[:size] ? paging[:size].to_i : 0
         | 
| @@ -155,12 +181,16 @@ module Promoted | |
| 155 181 | 
             
                        insertion_obj[:insertion_id] = @id_generator.newID
         | 
| 156 182 | 
             
                        insertion_obj[:request_id]   = request_id
         | 
| 157 183 | 
             
                        insertion_obj[:position]     = offset + index
         | 
| 158 | 
            -
                        insertion_obj                =  | 
| 184 | 
            +
                        insertion_obj                = compact_one_insertion(insertion_obj, @to_compact_metrics_properties_func)
         | 
| 159 185 | 
             
                        @insertion << insertion_obj.clean!
         | 
| 160 186 | 
             
                      end
         | 
| 161 187 | 
             
                      @insertion
         | 
| 162 188 | 
             
                    end
         | 
| 163 189 |  | 
| 190 | 
            +
                    def client_request_id
         | 
| 191 | 
            +
                      request[:client_request_id]
         | 
| 192 | 
            +
                    end
         | 
| 193 | 
            +
             | 
| 164 194 | 
             
                    private
         | 
| 165 195 |  | 
| 166 196 | 
             
                    def add_missing_ids_on_insertions! request, insertions
         | 
| @@ -2,16 +2,39 @@ module Promoted | |
| 2 2 | 
             
                module Ruby
         | 
| 3 3 | 
             
                  module Client
         | 
| 4 4 | 
             
                    module Util
         | 
| 5 | 
            -
                        def self. | 
| 5 | 
            +
                        def self.translate_array(arr)
         | 
| 6 | 
            +
                          sym_arr = Array.new(arr.length)
         | 
| 7 | 
            +
                          arr.each_with_index do |v, i|
         | 
| 8 | 
            +
                            new_v = v
         | 
| 9 | 
            +
                            case v
         | 
| 10 | 
            +
                            when Hash
         | 
| 11 | 
            +
                              new_v = translate_hash(v)
         | 
| 12 | 
            +
                            when Array
         | 
| 13 | 
            +
                              new_v = translate_array(v)
         | 
| 14 | 
            +
                            end
         | 
| 15 | 
            +
                            sym_arr[i] = new_v
         | 
| 16 | 
            +
                          end
         | 
| 17 | 
            +
                          sym_arr
         | 
| 18 | 
            +
                        end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                        def self.translate_hash(args)
         | 
| 6 21 | 
             
                          sym_hash = {}
         | 
| 7 22 | 
             
                          args.each do |k, v|
         | 
| 8 | 
            -
                             | 
| 23 | 
            +
                            new_key = k.to_s.to_underscore.to_sym
         | 
| 24 | 
            +
                            case v
         | 
| 25 | 
            +
                            when Hash
         | 
| 26 | 
            +
                              sym_hash[new_key] = translate_hash(v)
         | 
| 27 | 
            +
                            when Array
         | 
| 28 | 
            +
                              sym_hash[new_key] = translate_array(v)
         | 
| 29 | 
            +
                            else
         | 
| 30 | 
            +
                              sym_hash[new_key] = v
         | 
| 31 | 
            +
                            end
         | 
| 9 32 | 
             
                          end
         | 
| 10 33 | 
             
                          sym_hash
         | 
| 11 34 | 
             
                          rescue => e
         | 
| 12 35 | 
             
                            raise 'Unable to parse args. Please pass correct arguments. Must be JSON'
         | 
| 13 36 | 
             
                          end      
         | 
| 14 | 
            -
             | 
| 37 | 
            +
                        end
         | 
| 15 38 | 
             
                  end
         | 
| 16 39 | 
             
              end
         | 
| 17 40 | 
             
            end
         | 
| @@ -14,6 +14,7 @@ Gem::Specification.new do |spec| | |
| 14 14 | 
             
              spec.homepage      = 'https://github.com/promotedai/promoted-ruby-client'
         | 
| 15 15 | 
             
              spec.license       = 'MIT'
         | 
| 16 16 |  | 
| 17 | 
            +
              spec.metadata["allowed_push_host"] = "https://rubygems.org/"
         | 
| 17 18 | 
             
              spec.metadata["homepage_uri"] = spec.homepage
         | 
| 18 19 | 
             
              spec.metadata["source_code_uri"] = "https://github.com/promotedai/promoted-ruby-client"
         | 
| 19 20 | 
             
              spec.metadata["changelog_uri"] = "https://github.com/promotedai/promoted-ruby-client/blob/master/CHANGELOG.md"
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: promoted-ruby-client
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0.1. | 
| 4 | 
            +
              version: 0.1.20
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - scottmcmaster
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: exe
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2021- | 
| 11 | 
            +
            date: 2021-08-19 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: faraday
         | 
| @@ -123,6 +123,7 @@ extensions: [] | |
| 123 123 | 
             
            extra_rdoc_files:
         | 
| 124 124 | 
             
            - README.md
         | 
| 125 125 | 
             
            files:
         | 
| 126 | 
            +
            - ".github/workflows/push-pull-requests_check.yml"
         | 
| 126 127 | 
             
            - ".gitignore"
         | 
| 127 128 | 
             
            - Gemfile
         | 
| 128 129 | 
             
            - Gemfile.lock
         | 
| @@ -149,6 +150,7 @@ homepage: https://github.com/promotedai/promoted-ruby-client | |
| 149 150 | 
             
            licenses:
         | 
| 150 151 | 
             
            - MIT
         | 
| 151 152 | 
             
            metadata:
         | 
| 153 | 
            +
              allowed_push_host: https://rubygems.org/
         | 
| 152 154 | 
             
              homepage_uri: https://github.com/promotedai/promoted-ruby-client
         | 
| 153 155 | 
             
              source_code_uri: https://github.com/promotedai/promoted-ruby-client
         | 
| 154 156 | 
             
              changelog_uri: https://github.com/promotedai/promoted-ruby-client/blob/master/CHANGELOG.md
         |