I was not saying that it wasn't possible to write the proper routes,
just that they don't seem very consistent.
I would guess that most applications won't be API ones, so many of them
won't opt for REST and responds_to.
For example, all applications I've been working with for the past decade
will only need to respond to a single format per action.
That means that if I wanted strict rules to my routes I'd have to write
them as:
get '/anything', format: false
or
get '/anything.:format' => 'anything#index', constraints: {format:
/json/}, defaults: {format: :json}
I could use a block for this common option except that not all of my
actions will return a JSON.
Sometimes I'll just return a "head :ok" for remove actions, for example.
But it is important that Rails always returns the correct content-type
so that my AJAX callbacks get interpreted correctly.
The only reason I have something like '/anything.json' in some of my
actions is because I want to cache some of them.
Today is Mother's day in Brazil and I'm going to leave in a few minutes
to have lunch with my mom in a near city, but I guess I've already found
some bugs.
Consider this snippets:
class TestController < ApplicationController
caches_action :index
def index
render json: 'test' #, content_type: 'application/json'
end
def expire
expire_action :index #action: :index #, format: :json
head :ok
end
end
routes.rb:
get "test/index", format: false, as: :index
# get "test/index" => 'test#index', format: false, defaults: {format:
:json}, as: :index
get "test/expire"
I've made several experiments that yield to strange results when it
comes to content-type.
Basically, I'm getting 'text/html' instead of 'application/json'. This
happens even if I pass content_type: 'application/json' explicitly.
Another bug is that expire_action doesn't seem to work correctly either.
For example, if you use the commented route the output will be:
Expire fragment views/localhost:3000/assets?controller=test
It doesn't matter if I use a named route or "expire_action action:
:index" or "expire_action action: :index, format: :json" if I remember
correctly.
Sorry, I have to leave now and I'll only be back very late at night.
Have a great Sunday,
Rodrigo.
Em 13-05-2012 06:10, Andrew White escreveu:
On 13 May 2012, at 04:10, Rodrigo Rosenfeld Rosas wrote:
What I was suggesting is that we changed the generated routes.rb so that the
Rails 1 style route could be written as
match ':controller(/:action(/:id))'
Whether you write it with or without :format it ends up being the same route -
the mapper checks for the presence of the :format key in the path. The
generator adds the :format to make it explicitly visible what's happening.
Some history on why there's an optional format would probably useful here. We
used to generate both formatted routes and non-formatted routes, e.g. you'd
have formatted_product_path(@product, :json) and product_path(@product). Upon
investigation[1][2] it was discovered that this took up significant amount of
memory and was changed to an optional segment[3] in the Rails 2.3 release.
As well as mentioning and explaining the "format" option, like some of these
examples:
post '/products/:id.:format' => 'products#show', as: :field, constraints: {id:
/\d+/} # format is required
post '/products/:id' => 'products#show', format: true, as: :field,
constraints: {id: /\d+/} # this is equivalent
post '/products/:id.json' => 'products#show', format: :json # it only answers
to json format
post '/products/:id' => 'products#show', format: :json # the same with a
shorter URL but still allowing you to cache the result and use the correct
content-type
But then I decided to test it and I was surprised that it doesn't make any
difference if you use caches_page.
Also, there are more weird rules with regards to page or action caching. The
routes rules don't seem to be respected if you use caching.
Consider this example:
get '/products' => 'products#list', format: :json
try to GET /products with caches_page enabled and you won't get a
'application/json' content-type in the next responses because it won't probably
even read the routes rules.
Page caching is explicitly designed to avoid hitting the Rails stack - you need
to setup Apache or nginx to serve the cached files from the format-less path
with the appropriate content type. Action caching should just avoid the page
rendering - if you can reproduce a case where a JSON request is action cached
and returns an incorrect content type when serving the cached file then please
create a new issue in the tracker.
Also, if you GET /products.html not only it accepts this request but the
content-type will be 'text/html' instead of 'application/json' (independent
from caching).
That's because you're defining a default format for the route not a constraint
- either use a explicit constraint or use a regexp, e.g:
get '/products' => 'products#list', :format => /json/
or
get '/products' => 'products#list', :constraints => { :format => 'json' }
The mapper assumes non-significant keys in a route definition are defaults
unless they're regexps.
Also, consider this other example:
get '/products.json' => 'products#list', format: :json
This will also respond to '/products.json.html' for example, and I don't think
it should answer to anything else but '/products.json'. Also, the content-type
declared in the routes wouldn't be respected.
That's because :format is still being appended to the route - the mapper
doesn't interpret the path you specify other than to look for segment keys and
optional segments. If you're after a format-less path that only serves JSON
then use this:
get '/products' => 'products#list', :format => false, :defaults => { :format
=> 'json' }
or if you want the extension then use this:
get '/products.json' => 'products#list', :format => false, :defaults => {
:format => 'json' }
The only way to turn off the :format segment being added is to either insert it
yourself or pass :format => false.
Maybe I'm the only one considering the current behavior an issue, but I'd like
to ask you to consider some changes in the routing rules with regards to format
to make them less loose.
If you can come up with a route that isn't supported or doesn't appear to be
supported please open a new issue. You don't need to ping me on it - I normally
take a look at all the routing issues that get created.
Andrew White
[1]: https://rails.lighthouseapp.com/projects/8994/tickets/1215
[2]: https://rails.lighthouseapp.com/projects/8994/tickets/1359
[3]:
https://github.com/rails/rails/commit/fef6c32afe2276dffa0347e25808a86e7a101af1
--
You received this message because you are subscribed to the Google Groups "Ruby on
Rails: Core" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/rubyonrails-core?hl=en.