I think I didn't make myself clear: If I remove the block, I don't get the same 
exception: I get 

ActionView::Template::Error: undefined method `model_name' for NilClass:Class

Which (eventually) traces back to the session[order_id] being nil. 

The begin rescue thing is just so that ExceptionNotifier emails me the 
environment information. It is being raised immediately in the preceding line. 
It's just a quick and dirty hack so that I am getting as much info as I can on 
this. The important part is that session[order_id] is not expected to be nil, 
but it is. 

I hope that clears it up.

--
Ylan Segal
[email protected]

On Dec 29, 2011, at 10:31 AM, Ben Wanicur wrote:

> I'm surprised that if you removed the exception block, that you still get 
> your exception message (" Expecting to have order, but session doesn't have 
> one").  Maybe I am not understanding you.
> 
> Anyways, here is what I mean about narrowing your exception handling.  This 
> might not be your problem, but it's a good alternative to rescuing every 
> exception:
> 
>  class HomeGrownError < StandardError
>  end
>  
>  ...
>  ...
>  ...
>  
>  protected
>  # This is where I am caching the exceptions.
>  def check_for_existing_order
>    unless current_order?
>      begin
>        raise HomeGrownError("Expecting to have order, but session doesn't 
> have one")
>      rescue HomeGrownError => exception
>        ExceptionNotifier::Notifier.exception_notification(request.env, 
> exception).deliver
>      ensure
>        redirect_to root_path unless Rails.env.development?
>        return
>      end
>    end
>  end
> 
> 
> On Thu, Dec 29, 2011 at 10:13 AM, Ylan Segal <[email protected]> wrote:
> Ben,
> 
> def current_order?
>   session[:order_id]
> end
> 
> Since the problem only happens on production, I wasn't really getting full 
> stack trace information if I let the exception through. That is why I added 
> the rescue block in the first place: It sends me all the info with 
> ExceptionNotifier. Without the rescue block, eventually what happens is a 
> call a property that is nil on the order and that throws an exception, but 
> the problem is that the order_id is nill in the first place and it shouldn't 
> be.
> 
> Here is what that output looks like:
> 
> A RuntimeError occurred in orders#show:
> 
>  Expecting to have order, but session doesn't have one
>  app/controllers/lbd/orders_controller.rb:124:in `check_for_existing_order'
> 
> -------------------------------
> Request:
> -------------------------------
> 
>  * URL       : http://www.edited.com/order
>  * IP address: 184.73.92.227
>  * Parameters: {"action"=>"show", "controller"=>"lbd/orders"}
>  * Rails root: /app
> 
> -------------------------------
> Session:
> -------------------------------
> 
>  * session id: "8913455d4a9e22b76d48c438f90aaea6"
>  * data: {"session_id"=>"8913455d4a9e22b76d48c438f90aaea6"}
> 
> 
> -------------------------------
> Environment:
> -------------------------------
> 
>  * GATEWAY_INTERFACE                              : CGI/1.2
>  * HTTP_ACCEPT                                    : */*
>  * HTTP_ACCEPT_ENCODING                           : gzip
>  * HTTP_CONNECTION                                : close
>  * HTTP_HOST                                      : www.edited.com
>  * HTTP_USER_AGENT                                : Mozilla/5.0 (Windows NT 
> 6.1; WOW64; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 SmartLinksAddon
>  * HTTP_VERSION                                   : HTTP/1.1
>  * HTTP_VIA                                       : 1.1 
> web02.mashlogic.local:3028 (squid/2.7.STABLE9)
>  * HTTP_X_FORWARDED_FOR                           : 127.0.0.1, 50.17.249.10, 
> 10.114.118.95
>  * HTTP_X_FORWARDED_PORT                          : 80
>  * HTTP_X_FORWARDED_PROTO                         : http
>  * HTTP_X_HEROKU_DYNOS_IN_USE                     : 1
>  * HTTP_X_HEROKU_QUEUE_DEPTH                      : 0
>  * HTTP_X_HEROKU_QUEUE_WAIT_TIME                  : 3
>  * HTTP_X_REAL_IP                                 : 10.114.118.95
>  * HTTP_X_REQUEST_START                           : 1325180702283
>  * HTTP_X_VARNISH                                 : 2592570555
>  * PATH_INFO                                      : /order
>  * QUERY_STRING                                   :
>  * REMOTE_ADDR                                    : 10.66.162.3
>  * REQUEST_METHOD                                 : GET
>  * REQUEST_PATH                                   : /order
>  * REQUEST_URI                                    : /order
>  * SCRIPT_NAME                                    :
>  * SERVER_NAME                                    : www.edited.com
>  * SERVER_PORT                                    : 80
>  * SERVER_PROTOCOL                                : HTTP/1.1
>  * SERVER_SOFTWARE                                : thin 1.2.6 codename Crazy 
> Delicious
>  * action_controller.instance                     : orders#show
>  * action_dispatch.cookies                        : 
> #<ActionDispatch::Cookies::CookieJar:0x0000000b4e3c38>
>  * action_dispatch.parameter_filter               : [:password, :credit_card, 
> :payment_profile, /RAW_POST_DATA/, /RAW_POST_DATA/]
>  * action_dispatch.remote_ip                      : 50.17.249.10
>  * action_dispatch.request.accepts                : [*/*]
>  * action_dispatch.request.content_type           :
>  * action_dispatch.request.formats                : [*/*]
>  * action_dispatch.request.parameters             : {"action"=>"show", 
> "controller"=>"lbd/orders"}
>  * action_dispatch.request.path_parameters        : {:action=>"show", 
> :controller=>"lbd/orders"}
>  * action_dispatch.request.query_parameters       : {}
>  * action_dispatch.request.request_parameters     : {}
>  * action_dispatch.request.unsigned_session_cookie: 
> {"session_id"=>"018022ab5db5fe76684e2d1a5867d8a8"}
>  * action_dispatch.routes                         : 
> #<ActionDispatch::Routing::RouteSet:0x0000000496b690>
>  * action_dispatch.secret_token                   : 
> 0d72ef374495f4ed8ae2bd664e0fbf43e8c4f1a71cef4fb11d23dcc19dd55d0bbfe3fb9c55e59b8fe509c5d2c3ca77976f23c5f39392121e8d77d8b68de4359c
>  * action_dispatch.show_exceptions                : true
>  * async.callback                                 : #<Method: 
> Thin::Connection#post_process>
>  * async.close                                    : 
> #<EventMachine::DefaultDeferrable:0x0000000b502660>
>  * rack-cache.allow_reload                        : false
>  * rack-cache.allow_revalidate                    : false
>  * rack-cache.cache_key                           : Rack::Cache::Key
>  * rack-cache.default_ttl                         : 0
>  * rack-cache.entitystore                         : rails:/
>  * rack-cache.metastore                           : rails:/
>  * rack-cache.private_headers                     : ["Authorization", 
> "Cookie"]
>  * rack-cache.storage                             : 
> #<Rack::Cache::Storage:0x00000003c61918>
>  * rack-cache.use_native_ttl                      : false
>  * rack-cache.verbose                             : true
>  * rack.errors                                    : #<IO:0x00000000b39890>
>  * rack.input                                     : 
> #<StringIO:0x0000000b503038>
>  * rack.multiprocess                              : false
>  * rack.multithread                               : false
>  * rack.request.cookie_hash                       : {}
>  * rack.request.query_hash                        : {}
>  * rack.request.query_string                      :
>  * rack.run_once                                  : false
>  * rack.session                                   : 
> {"session_id"=>"018022ab5db5fe76684e2d1a5867d8a8", 
> "abingo_identity"=>9991086208}
>  * rack.session.options                           : {:key=>"_locum_session", 
> :path=>"/", :domain=>nil, :expire_after=>nil, :secure=>false, 
> :httponly=>true, :defer=>false, :renew=>false, 
> :coder=>#<Rack::Session::Cookie::Base64::Marshal:0x000000058583b0>, 
> :id=>"018022ab5db5fe76684e2d1a5867d8a8"}
>  * rack.url_scheme                                : http
>  * rack.version                                   : [1, 0]
>  * warden                                         : Warden::Proxy:94837780 
> @config={:default_scope=>:user, :scope_defaults=>{}, 
> :default_strategies=>{:user=>[:database_authenticatable]}, 
> :intercept_401=>false, :failure_app=>#<Devise::Delegator:0x00000005d371b0>}
> 
>  * Process: 1
>  * Server : 4950a26f-9aa2-4265-af61-f08d70fc8a30
> 
> --
> Ylan Segal
> [email protected]
> 
> 
> On Dec 29, 2011, at 10:00 AM, Ben Wanicur wrote:
> 
> > Sorry, I missed your def current_order? method (formatting is really bad on 
> > my computer here).... I would remove the exception handling (you are 
> > capturing everything with your rescue block), and see what more information 
> > you can gather.
> >
> >
> >
> > On Thu, Dec 29, 2011 at 9:43 AM, Ylan Segal <[email protected]> wrote:
> > Sure. Here we go:
> >
> > #config/session_store.rb
> > Locum::Application.config.session_store :cookie_store, :key => 
> > '_locum_session'
> >
> > #ApplicationController.rb
> >  def current_order
> >    if session[:order_id]
> >      current_order = Order.find(session[:order_id])
> >    end
> >    if session[:order_id].nil?
> >      current_order = Order.new
> >    end
> >    current_order
> >  end
> >
> >  def current_order?
> >    session[:order_id]
> >  end
> >
> > #OrdersController (inherits from Application Controller)
> >  before_filter :check_for_existing_order, :except => :except => [:add_item]
> >
> >  # Users cannot see any other action on the app until they have gone 
> > through add_item.
> >  def add_item
> >    @order = current_order
> >    @order.save
> >    session[:order_id] = @order.id
> >    variant = Variant.where(:sku => params[:variant_sku]).first
> >    quantity = params[:quantity].to_i
> >    @order.add_item(variant, quantity) unless variant.nil?
> >    redirect_to order_path
> >  end
> >
> >  def show
> >    @order = current_order
> >  end
> >
> >  def update
> >    @order = current_order
> >    @order.attributes = params[:order]
> >    if @order.save
> >      flash[:notice] = 'Your cart has been updated successfully'
> >    else
> >      flash[:alert] = "Your cart could not be updated: 
> > #{@order.errors.full_messages.join(',')}"
> >    end
> >    redirect_to order_path
> >  end
> >
> >  protected
> >  # This is where I am caching the exceptions.
> >  def check_for_existing_order
> >    unless current_order?
> >      begin
> >        raise "Expecting to have order, but session doesn't have one"
> >      rescue => exception
> >        ExceptionNotifier::Notifier.exception_notification(request.env, 
> > exception).deliver
> >      ensure
> >        redirect_to root_path unless Rails.env.development?
> >        return
> >      end
> >    end
> >  end
> >
> > #config/routes.rb
> >  resource :order, :except => [:destroy] do
> >      member do
> >        get :checkout
> >        post :add_item
> >      end
> >    end
> >
> > I added the important parts (I think). Thanks for the help!
> >
> > --
> > Ylan Segal
> > [email protected]
> >
> > On Dec 29, 2011, at 9:24 AM, Ben Wanicur wrote:
> >
> > > Can you post your code Ylan ?  Also, can you include and session store 
> > > config files as well ?
> > >
> > > On Thu, Dec 29, 2011 at 9:21 AM, Ylan Segal <[email protected]> wrote:
> > > Fellow Rubyists,
> > >
> > > I have been scratching my head on this one for a while: I have an 
> > > e-commerce app in production with pretty standard add-to-cart 
> > > functionality. Whenever a user starts an order, I add the order id to the 
> > > session and read it back on subsequent requests (like showing the cart, 
> > > checkout form, etc). By and large, this works as expected in my tests and 
> > > testing with local browsers.
> > >
> > > However, for a small number of my users, the session doesn't seems to 
> > > keep the order id. In actions where I would expect the order id to be 
> > > there, it is not. For example, I have a OrdersController#update action 
> > > that, well, updates the order. Following convention, that actions 
> > > forwards to OrdersController#show. Since the session[:order_id] was 
> > > present in #update, I would obviously expect it to be set in #show, and 
> > > for most users it is, but for some it is not. I am obviously, checking 
> > > that the user is not visiting #show before #update or #create has been 
> > > called.
> > >
> > > Random stuff that I think might make a difference
> > >
> > > * It is not restricted to any one browser/version. It happens with IE, 
> > > Firefox, etc.
> > > * It happens with browsers that have cookies (I can see when analyzing 
> > > requests, that the cookies headers are being sent, it just that the 
> > > session doesn't contain the expected variable/value).
> > > * Running Rails 3.1 on heroku with default session store.
> > >
> > > Currently, my only hunch is that the users browser is not sending the 
> > > latest version of a cookie (with the order_id set in the session) but the 
> > > original one generated when the first visited the site (where the 
> > > session[:order_id] has not been set).
> > >
> > > Has anyone experiences something like this? Would using another kind of 
> > > cookie store solve this?
> > >
> > > Thanks for the help,
> > >
> > > --
> > > Ylan Segal
> > > [email protected]
> > > Tel: +1-858-224-7421
> > > Fax: +1-858-876-1799
> > >
> > > --
> > > SD Ruby mailing list
> > > [email protected]
> > > http://groups.google.com/group/sdruby
> > >
> > >
> > > --
> > > SD Ruby mailing list
> > > [email protected]
> > > http://groups.google.com/group/sdruby
> >
> > --
> > SD Ruby mailing list
> > [email protected]
> > http://groups.google.com/group/sdruby
> >
> >
> > --
> > SD Ruby mailing list
> > [email protected]
> > http://groups.google.com/group/sdruby
> 
> --
> SD Ruby mailing list
> [email protected]
> http://groups.google.com/group/sdruby
> 
> 
> -- 
> SD Ruby mailing list
> [email protected]
> http://groups.google.com/group/sdruby

-- 
SD Ruby mailing list
[email protected]
http://groups.google.com/group/sdruby

Reply via email to