Em 14-05-2012 02:11, Andrew White escreveu:
On 14 May 2012, at 03:08, Rodrigo Rosenfeld Rosas wrote:
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.
That's because the cache action tries to infer the format from the request but
can't because there's no extension or default value for :format. It sets the
content_type to the default HTML and when you call render :json it only sets
the content_type if it is not already been set.
I'm not sure what you expect Rails to do here - how does it know to fetch the
JSON cached version if you're relying on the content_type being set by the
render? The whole point of action caching is to avoid calling render.
I was expecting the relevant headers to be cached alongside with the
body content of the response.
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.
As I said non-regexp keys are assumed to be defaults - use a regexp to make it
only accept JSON:
get 'test/caches', :format => /json/
You'd need to have the format in the url though.
Well, this is great! I don't remember that you said that by using a
regular expression it would be an enforcement instead of a default. And
I don't mind that I have to use '/test/caches.json'. At least I know
that if it is called in any other way the application will respond with
500 or any other error code.
Thank you very much!
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".
As I said you may want to expire all or some cached action formats - not just
the format of the current request and you need to tell it which format somehow.
Ah, okay, I guess I got it now.
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...
It makes sense when you look at the tense - caches_action is saying that the
controller will cache the action (i.e in the future) whereas expire_action is
actually doing it now.
So, shouldn't it be the opposite? Controller will *cache* and it
currently *expires*? :)
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?
Pagination of results - use the JSON request to provide just the results so
that they can be rendered on the client.
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}
class ProductsController
responds_to :html, :json
def index
@products = Products.paginate :page => params[:page]
responds_with(@products)
end
end
Then use something like Jbuilder or ActiveModel::Serializers to render the JSON
response and your standard ERb/Haml for the HTML response.
Okay, makes sense.
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'.
Sorry, I thought you wanted the expire action to return 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.
Named url helpers still call url_for internally so you'd still end up with a
path without a format extension.
Yeah, I had just figured it out from a previous comment of yours in this
message :)
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.
We could certainly consider whether :format => :json or :format => [:html,
:json] would restrict it to those formats (i.e. setup :constraints and :defaults
automatically), however that would have to be with :format in the path as you can't turn
it off without :format => false. Please open an issue to consider this further.
Thanks! I'll try to figure it out an API that could allow an unformatted
URL before opening the issue. If I can't come to any suggestion I'll
open the issue with the API you've just mentioned.
Wouldn't it be possible that "get '/products', format: :json" responded
to both '/products' and '/products.json' when a single format is given
instead of an array? Of course I mean that action caching should also
use the same correct content-type in the response for both URLs.
Cheers,
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.