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.

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

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

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

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

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

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


Andrew White

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