Extract kwargs to fix 2.7 warnings

Related: gitlab-org/gitlab#257438 (closed)

It fixes 2.7 warning related to actionpack-6.0.3.3/lib/action_dispatch/testing/integration.rb:418

https://github.com/rails/rails/blob/v6.0.3.3/actionpack/lib/action_dispatch/testing/integration.rb#L425 already contains ruby2_keywords, so the reason happens somewhere up in the chain.

The stacktrace from running: rspec './ee/spec/requests/api/wikis_spec.rb[1:6:3:2:1]'

 "/Users/igordrozdov/.asdf/installs/ruby/2.7.2/lib/ruby/gems/2.7.0/gems/actionpack-6.0.3.4/lib/action_dispatch/testing/integration.rb:419:in `method_missing'",
 "/Users/igordrozdov/.asdf/installs/ruby/2.7.2/lib/ruby/gems/2.7.0/gems/grape-path-helpers-1.5.0/lib/grape-path-helpers/named_route_matcher.rb:7:in `method_missing'",
 "/Users/igordrozdov/.asdf/installs/ruby/2.7.2/lib/ruby/gems/2.7.0/gems/rails-controller-testing-1.0.5/lib/rails/controller/testing/template_assertions.rb:62:in `process'",
 "/Users/igordrozdov/Documents/Projects/gdk-new/gitlab/spec/support/helpers/workhorse_helpers.rb:75:in `workhorse_request_with_multiple_files'",
 "/Users/igordrozdov/Documents/Projects/gdk-new/gitlab/spec/support/helpers/workhorse_helpers.rb:51:in `workhorse_request_with_file'",
 "/Users/igordrozdov/Documents/Projects/gdk-new/gitlab/spec/support/helpers/workhorse_helpers.rb:27:in `workhorse_post_with_file'",
 "/Users/igordrozdov/Documents/Projects/gdk-new/gitlab/spec/support/shared_examples/lib/wikis_api_examples.rb:140:in `block (2 levels) in <main>'",

Since the calling of process method goes through grape-path-helpers, we need to properly propagate it.

At first I came up with a solution that squashes kwargs into segments:

    def method_missing(method_id, *args, **kwargs)
      return super unless method_id.to_s =~ /_path$/

      first_arg, *rest_args = args
      segments = first_arg || {}

      unless segments.is_a?(Hash)
        raise ArgumentError, 'Helper options must be a hash'
      end

      segments.merge!(kwargs) # in case options were passed as kwargs

      route = Grape::API::Instance.decorated_routes.detect do |r|
        route_match?(r, method_id, segments)
      end

      if route
        route.send(method_id, segments, *rest_args)
      else
        super
      end
    end

But maybe let's just extract path-methods-logic into a separate method and leave the propagation logic in the method-missing, it looks more safe:

    def method_missing(method_id, *args, **kwargs)
      return super unless method_id.to_s =~ /_path$/

      success, result = call_path_method(method_id, *args, **kwargs)

      if success
        result
      else
        super
      end
    end

    def call_path_method(method_id, *arguments)
      segments = arguments.first || {}

      route = Grape::API::Instance.decorated_routes.detect do |r|
        route_match?(r, method_id, segments)
      end

      return false unless route

      [true, route.send(method_id, *arguments)]
    end
Edited by Igor Drozdov

Merge request reports

Loading