routes constraints doesn't work for empty format #5548

refaelos opened this Issue Mar 22, 2012 · 4 comments

4 participants



I'm trying to restrict access to some of my routes to specific request formats:

constraints(:format => :json) do

The thing is that all formats other than "json" are blocked except for the empty format (meaning urls without a format in them).

Any idea how can it be solved ?


This works: constraints(lambda { |r| (r.format == :json) }) do ...

But it's just a workaround. I want to use the "regular" way to do it.

Ruby on Rails member

Here's what I'd consider the ‘regular’ way:

MyApplication::Application.routes.draw do
  resources :products, :format => true

class ProductsController < ApplicationController
  respond_to :json

  def index

  # other actions
$ rake routes
    products GET    /products.:format          products#index {:format=>true}
             POST   /products.:format          products#create {:format=>true}
 new_product GET    /products/new.:format      products#new {:format=>true}
edit_product GET    /products/:id/edit.:format products#edit {:format=>true}
     product GET    /products/:id.:format      products#show {:format=>true}
             PUT    /products/:id.:format      products#update {:format=>true}
             DELETE /products/:id.:format      products#destroy {:format=>true}

This gives you a 404 Not Found if you don't use a format and a 406 Not Acceptable if you use a format other than JSON.

For non-resource routes you can just include the format in the path:

get '/products.:format', :to => 'products#index', :format => /json/

This gives you an 404 for anything other than /products.json.

Ruby on Rails member

Closing as this is not a bug in rails. There was recently a bigger dicussion on the subject on rails core mailing list:!topic/rubyonrails-core/upWLY6WeD1U

Basically, rails automatically matches both versions of routes, with and without a format. I'm not sure what you want to achieve, but if @pixeltrix's response is not what you're looking for and you would rather like to match routes instead of using respond_to in controller, you can do it this way:

  scope :format => true, :constraints => { :format => 'json' } do
    get '/bar' => "bar#index_with_json"

  get '/bar' => "bar#index"

With such routes, when you GET /bar.json, it will match bar#index_with_json and GET /bar will match bar#index

@drogus drogus closed this May 20, 2012

@drogus I had to change my scoping to "json" to make this work or else when I have format: true, and I go to respond_with(newly_created_model) it will error out and say it can't find the route. I'm using ONLY respond_to :json and respond_with.

Tested against Rails 2.3.9

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment