1

I have the following wildcard routes & constraints setup ...

get '*path' => 'profiles#show', constraints: SlugConstraint.new
get '*path' => 'blogs#show', constraints: SlugConstraint.new

and

class SlugConstraint
  def initialize
    @slugs = Slug.all.map(&:name)
  end

  def matches?(request)
    request.url =~ /\/(.+)/
    @slugs.include?($1)
  end
end

... a variation based on the issue I described here: Rails wildcard route with database lookup & multiple controllers

My issue now is that if the first call to SlugConstraint.new returns false (so that the 2nd routes.rb SlugConstraint.new now gets called) I don't want to have to redo the call to:

Slug.all.map(&:name)

How do I properly save (or scope) the @slugs data from the first constraint call that failed, so that I can access it if needed in the next constraint call?

Thanks.

Community
  • 1
  • 1
kayatela
  • 394
  • 5
  • 21
  • 1
    My apologies here, I know that the `matches?` logic does not make sense and in both instances false would be returned here, so it makes no difference. My issue is with how to save the data between constraint calls, not with the logic of `matches?` – kayatela Jul 18 '14 at 08:59

1 Answers1

1

Routing

You're not going to be able to use 2 routing patterns for the same path

When you send a request to Rails (or any other MVC application), Rails will take the path you've sent & consequently try to assign the right route (controller#action) for it.

This happens sequentially - IE Rails will look through your routes from top -> bottom until it finds one which corresponds. As you have two routes to match the same path, you're not going to be able to use the set up you have

enter image description here

--

App-Wide Slugs

What you're looking for is something called app-wide slugs - which essentially means you're able to manage a single slug path, and have a system in the back-end to accommodate it.

You're on the brink of being able to achieve this, and whilst I don't have any code to help, I do have an idea, which I found here:

#config/routes.rb
get '*path' => MyRouter.new, constraints: SlugConstraint.new

#lib/my_router.rb
class MyRouter
  def call(env)
    # Matched from routes, you can access all matched parameters
    view_name= env['action_dispatch.request.path_parameters'][:view_name]

    # Compute these the way you like, possibly using view_name
    controller= 'post' 
    my_action= 'show'

    controller_class= (controller + '_controller').camelize.constantize
    controller_class.action(my_action.to_sym).call(env)
  end
end

This will allow you to pick up the slugged paths, whilst routing to the correct controller. This is TOTALLY untested & just a stab in the dark - if you want to go over it with me, comment & we can have a look

Community
  • 1
  • 1
Richard Peck
  • 76,116
  • 9
  • 93
  • 147
  • Thanks for your answer Rich, I will see where this takes me. For the record [the 2nd answer here](http://stackoverflow.com/questions/3028981/constraints-in-ruby-on-rails-routing) was my original inspiration, and I had some successful initial tests, apart from my original question about scope & not wanting to repeat DB calls. For my Ruby knowledge, it would still also be great to know what I'm doing wrong with classes and scope. – kayatela Jul 18 '14 at 14:50