0

I need to conditionally set the param option in routes.

Without condition it's easy:

resources :foo, param: :uuid do
  #...
end

What I ideally want is something along the following lines (not working obviously):

resources :foo, param: ->(req) { req.env['PATH_INFO'].match?(/bar/) ? :uuid : :id } do
  #...
end
Andrey Deineko
  • 51,333
  • 10
  • 112
  • 145
  • What do you want to accomplish? Just to change the param key to `uuid`? I would stick with `:id` and handle it by using a special finder like friendly_id does. – max Apr 20 '17 at 13:14
  • @max I installed friendly_id, but only for few controllers I need to use `param: :slug`. In other controllers this resource should stay unchanged using default `param`... – Andrey Deineko Apr 20 '17 at 13:15
  • Can you use a constraint? `resources :foo, constraints: lambda { |req| req.env['PATH_INFO'].match?(/bar/) }` – Eyeslandic Apr 20 '17 at 13:15
  • @Iceman constraint is something totally different from what I need. Constraints restrict access to resource based on something, I need not to restrict access but to conditionally set `param` option. – Andrey Deineko Apr 20 '17 at 13:19
  • Yes, I know that. What my suggestion was, is to include two `resources` lines in the `routes.rb` file, one which matches and one that does not. And set your param that way. – Eyeslandic Apr 20 '17 at 13:33
  • @Iceman yea, this is one of the options I first thought of. But i will have to repeat about 90 lines of code because of that... :\ So it's the last resort option and I'd rather never use it. – Andrey Deineko Apr 20 '17 at 13:34
  • Ok, I see, that's a bit too much :) – Eyeslandic Apr 20 '17 at 13:34

1 Answers1

2

You can write a piece of middleware that alters the params:

class ParamTransformer
  def initialize(app)
    @app = app
  end

  def call(env)
    if env['PATH_INFO'].match?(/bar/)
      env.request.update_param('slug', env.request.params['id'])
    end
    @app.call(env)
  end
end

# config/application.rb
config.middleware.use 'ParamTransformer'

If you really want to do it conditionally on your routes you could create a constraint:

class ParamTransformerConstraint
  def matches?(request)
    if env['PATH_INFO'].match?(/bar/)
      request.update_param('slug', request.params['id'])
    end
    true # lets everyone through
  end
end

It feels really hacky though.

max
  • 96,212
  • 14
  • 104
  • 165