merge_params 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Changelog.md +8 -0
- data/lib/facets/hash/recursively_comparing.rb +31 -0
- data/lib/merge_params/helpers.rb +42 -28
- data/lib/merge_params/version.rb +1 -1
- data/merge_params.gemspec +1 -0
- metadata +17 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 50468b8b15c7c21253bc50acaaa50f423eb45f012373ec5d09e96d8477fa115d
         | 
| 4 | 
            +
              data.tar.gz: a3733c9745be932c2c7792aee32966a8cb5b7c36a67785b63afe9094e8858a74
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 458352f9fae2cc4f410886360880c8261466d1c1358bc52cbb40f6bc79268c1752a5a6962308ce34021da751eb392b6c46b4b78bfcc95a9ce53a6aecb2e6dfc4
         | 
| 7 | 
            +
              data.tar.gz: da60236fa26260b6d227b7923b7562f455962256f247e6fff84fdbb1c5f6008f6d2b9f653f22452bc6df0472ce1463e97e8f61f247862d433d64636ab060e05b
         | 
    
        data/Changelog.md
    CHANGED
    
    | @@ -5,6 +5,14 @@ recommendations of [keepachangelog.com](http://keepachangelog.com/). | |
| 5 5 |  | 
| 6 6 | 
             
            ## (Unreleased)
         | 
| 7 7 |  | 
| 8 | 
            +
            ## 0.4.0 (2019-02-07)
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            ### Added/Changed
         | 
| 11 | 
            +
            - Better support for nested hashes: Using `deep_symbolize_keys` instead of `symbolize_keys`.
         | 
| 12 | 
            +
            - Allow keys in nested hashes to be deleted by setting their value to nil
         | 
| 13 | 
            +
            - Add `params_from_url(url)` helper
         | 
| 14 | 
            +
            - Allow a hash to be passed as an argument to `params_for_url_for`
         | 
| 15 | 
            +
            - Add dependency on `facets` gem
         | 
| 8 16 |  | 
| 9 17 | 
             
            ## 0.3.0 (2019-01-24)
         | 
| 10 18 |  | 
| @@ -0,0 +1,31 @@ | |
| 1 | 
            +
            require 'facets/hash/recursively'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            class Hash
         | 
| 4 | 
            +
              def recursively_comparing(other_enum, path: [], &block)
         | 
| 5 | 
            +
                ComparingRecursor.new(self, other_enum, &block)
         | 
| 6 | 
            +
              end
         | 
| 7 | 
            +
             | 
| 8 | 
            +
              class ComparingRecursor < Enumerable::Recursor #:nodoc:
         | 
| 9 | 
            +
                def initialize(enum, other_enum, *types, &block)
         | 
| 10 | 
            +
                  @other_enum = other_enum
         | 
| 11 | 
            +
                  super(enum, *types, &block)
         | 
| 12 | 
            +
                end
         | 
| 13 | 
            +
                def method_missing(op, &yld)
         | 
| 14 | 
            +
                  yld = yld    || lambda{ |k,v| [k,v] }  # ? to_enum
         | 
| 15 | 
            +
                  rec = @block || yld #lambda{ |k,v| [k,v] }
         | 
| 16 | 
            +
                  @enum.__send__(op) do |k,v|
         | 
| 17 | 
            +
                    other_v = @other_enum.dig(k)
         | 
| 18 | 
            +
                    #puts %(#{@enum.inspect}: k=#{k.inspect}, v=#{v.inspect}, other_v=#{other_v.inspect})
         | 
| 19 | 
            +
                    case v
         | 
| 20 | 
            +
                    when String # b/c of 1.8
         | 
| 21 | 
            +
                      yld.call(k, v, other_v)
         | 
| 22 | 
            +
                    when *@types
         | 
| 23 | 
            +
                      res = v.recursively_comparing(other_v, &@block).__send__(op,&yld)
         | 
| 24 | 
            +
                      rec.call(k, res, other_v)
         | 
| 25 | 
            +
                    else
         | 
| 26 | 
            +
                      yld.call(k, v, other_v)
         | 
| 27 | 
            +
                    end
         | 
| 28 | 
            +
                  end
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
              end
         | 
| 31 | 
            +
            end
         | 
    
        data/lib/merge_params/helpers.rb
    CHANGED
    
    | @@ -1,25 +1,30 @@ | |
| 1 1 | 
             
            require 'uri'
         | 
| 2 | 
            +
            require 'facets/hash/deep_merge'
         | 
| 3 | 
            +
            require 'facets/hash/recurse'
         | 
| 4 | 
            +
            require 'facets/hash/recursively_comparing'
         | 
| 5 | 
            +
            require 'facets/enumerable/graph'
         | 
| 6 | 
            +
            require 'facets/hash/graph'
         | 
| 2 7 |  | 
| 3 8 | 
             
            module MergeParams::Helpers
         | 
| 4 9 | 
             
              extend ActiveSupport::Concern
         | 
| 5 10 |  | 
| 6 11 | 
             
              # request.parameters but with symbolized keys.
         | 
| 7 12 | 
             
              def request_params
         | 
| 8 | 
            -
                request.parameters. | 
| 13 | 
            +
                request.parameters.deep_symbolize_keys
         | 
| 9 14 | 
             
              end
         | 
| 10 15 |  | 
| 11 16 | 
             
              # request.parameters (which also includes POST params) but with only those keys that would
         | 
| 12 17 | 
             
              # normally be passed in a query string (without :controller, :action, :format) and with symbolized
         | 
| 13 18 | 
             
              # keys.
         | 
| 14 19 | 
             
              def query_params_from_request_params
         | 
| 15 | 
            -
                request.parameters. | 
| 16 | 
            -
                  except(*request.path_parameters. | 
| 20 | 
            +
                request.parameters.deep_symbolize_keys.
         | 
| 21 | 
            +
                  except(*request.path_parameters.deep_symbolize_keys.keys)
         | 
| 17 22 | 
             
              end
         | 
| 18 23 |  | 
| 19 24 | 
             
              # Returns a hash of params from the query string (https://en.wikipedia.org/wiki/Query_string),
         | 
| 20 25 | 
             
              # with symbolized keys.
         | 
| 21 26 | 
             
              def query_params
         | 
| 22 | 
            -
                request.query_parameters. | 
| 27 | 
            +
                request.query_parameters.deep_symbolize_keys
         | 
| 23 28 | 
             
              end
         | 
| 24 29 |  | 
| 25 30 | 
             
              # Params that can safely be passed to url_for to build a route. (Used by merge_url_for.)
         | 
| @@ -40,8 +45,9 @@ module MergeParams::Helpers | |
| 40 45 | 
             
              # (And we don't even need to pass the path_parameters on to url_for because url_for already
         | 
| 41 46 | 
             
              # includes those (from :_recall)
         | 
| 42 47 | 
             
              #
         | 
| 43 | 
            -
              def params_for_url_for
         | 
| 44 | 
            -
                params.to_unsafe_h. | 
| 48 | 
            +
              def params_for_url_for(params = params())
         | 
| 49 | 
            +
                params = params.to_unsafe_h if params.respond_to?(:to_unsafe_h)
         | 
| 50 | 
            +
                params.deep_symbolize_keys.except(
         | 
| 45 51 | 
             
                  *ActionDispatch::Routing::RouteSet::RESERVED_OPTIONS,
         | 
| 46 52 | 
             
                  :controller,
         | 
| 47 53 | 
             
                  :action,
         | 
| @@ -51,7 +57,8 @@ module MergeParams::Helpers | |
| 51 57 |  | 
| 52 58 | 
             
              # Safely merges the given params with the params from the current request
         | 
| 53 59 | 
             
              def merge_params(new_params = {})
         | 
| 54 | 
            -
                params_for_url_for. | 
| 60 | 
            +
                params_for_url_for.
         | 
| 61 | 
            +
                  merge(new_params.deep_symbolize_keys)
         | 
| 55 62 | 
             
              end
         | 
| 56 63 |  | 
| 57 64 | 
             
              # Easily extract just certain param keys.
         | 
| @@ -83,31 +90,31 @@ module MergeParams::Helpers | |
| 83 90 | 
             
              def merge_url_for(new_params = {})
         | 
| 84 91 | 
             
                url = url_for(merge_params(new_params))
         | 
| 85 92 |  | 
| 86 | 
            -
                # Now pass along in the *query string* any params that we couldn't pass to url_for because they
         | 
| 87 | 
            -
                # were reserved options.
         | 
| 88 | 
            -
                query_params_already_added = parse_nested_query(URI(url).query || '')
         | 
| 89 | 
            -
                # Some params from new_params (like company_id) that we pass in may be recognized by a route and
         | 
| 90 | 
            -
                # therefore no longer be query params. We use recognize_path to find those params that ended up
         | 
| 91 | 
            -
                # as route params instead of query_params but are nonetheless  | 
| 92 | 
            -
                params_already_added = Rails.application.routes.recognize_path(url).merge(query_params_already_added)
         | 
| 93 | 
            -
                 | 
| 94 | 
            -
                 | 
| 95 | 
            -
             | 
| 96 | 
            -
             | 
| 97 | 
            -
             | 
| 93 | 
            +
            #    # Now pass along in the *query string* any params that we couldn't pass to url_for because they
         | 
| 94 | 
            +
            #    # were reserved options.
         | 
| 95 | 
            +
            #    query_params_already_added = parse_nested_query(URI(url).query || '')
         | 
| 96 | 
            +
            #    # Some params from new_params (like company_id) that we pass in may be recognized by a route and
         | 
| 97 | 
            +
            #    # therefore no longer be query params. We use recognize_path to find those params that ended up
         | 
| 98 | 
            +
            #    # as route params instead of query_params but are nonetheless already added to the url.
         | 
| 99 | 
            +
            #    params_already_added = Rails.application.routes.recognize_path(url).merge(query_params_already_added)
         | 
| 100 | 
            +
                params_already_added = params_from_url(url)
         | 
| 101 | 
            +
                query_params_to_add = new_params.recursively_comparing(params_already_added).graph { |k,v, other|
         | 
| 102 | 
            +
                  if v.is_a?(Hash) || v.nil? || other.nil?
         | 
| 103 | 
            +
                    [k, v]
         | 
| 104 | 
            +
                  end
         | 
| 105 | 
            +
                }
         | 
| 98 106 | 
             
                add_params(query_params_to_add, url)
         | 
| 99 107 | 
             
              end
         | 
| 100 108 |  | 
| 101 109 | 
             
              # Adds params to the query string
         | 
| 102 110 | 
             
              # (Unlike url_for_merge, which tries to generate a route from the params.)
         | 
| 103 | 
            -
               | 
| 104 | 
            -
              #   UriQueryMerger.new("http://www.google.com?other=1", {jordan: "rules"}).merge
         | 
| 105 | 
            -
              # Can we make it work that way when a URL is supplied buth otherwise let the params be the first
         | 
| 106 | 
            -
              # and only argument (to optimize for that more common use case)?
         | 
| 107 | 
            -
              def add_params(params = {}, url = request.fullpath)
         | 
| 111 | 
            +
              def add_params(new_params = {}, url = request.fullpath)
         | 
| 108 112 | 
             
                uri = URI(url)
         | 
| 109 | 
            -
                 | 
| 110 | 
            -
                 | 
| 113 | 
            +
                # Allow keys that are currently in query_params to be deleted by setting their value to nil in
         | 
| 114 | 
            +
                # new_params (including in nested hashes).
         | 
| 115 | 
            +
                merged_params = parse_nested_query(uri.query || '').
         | 
| 116 | 
            +
                  deep_merge(new_params).recurse(&:compact)
         | 
| 117 | 
            +
                uri.query = Rack::Utils.build_nested_query(merged_params).presence
         | 
| 111 118 | 
             
                uri.to_s
         | 
| 112 119 | 
             
              end
         | 
| 113 120 |  | 
| @@ -121,9 +128,16 @@ module MergeParams::Helpers | |
| 121 128 | 
             
                ) if respond_to?(:helper_method)
         | 
| 122 129 | 
             
              end
         | 
| 123 130 |  | 
| 124 | 
            -
             | 
| 131 | 
            +
              # Parsing helpers
         | 
| 132 | 
            +
              def params_from_url(url)
         | 
| 133 | 
            +
                query_params = parse_nested_query(URI(url).query || '')
         | 
| 134 | 
            +
                route_params = Rails.application.routes.recognize_path(url.to_s)
         | 
| 135 | 
            +
                params_for_url_for(
         | 
| 136 | 
            +
                  route_params.merge(query_params)
         | 
| 137 | 
            +
                )
         | 
| 138 | 
            +
              end
         | 
| 125 139 |  | 
| 126 140 | 
             
              def parse_nested_query(query)
         | 
| 127 | 
            -
                Rack::Utils.parse_nested_query(query || ''). | 
| 141 | 
            +
                Rack::Utils.parse_nested_query(query || '').deep_symbolize_keys
         | 
| 128 142 | 
             
              end
         | 
| 129 143 | 
             
            end
         | 
    
        data/lib/merge_params/version.rb
    CHANGED
    
    
    
        data/merge_params.gemspec
    CHANGED
    
    | @@ -29,6 +29,7 @@ Gem::Specification.new do |spec| | |
| 29 29 | 
             
              spec.required_ruby_version = ">= 2.3.0"
         | 
| 30 30 | 
             
              spec.add_dependency "activesupport", [">= 4.2", "< 5.3"]
         | 
| 31 31 | 
             
              spec.add_dependency "actionpack", [">= 4.2", "< 5.3"]
         | 
| 32 | 
            +
              spec.add_dependency "facets"
         | 
| 32 33 |  | 
| 33 34 | 
             
              spec.add_development_dependency "bundler", "~> 1.17"
         | 
| 34 35 | 
             
              spec.add_development_dependency "rake", "~> 10.0"
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: merge_params
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0. | 
| 4 | 
            +
              version: 0.4.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Tyler Rick
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: exe
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2019- | 
| 11 | 
            +
            date: 2019-02-08 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: activesupport
         | 
| @@ -50,6 +50,20 @@ dependencies: | |
| 50 50 | 
             
                - - "<"
         | 
| 51 51 | 
             
                  - !ruby/object:Gem::Version
         | 
| 52 52 | 
             
                    version: '5.3'
         | 
| 53 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 54 | 
            +
              name: facets
         | 
| 55 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 56 | 
            +
                requirements:
         | 
| 57 | 
            +
                - - ">="
         | 
| 58 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 59 | 
            +
                    version: '0'
         | 
| 60 | 
            +
              type: :runtime
         | 
| 61 | 
            +
              prerelease: false
         | 
| 62 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 63 | 
            +
                requirements:
         | 
| 64 | 
            +
                - - ">="
         | 
| 65 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 66 | 
            +
                    version: '0'
         | 
| 53 67 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 54 68 | 
             
              name: bundler
         | 
| 55 69 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -109,6 +123,7 @@ files: | |
| 109 123 | 
             
            - Readme.md
         | 
| 110 124 | 
             
            - bin/console
         | 
| 111 125 | 
             
            - bin/setup
         | 
| 126 | 
            +
            - lib/facets/hash/recursively_comparing.rb
         | 
| 112 127 | 
             
            - lib/merge_params.rb
         | 
| 113 128 | 
             
            - lib/merge_params/helpers.rb
         | 
| 114 129 | 
             
            - lib/merge_params/version.rb
         |