Rails Routing Clash When Rendering Static Pages

Viewed 63

I have a routing clash. After moving all of my blog posts from /posts/:id to /:id (which is great), I now have an issue where my static pages don't contain an ID, so they aren't rendering. I don't want to have to process them through my posts controller.

Here's what I currently have in my routes.rb file:

  resources :posts, only: [:index, :create, :edit, :new, :destroy]
  get '/:id' => 'posts#show', :as => 'custom_url'
  match '/posts/:id' => redirect('/%{id}', status: 301)

But then these now don't work...

  match '/privacy' => 'static#privacy'
  match '/terms' => 'static#terms'

I have a controller called static_controller.rb which I can use if I need to. How can I jump over the /:id match.

UPDATE:

Also experiencing issues where my def update isn't updating my content.

  def update
    @post = Post.find(params[:id])

    respond_to do |format|
      if @post.update_attributes(params[:post])
        format.html { redirect_to @post, :notice => 'Post was successfully updated.' }
        format.json { head :no_content }
      else
        format.html { render :action => "edit" }
        format.json { render :json => @post.errors, :status => :unprocessable_entity }
      end
    end
  end
2 Answers

Rails matches routes from top to bottom order, so the higher to the top, the higher priority. See Rails Routing from the Outside In. If you move these routes

  match '/privacy' => 'static#privacy'
  match '/terms' => 'static#terms'

above these routes, then the static routes will have priority over the blog posts and should render correctly.

  resources :posts, only: [:index, :create, :edit, :new, :destroy]
  get '/:id' => 'posts#show', :as => 'custom_url'
  match '/posts/:id' => redirect('/%{id}', status: 301)

Note, this means if you have any blog post ids that clash with static page routes, the static pages will match and be displayed.

To avoid the scenario you are describing you should NOT match out and by-pass /posts/ with the redirect. That breaks rails pattern of hierarchy and order and will potentially make your code messier than it need to. @Chris Selemers answer is correct but as he points out there are potential (if very limited) risks with that approach.

get '/posts/:id' => 'posts#show', :as => 'custom_url'

Or better yet simply do:

resources :posts
Related