Hi Andrew, I'm finally back. And thanks, my day was really nice :) I hope you have enjoyed yours as well.

Please take a look at the comments inline.

Em 13-05-2012 12:23, Andrew White escreveu:
On 13 May 2012, at 14:16, Rodrigo Rosenfeld Rosas wrote:

I was not saying that it wasn't possible to write the proper routes, just that 
they don't seem very consistent.
I'm not getting why you think they're inconsistent - there's always a optional 
format parameter unless you tell it not to add one or you make it non-optional 
in the route itself.

Here is the main inconsistent issue I was referring to:

routes.rb:
get 'test/cached', format: false
get 'test/uncached', format: false

class TestController < ApplicationController
  caches_action :cached

  def cached
    render json: 1
  end

  def uncached
    render json: 1
  end
end

curl -I http://localhost:3000/test/uncached 2>/dev/null | grep Content-Type

Content-Type: application/json; charset=utf-8

curl -I http://localhost:3000/test/cached 2>/dev/null | grep Content-Type

Content-Type: text/html; charset=utf-8


I would expect "render json: xxx" to render an 'application/json' content-type independent from the :format state. This is true for uncached actions but cached actions seems to only take into account the value of :format.

Because of that, we get a very verbose route for getting it to properly work with caches_action when we only want to support the :json format:

get 'test/cached', format: false, defaults: {format: :json}

That is the other inconsistency I was talking about. I'd prefer to just read the format option as the actual format instead of the default one like in:

get 'test/cached', format: :json # that should be the same as the previous example for brevity

but the above rule would allow '/test/cached.html' for instance. I find this an inconsistency with regards to API expected behavior, although it is consistent with the current implementation.

Also, there is another problem. With this last rule, I'd need to append something like ", as: :test_cached" to be able to "expire_action :test_cached" since "expire_action action: :cached" won't work and the full line would be too lengthy: "expire_action action: :cached, format: :json".

I mean, these rules were intended to simplify rules writing of REST APIs more than actual applications that don't need responds_to.

Also, I don't understand why we have "caches_page" and "caches_action" but "expire_page" and "expire_action". For consistency sake those should be named either caches/expires or cache/expire...

I would guess that most applications won't be API ones, so many of them won't 
opt for REST and responds_to.
There are plenty of non-API apps that utilise REST and responds_to

Could you please give me an actual example where you find responds_to to be useful for applications that don't interact with external applications?

For example, if I have a '/products' and '/products.json' where the former will render an HTML that will fill the page with the products requested by the latter, I'd probably use separate actions as they do completely different things:

get '/products' => 'products#index', format: false
get '/products.json' => 'products#index_json', format: false, defaults: {format: :json}

This also makes tests easier to be written and understood.

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.
Just use a scope - :format works here as well:

scope :format =>  false do
   resources :products
end

That is exactly the block-based approach I was referring to. But the problem remains. I'd still need to write a lot for my JSON routes (defaults: {format: :json}).

You could even use a nested scope to wrap your actions that return JSON to add 
the constraints/defaults.

That would force me to write the rules in some unnatural ways. I like to group the actions not by the content-type of the response but by the involved resource instead.

...
There's a slight wrinkle here - read and write action caches always adds the 
:format so your cache file ends with .json but expire_action is essentially a 
wrapper around url_for so gives a path without the :format, making the expiry 
fail. I'll look at whether this needs addressing.

Thanks for taking a look into this. :)

In the meantime it's probably best to use formatted urls - these routes work 
fine:

constraints :format =>  'json' do
   get 'test/index', :as =>  :index
   get 'test/expire', :as =>  :expire
end

If I understand correctly, this would require me to request '/test/expire.json', right? But usually I'd write the expire action with "head :ok", returning a 'text/html' or 'text/plain' instead of 'application/json'.

You'll need to pass the format to the expire_action as it doesn't infer it from 
the current request - otherwise you could only expire JSON caches from JSON 
requests.

Or I could just pass the named routes to "expire_action", right? The named route would already contain the format information so 'expire_action' method wouldn't need to guess.

Please, don't get me wrong. I'm not against making API applications easy to write, nor I'm against responds_to. I just think that the commonest case may currently need too verbose routing rules.

That shortcoming could be minimized if we assumed the "format: :json" to restrict the only possible format to 'json' instead of using it as a default.

Please consider this change to routing DSL for Rails 4.

Best,
Rodrigo.

--
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.

Reply via email to