R – fresh_when in ruby not working with xml rendering

cachingetagruby

While trying to implement support for conditional GETting in a rest system, we have come across the fresh_when and stale? methods.

The following code works fine with 304 and not further rendering:
if stale?(:etag => resource, :last_modified => resource.updated_at.utc)
respond_to do |format|
format.html # show.html.erb
}
end
end

But accessing 1.xml will try to render the resource twice:

if stale?(:etag => resource, :last_modified => resource.updated_at.utc)
  respond_to do |format|
    format.html # show.html.erb
    format.xml  { 
      render :xml => @order.to_xml(:controller => self, :except => [:paid_at]) 
      }
  end
end

The error message:

ActionController::DoubleRenderError in OrdersController#show

Can only render or redirect once per action

RAILS_ROOT: /Users/guilherme/Documents/ruby/restfulie-test
Application Trace | Framework Trace | Full Trace

/Library/Ruby/Gems/1.8/gems/actionpack-2.3.4/lib/action_controller/base.rb:900:in render_without_benchmark'
/Library/Ruby/Gems/1.8/gems/actionpack-2.3.4/lib/action_controller/benchmarking.rb:51:in
render'
/Library/Ruby/Gems/1.8/gems/activesupport-2.3.4/lib/active_support/core_ext/benchmark.rb:17:in ms'
/Library/Ruby/Gems/1.8/gems/activesupport-2.3.4/lib/active_support/core_ext/benchmark.rb:10:in
realtime'
/Library/Ruby/Gems/1.8/gems/activesupport-2.3.4/lib/active_support/core_ext/benchmark.rb:17:in ms'
/Library/Ruby/Gems/1.8/gems/actionpack-2.3.4/lib/action_controller/benchmarking.rb:51:in
render'
/Library/Ruby/Gems/1.8/gems/actionpack-2.3.4/lib/action_controller/base.rb:1331:in send'
/Library/Ruby/Gems/1.8/gems/actionpack-2.3.4/lib/action_controller/base.rb:1331:in
perform_action_without_filters'
/Library/Ruby/Gems/1.8/gems/actionpack-2.3.4/lib/action_controller/filters.rb:617:in call_filters'
/Library/Ruby/Gems/1.8/gems/actionpack-2.3.4/lib/action_controller/filters.rb:610:in
perform_action_without_benchmark'
/Library/Ruby/Gems/1.8/gems/actionpack-2.3.4/lib/action_controller/benchmarking.rb:68:in perform_action_without_rescue'
/Library/Ruby/Gems/1.8/gems/activesupport-2.3.4/lib/active_support/core_ext/benchmark.rb:17:in
ms'
/Library/Ruby/Gems/1.8/gems/activesupport-2.3.4/lib/active_support/core_ext/benchmark.rb:10:in realtime'
/Library/Ruby/Gems/1.8/gems/activesupport-2.3.4/lib/active_support/core_ext/benchmark.rb:17:in
ms'
/Library/Ruby/Gems/1.8/gems/actionpack-2.3.4/lib/action_controller/benchmarking.rb:68:in perform_action_without_rescue'
/Library/Ruby/Gems/1.8/gems/actionpack-2.3.4/lib/action_controller/rescue.rb:160:in
perform_action_without_flash'
/Library/Ruby/Gems/1.8/gems/actionpack-2.3.4/lib/action_controller/flash.rb:146:in perform_action'
/Library/Ruby/Gems/1.8/gems/actionpack-2.3.4/lib/action_controller/base.rb:532:in
send'
/Library/Ruby/Gems/1.8/gems/actionpack-2.3.4/lib/action_controller/base.rb:532:in process_without_filters'
/Library/Ruby/Gems/1.8/gems/actionpack-2.3.4/lib/action_controller/filters.rb:606:in
process'
/Library/Ruby/Gems/1.8/gems/actionpack-2.3.4/lib/action_controller/base.rb:391:in process'
/Library/Ruby/Gems/1.8/gems/actionpack-2.3.4/lib/action_controller/base.rb:386:in
call'
/Library/Ruby/Gems/1.8/gems/actionpack-2.3.4/lib/action_controller/routing/route_set.rb:437:in `call'

Any suggestions?

Regards

Best Answer

Not sure if you found the solution to this, but i just had the very same problem rendering js

the solution i found was to use the inverse:

def index
  if stale?(:etag => [request.host],
            :public => true)
    respond_to do |format|
      format.js
    end
  end
end

replacing [request.host] withou whatever youre using to determine freshness, of course.