I have a series of resources that I want only available if accessed via the JS format. Rails' route resources gives me the formats plus the standard HTML. Is there a way to specify that only the JS format routes be created?
-
1What version of Rails are you using? – Garrett Sep 09 '10 at 20:56
-
2Can you accept my answer below, its the correct one, the current selected answer is wrong and confusing the community. – koonse May 01 '13 at 17:03
7 Answers
You must wrap those routes in a scope. Constraints unfortunately don't work as expected in this case.
This is an example of such a block...
scope :format => true, :constraints => { :format => 'json' } do
get '/bar' => "bar#index_with_json"
end
More information can be found here: https://github.com/rails/rails/issues/5548

- 1,517
- 1
- 14
- 16
-
4If you're using `resources`, you don't need a scope block, just add the `:format => true` and `:constraints => ...` directly to the `resources` call. – Nathan Nov 26 '14 at 00:11
-
This worked in my case for resourcefull route. `resources :photos, format: true, constraints: 'json'` – maicher Dec 24 '14 at 11:41
-
2Unfortunately, it seems that this requires the url to have the file extension on it – stephen.hanson Jan 31 '15 at 06:55
-
3@steve.hanson to avoid the format requirement in the URL, use a lambda for constraint: `get :foo, constraints: lambda { |req| req.format == :json }`. – RocketR May 17 '17 at 12:00
-
The problem is when I wrap the route in a scope block, other code in my rails fails because the link_to command cant find this wrapped route anymore – Nathan B Jul 21 '21 at 07:06
-
1Reiterating the comment by @RocketR above, **this solution does not work**, and [it's mentioned in the rails routing documentation](https://guides.rubyonrails.org/routing.html). (See the callout starting "There is an exception for the format constraint...") You need to use a lambda for a route format constraint, not a plain hash: `constraints: lambda { |req| req.format == :json }`, or equivalently, `constraints: ->(req) { req.format == :json }` – Tom Lord Feb 23 '23 at 16:20
You just add constraints about format :
resources :photos, :constraints => {:format => /(js|json)/}

- 46,608
- 11
- 99
- 105
-
Unless I'm doing something wrong, that still allows me to access /photos as :html. I get the missing template message, when I'd expect a missing route exception. Thoughts? – Eric M. Sep 09 '10 at 20:51
-
-
Yeah, I caught that and changed it. Still doesn't work for me. I have resources :members, :controller => 'homes/members', :constraints => {:format => /js/} – Eric M. Sep 09 '10 at 21:29
-
4this will not limit requests to those formats, see my answer below for the correct implementation – koonse Feb 06 '13 at 07:32
None of the above solutions worked for me. I ended up going with this solution:
post "/test/suggestions", to: "test#suggestions", :constraints => -> (req) { req.xhr? }
Found on https://railsadventures.wordpress.com/2012/10/07/routing-only-ajax-requests-in-ror/#comment-375

- 347
- 4
- 7
how about
# routes.rb
class OnlyAjaxRequest
def matches?(request)
request.xhr?
end
end
post "/test/suggestions", to: "test#suggestions", :constraints => OnlyAjaxRequest.new
it doesn't get to the controller at all. Taken from railsadventures

- 93
- 1
- 7
If you need not only one or another than json
(cant use #xhr?
) I offer to you option below
resource :offers, only: :show, format: true, constraints: { format: 'pdf' }
Hope it helps

- 185
- 1
- 14
That's how I do it:
class OnlyAjaxRequest
def matches?(request)
request.xhr? and request.format.to_s.match(/(js|json|javascript)/).present?
end
end
match 'remote_login', to: 'remote_content#remote_login', via: [:get], :constraints => OnlyAjaxRequest.new
If you only care about the format, leave just the request.format part

- 1,625
- 1
- 17
- 15
You can use a before_filter
that raises a routing error unless the request format is MIME::JS
.
app/controllers/application_controller.rb:
class ApplicationController < ActionController::Base
before_filter :check_js
private
def check_js
raise RoutingError.new('expected application/json') unless request.format == MIME::JS
end
end
Apply this filter more surgically with :only
, :except
, and :skip_before_filter
as covered in the rails Action Controller Guide

- 1,297
- 7
- 19
-
I've used a similar approach to handle this kind of problem https://github.com/marcusg/force_format – marcus3006 Sep 29 '13 at 19:13