This project is archived and is in readonly mode.

#5904 ✓invalid
tvdeyen

'render :template' does not halt filter chain

Reported by tvdeyen | November 1st, 2010 @ 12:31 PM

Rendering a template (a view from a specific controller) does not halt the filter chain, but rendering a file halts the chain.

class Order < ApplicationController

  before_filter :check_auth

  def new
    @order = Order.new
  end

protected

  def check_auth
    if request.xhr?
      render :file => Rails.root + 'public/404.html'
    end
  end

end

=> Filter chain halted as [:check_auth] rendered_or_redirected

class Order < ApplicationController

  before_filter :check_auth

  def new
    @order = Order.new
  end

protected

  def check_auth
    if request.xhr?
      render :template => '/user_sessions/new'
    end
  end

end

=> ActionView::TemplateError (Called id for nil, which would mistakenly be 4 -- if you really wanted the id of nil, use object_id)

Returning false inside the filter does not help.

Is there a reason for this? In my opinion rendering a template also should halt the filter chain.

Comments and changes to this ticket

  • Andrew White

    Andrew White November 1st, 2010 @ 01:05 PM

    • Importance changed from “” to “Low”

    Looks like there's an error in your template which is raising an exception before the filter chain can be halted. This would explain why returning false doesn't help.

  • tvdeyen

    tvdeyen November 1st, 2010 @ 01:09 PM

    Sorry, this is not true. The Error comes from the action which is called, because the filter chain does not halt! Not from the template. This is my template. So what error should raise here?

    <% form_for @user_session ||= UserSession.new do |f| %>
        <%= f.error_messages %>
        <p>
            <%= f.label :username, "Benutzername" %>
            <%= f.text_field :username, :class => "field" %>
        </p>
        <p>
            <%= f.label :password, "Passwort" %>
            <%= f.password_field :password, :class => "field" %>
        </p>
        <p>
            <%= f.submit %>
        </p>
    <% end %>
    
  • Andrew White

    Andrew White November 1st, 2010 @ 01:32 PM

    What's calling id on nil? Is this Rails 2.3 or 3.0?

  • tvdeyen

    tvdeyen November 1st, 2010 @ 01:46 PM

    It's Rails 2.3.9

    @order is nil inside the Order#new view. So you see, the Order#new method is called. What should not happen, because the before_filter should halt the filter chain.

  • Andrew White

    Andrew White November 1st, 2010 @ 01:53 PM

    But @order shouldn't be nil inside the view because you're assigning it a new Order instance inside the action. In your new view @order.id would be nil but the exception is saying that @order is nil. Can you post a backtrace please?

  • Andrew White

    Andrew White November 1st, 2010 @ 02:20 PM

    The reason I'm suspecting that there's an error in your user session template is that in Rails 2.3 the filter chain is halted when performed? is true. This method returns true when the @performed_render instance variable is true. This instance variable is set to true in the render_for_text method and the render_for_file method calls this method.

    Since both the render :file and render :template call render_for_file, I don't see how one could halt the filter chain and the other not halt the filter chain as they use the same code path. Your sample code in the report renders a different template in the :file example so the logical conclusion is an error in your template. That's not to say I couldn't be wrong but you need to give me more to work with!

  • tvdeyen

    tvdeyen November 1st, 2010 @ 04:12 PM

    This is sample code. I can't post the actual code here, because of privacy/legal terms. But the concept is exactly the same.

    Maybe I explain what I want to achieve and why I found this issue for better understanding:

    I have a before_filter in my Orders Controller what checks the login state. In my ApplicationController I have a method what checks this login state and, if needed, redirects to the login page. No problems here. Everything works fine with this for normal HTTP requests.

    BUT:

    For Ajax requests I can't redirect to the login page (obviously). I have to render the login template directly. And this is what causes the error. I get an error for having nil objects in my view for the url I requested what IMO should not happen, because the filter should halt the render process for this view. I should get the template I rendered inside my filter. Understand?

    Thanks

  • Andrew White

    Andrew White November 1st, 2010 @ 04:48 PM

    • State changed from “new” to “invalid”

    I know what you're trying to do - but without a backtrace I can't help any further. I've double checked by creating a test application that uses render :template in a filter and that halts the filter chain successfully. If you can come up with some steps to reproduce then I'll reopen the ticket.

  • tvdeyen
  • tvdeyen

    tvdeyen November 2nd, 2010 @ 08:53 AM

    This is the error message:

    ActionView::TemplateError (Called id for nil, which would mistakenly be 4 -- if you really wanted the id of nil, use object_id) on line #1 of app/views/orders/_form.html.erb:
    1: <% form_for @order do |form| %>
    2:     <%= form.error_messages %>
    3:     <table id="order">
    4:         <tr>
    

    And this is the backtrace:

    /Users/tvd/code/rails/webtraining/vendor/rails/actionpack/lib/action_controller/record_identifier.rb:76:in `dom_id'
    /Users/tvd/code/rails/webtraining/vendor/rails/actionpack/lib/action_view/helpers/record_identification_helper.rb:16:in `dom_id'
    /Users/tvd/code/rails/webtraining/vendor/rails/actionpack/lib/action_view/helpers/form_helper.rb:293:in `apply_form_for_options!'
    /Users/tvd/code/rails/webtraining/vendor/rails/actionpack/lib/action_view/helpers/form_helper.rb:277:in `form_for'
    /Users/tvd/code/rails/webtraining/app/views/orders/_form.html.erb:1:in `_run_erb_app47views47orders47_form46html46erb_locals_form_object'
    /Users/tvd/code/rails/webtraining/vendor/rails/actionpack/lib/action_view/renderable.rb:34:in `send'
    /Users/tvd/code/rails/webtraining/vendor/rails/actionpack/lib/action_view/renderable.rb:34:in `render'
    /Users/tvd/code/rails/webtraining/vendor/rails/actionpack/lib/action_view/base.rb:306:in `with_template'
    /Users/tvd/code/rails/webtraining/vendor/rails/actionpack/lib/action_view/renderable.rb:30:in `render'
    /Users/tvd/code/rails/webtraining/vendor/rails/actionpack/lib/action_view/renderable_partial.rb:20:in `render'
    /Users/tvd/code/rails/webtraining/vendor/rails/actionpack/lib/action_controller/benchmarking.rb:26:in `benchmark'
    /Users/tvd/code/rails/webtraining/vendor/rails/activesupport/lib/active_support/core_ext/benchmark.rb:17:in `ms'
    /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/benchmark.rb:308:in `realtime'
    /Users/tvd/code/rails/webtraining/vendor/rails/activesupport/lib/active_support/core_ext/benchmark.rb:17:in `ms'
    /Users/tvd/code/rails/webtraining/vendor/rails/actionpack/lib/action_controller/benchmarking.rb:26:in `benchmark'
    /Users/tvd/code/rails/webtraining/vendor/rails/actionpack/lib/action_view/renderable_partial.rb:19:in `render'
    /Users/tvd/code/rails/webtraining/vendor/rails/actionpack/lib/action_view/template.rb:205:in `render_template'
    /Users/tvd/code/rails/webtraining/vendor/rails/actionpack/lib/action_view/renderable_partial.rb:44:in `render_partial'
    /Users/tvd/code/rails/webtraining/vendor/rails/actionpack/lib/action_view/partials.rb:184:in `render_partial'
    /Users/tvd/code/rails/webtraining/vendor/rails/actionpack/lib/action_view/base.rb:267:in `render'
    /Users/tvd/code/rails/webtraining/app/views/user_sessions/new.html.erb:1:in `_run_erb_app47views47user_sessions47new46html46erb'
    /Users/tvd/code/rails/webtraining/vendor/rails/actionpack/lib/action_view/renderable.rb:34:in `send'
    /Users/tvd/code/rails/webtraining/vendor/rails/actionpack/lib/action_view/renderable.rb:34:in `render'
    /Users/tvd/code/rails/webtraining/vendor/rails/actionpack/lib/action_view/base.rb:306:in `with_template'
    /Users/tvd/code/rails/webtraining/vendor/rails/actionpack/lib/action_view/renderable.rb:30:in `render'
    /Users/tvd/code/rails/webtraining/vendor/rails/actionpack/lib/action_view/template.rb:205:in `render_template'
    /Users/tvd/code/rails/webtraining/vendor/rails/actionpack/lib/action_view/base.rb:265:in `render'
    /Users/tvd/code/rails/webtraining/vendor/rails/actionpack/lib/action_controller/base.rb:1250:in `render_for_file'
    /Users/tvd/code/rails/webtraining/vendor/rails/actionpack/lib/action_controller/base.rb:936:in `render_without_benchmark'
    /Users/tvd/code/rails/webtraining/vendor/rails/actionpack/lib/action_controller/benchmarking.rb:51:in `render'
    /Users/tvd/code/rails/webtraining/vendor/rails/activesupport/lib/active_support/core_ext/benchmark.rb:17:in `ms'
    /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/benchmark.rb:308:in `realtime'
    /Users/tvd/code/rails/webtraining/vendor/rails/activesupport/lib/active_support/core_ext/benchmark.rb:17:in `ms'
    /Users/tvd/code/rails/webtraining/vendor/rails/actionpack/lib/action_controller/benchmarking.rb:51:in `render'
    /Users/tvd/code/rails/webtraining/app/controllers/application_controller.rb:147:in `permission_denied'
    /Library/Ruby/Gems/1.8/gems/declarative_authorization-0.5.1/lib/declarative_authorization/in_controller.rb:128:in `send'
    /Library/Ruby/Gems/1.8/gems/declarative_authorization-0.5.1/lib/declarative_authorization/in_controller.rb:128:in `filter_access_filter'
    /Users/tvd/code/rails/webtraining/vendor/rails/activesupport/lib/active_support/callbacks.rb:178:in `send'
    /Users/tvd/code/rails/webtraining/vendor/rails/activesupport/lib/active_support/callbacks.rb:178:in `evaluate_method'
    /Users/tvd/code/rails/webtraining/vendor/rails/activesupport/lib/active_support/callbacks.rb:166:in `call'
    /Users/tvd/code/rails/webtraining/vendor/rails/actionpack/lib/action_controller/filters.rb:225:in `call'
    /Users/tvd/code/rails/webtraining/vendor/rails/actionpack/lib/action_controller/filters.rb:629:in `run_before_filters'
    /Users/tvd/code/rails/webtraining/vendor/rails/actionpack/lib/action_controller/filters.rb:615:in `call_filters'
    /Users/tvd/code/rails/webtraining/vendor/rails/actionpack/lib/action_controller/filters.rb:610:in `perform_action_without_benchmark'
    /Users/tvd/code/rails/webtraining/vendor/rails/actionpack/lib/action_controller/benchmarking.rb:68:in `perform_action_without_rescue'
    /Users/tvd/code/rails/webtraining/vendor/rails/activesupport/lib/active_support/core_ext/benchmark.rb:17:in `ms'
    /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/benchmark.rb:308:in `realtime'
    /Users/tvd/code/rails/webtraining/vendor/rails/activesupport/lib/active_support/core_ext/benchmark.rb:17:in `ms'
    /Users/tvd/code/rails/webtraining/vendor/rails/actionpack/lib/action_controller/benchmarking.rb:68:in `perform_action_without_rescue'
    /Users/tvd/code/rails/webtraining/vendor/rails/actionpack/lib/action_controller/rescue.rb:160:in `perform_action_without_flash'
    /Users/tvd/code/rails/webtraining/vendor/rails/actionpack/lib/action_controller/flash.rb:151:in `perform_action'
    /Users/tvd/code/rails/webtraining/vendor/rails/actionpack/lib/action_controller/base.rb:532:in `send'
    /Users/tvd/code/rails/webtraining/vendor/rails/actionpack/lib/action_controller/base.rb:532:in `process_without_filters'
    /Users/tvd/code/rails/webtraining/vendor/rails/actionpack/lib/action_controller/filters.rb:606:in `process'
    /Users/tvd/code/rails/webtraining/vendor/rails/actionpack/lib/action_controller/base.rb:391:in `process'
    /Users/tvd/code/rails/webtraining/vendor/rails/actionpack/lib/action_controller/base.rb:386:in `call'
    /Users/tvd/code/rails/webtraining/vendor/rails/actionpack/lib/action_controller/routing/route_set.rb:438:in `call'
    /Users/tvd/code/rails/webtraining/vendor/rails/actionpack/lib/action_controller/dispatcher.rb:87:in `dispatch'
    /Users/tvd/code/rails/webtraining/vendor/rails/actionpack/lib/action_controller/dispatcher.rb:121:in `_call'
    /Users/tvd/code/rails/webtraining/vendor/rails/actionpack/lib/action_controller/dispatcher.rb:130:in `build_middleware_stack'
    /Users/tvd/code/rails/webtraining/vendor/rails/activerecord/lib/active_record/query_cache.rb:29:in `call'
    /Users/tvd/code/rails/webtraining/vendor/rails/activerecord/lib/active_record/query_cache.rb:29:in `call'
    /Users/tvd/code/rails/webtraining/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb:34:in `cache'
    /Users/tvd/code/rails/webtraining/vendor/rails/activerecord/lib/active_record/query_cache.rb:9:in `cache'
    /Users/tvd/code/rails/webtraining/vendor/rails/activerecord/lib/active_record/query_cache.rb:28:in `call'
    /Users/tvd/code/rails/webtraining/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb:361:in `call'
    /Users/tvd/code/rails/webtraining/vendor/rails/actionpack/lib/action_controller/string_coercion.rb:25:in `call'
    /Library/Ruby/Gems/1.8/gems/rack-1.1.0/lib/rack/head.rb:9:in `call'
    /Library/Ruby/Gems/1.8/gems/rack-1.1.0/lib/rack/methodoverride.rb:24:in `call'
    /Users/tvd/code/rails/webtraining/vendor/rails/actionpack/lib/action_controller/params_parser.rb:15:in `call'
    /Users/tvd/code/rails/webtraining/vendor/rails/actionpack/lib/action_controller/session/cookie_store.rb:100:in `call'
    /Users/tvd/code/rails/webtraining/vendor/rails/actionpack/lib/action_controller/failsafe.rb:26:in `call'
    /Library/Ruby/Gems/1.8/gems/rack-1.1.0/lib/rack/lock.rb:11:in `call'
    /Library/Ruby/Gems/1.8/gems/rack-1.1.0/lib/rack/lock.rb:11:in `synchronize'
    /Library/Ruby/Gems/1.8/gems/rack-1.1.0/lib/rack/lock.rb:11:in `call'
    /Users/tvd/code/rails/webtraining/vendor/rails/actionpack/lib/action_controller/dispatcher.rb:114:in `call'
    /Users/tvd/code/rails/webtraining/vendor/rails/actionpack/lib/action_controller/reloader.rb:34:in `run'
    /Users/tvd/code/rails/webtraining/vendor/rails/actionpack/lib/action_controller/dispatcher.rb:108:in `call'
    /Users/tvd/code/rails/webtraining/vendor/rails/railties/lib/rails/rack/static.rb:31:in `call'
    /Library/Ruby/Gems/1.8/gems/rack-1.1.0/lib/rack/urlmap.rb:47:in `call'
    /Library/Ruby/Gems/1.8/gems/rack-1.1.0/lib/rack/urlmap.rb:41:in `each'
    /Library/Ruby/Gems/1.8/gems/rack-1.1.0/lib/rack/urlmap.rb:41:in `call'
    /Users/tvd/code/rails/webtraining/vendor/rails/railties/lib/rails/rack/log_tailer.rb:17:in `call'
    /Library/Ruby/Gems/1.8/gems/rack-1.1.0/lib/rack/content_length.rb:13:in `call'
    /Library/Ruby/Gems/1.8/gems/rack-1.1.0/lib/rack/chunked.rb:15:in `call'
    /Library/Ruby/Gems/1.8/gems/rack-1.1.0/lib/rack/handler/mongrel.rb:67:in `process'
    /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:159:in `process_client'
    /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:158:in `each'
    /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:158:in `process_client'
    /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:285:in `run'
    /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:285:in `initialize'
    /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:285:in `new'
    /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:285:in `run'
    /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:268:in `initialize'
    /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:268:in `new'
    /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/gems/1.8/gems/mongrel-1.1.5/lib/mongrel.rb:268:in `run'
    /Library/Ruby/Gems/1.8/gems/rack-1.1.0/lib/rack/handler/mongrel.rb:38:in `run'
    /Users/tvd/code/rails/webtraining/vendor/rails/railties/lib/commands/server.rb:111
    /Library/Ruby/Site/1.8/rubygems/custom_require.rb:31:in `gem_original_require'
    /Library/Ruby/Site/1.8/rubygems/custom_require.rb:31:in `require'
    script/server:3
    

    And I guess I know why this raises an error. The name of the partial I render inside my 'user_sessions/new' template is the same I render inside my Orders#new action '_form'. And Rails does not change controller scope while rendering a template. So the partial renderers scope is 'app/views/orders' not 'app/views/user_sessions'. If I pass the whole path ('user_sessions/form') to the partial renderer it works!

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile »

<h2 style="font-size: 14px">Tickets have moved to Github</h2>

The new ticket tracker is available at <a href="https://github.com/rails/rails/issues">https://github.com/rails/rails/issues</a>

People watching this ticket

Pages