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
