Request.format = :mobile causes error "undefined method `ref' for nil:NilClass"

I have a strange problem with setting request.format = :mobile

I can reproduce this problem on a completely fresh Rails 3.0.7 app
with no special gems. This seemed to work well in Rails 2 but for some
reason is hiccuping here, not sure what’s different in Rails 3 that
makes this hiccup. If you look at the stack track, it doesn’t even
pass through my app stack once – weird – maybe this is a problem
with Passenger? Anyone see anything i’m doing wrong here? Your tips
are much appreciated, this is baffling me.

Step-by-step instructions to reproduce:

Totally fresh rails app (rails new test_mobile), then go delete public/
index.html

routes.rb __________________________________

TestMobile::Application.routes.draw do
root :to => “application#welcome”
end

application_controller.rb __________________________

class ApplicationController < ActionController::Base
protect_from_forgery

def welcome
render “welcome/index”
end

before_filter :check_mobile

def check_mobile
request.format = :mobile if request.env[“HTTP_USER_AGENT”] =~ /
iPhone/
end
end

views/welcome/index.html.erb ______________________________________

this is my regular site

views/welcome/index.mobile.erb ____________________________________

this is my mobile site

That’s it – those are all the steps one needs to take to reproduce
this, no gem configuration necessary.

Set it up with Passenger (as test-mobile.local), go to Safrai, load
test-mobile.local, you get “this is my regular site”. Then switch
Develop > User Agent to “Safari iOS 4.1”, reload the page, and bam:

NoMethodError in ApplicationsController#welcome

undefined method `ref’ for nil:NilClass
Rails.root: /Users/jason/Projects/DEVELOPMENT/ROR/test_mobile

Application Trace | Framework Trace | Full Trace
activesupport (3.0.7) lib/active_support/whiny_nil.rb:48:in
method_missing' actionpack (3.0.7) lib/action_controller/metal/rendering.rb:10:inprocess_action’
actionpack (3.0.7) lib/action_controller/metal/rendering.rb:10:in
map' actionpack (3.0.7) lib/action_controller/metal/rendering.rb:10:inprocess_action’
actionpack (3.0.7) lib/abstract_controller/callbacks.rb:18:in
process_action' activesupport (3.0.7) lib/active_support/callbacks.rb:441:in_run__2115867319__process_action__733682996__callbacks’
activesupport (3.0.7) lib/active_support/callbacks.rb:410:in send' activesupport (3.0.7) lib/active_support/callbacks.rb:410:in_run_process_action_callbacks’
activesupport (3.0.7) lib/active_support/callbacks.rb:94:in send' activesupport (3.0.7) lib/active_support/callbacks.rb:94:inrun_callbacks’
actionpack (3.0.7) lib/abstract_controller/callbacks.rb:17:in
process_action' actionpack (3.0.7) lib/action_controller/metal/instrumentation.rb: 30:inprocess_action’
activesupport (3.0.7) lib/active_support/notifications.rb:52:in
instrument' activesupport (3.0.7) lib/active_support/notifications/instrumenter.rb: 21:ininstrument’
activesupport (3.0.7) lib/active_support/notifications.rb:52:in
instrument' actionpack (3.0.7) lib/action_controller/metal/instrumentation.rb: 29:inprocess_action’
actionpack (3.0.7) lib/action_controller/metal/rescue.rb:17:in
process_action' actionpack (3.0.7) lib/abstract_controller/base.rb:119:inprocess’
actionpack (3.0.7) lib/abstract_controller/rendering.rb:41:in
process' actionpack (3.0.7) lib/action_controller/metal.rb:138:indispatch’
actionpack (3.0.7) lib/action_controller/metal/rack_delegation.rb:
14:in dispatch' actionpack (3.0.7) lib/action_controller/metal.rb:178 actionpack (3.0.7) lib/action_dispatch/routing/route_set.rb:62:incall’
actionpack (3.0.7) lib/action_dispatch/routing/route_set.rb:62:in
dispatch' actionpack (3.0.7) lib/action_dispatch/routing/route_set.rb:27:incall’
rack-mount (0.6.14) lib/rack/mount/route_set.rb:148:in call' rack-mount (0.6.14) lib/rack/mount/code_generation.rb:93:inrecognize’
rack-mount (0.6.14) lib/rack/mount/code_generation.rb:68:in
optimized_each' rack-mount (0.6.14) lib/rack/mount/code_generation.rb:92:inrecognize’
rack-mount (0.6.14) lib/rack/mount/route_set.rb:139:in call' actionpack (3.0.7) lib/action_dispatch/routing/route_set.rb:493:incall’
actionpack (3.0.7) lib/action_dispatch/middleware/
best_standards_support.rb:17:in call' actionpack (3.0.7) lib/action_dispatch/middleware/head.rb:14:incall’
rack (1.2.2) lib/rack/methodoverride.rb:24:in call' actionpack (3.0.7) lib/action_dispatch/middleware/params_parser.rb: 21:incall’
actionpack (3.0.7) lib/action_dispatch/middleware/flash.rb:182:in
call' actionpack (3.0.7) lib/action_dispatch/middleware/session/ abstract_store.rb:149:incall’
actionpack (3.0.7) lib/action_dispatch/middleware/cookies.rb:302:in
call' activerecord (3.0.7) lib/active_record/query_cache.rb:32:incall’
activerecord (3.0.7) lib/active_record/connection_adapters/abstract/
query_cache.rb:28:in cache' activerecord (3.0.7) lib/active_record/query_cache.rb:12:incache’
activerecord (3.0.7) lib/active_record/query_cache.rb:31:in call' activerecord (3.0.7) lib/active_record/connection_adapters/abstract/ connection_pool.rb:354:incall’
actionpack (3.0.7) lib/action_dispatch/middleware/callbacks.rb:46:in
call' activesupport (3.0.7) lib/active_support/callbacks.rb:416:in_run_call_callbacks’
actionpack (3.0.7) lib/action_dispatch/middleware/callbacks.rb:44:in
call' rack (1.2.2) lib/rack/sendfile.rb:107:incall’
actionpack (3.0.7) lib/action_dispatch/middleware/remote_ip.rb:48:in
call' actionpack (3.0.7) lib/action_dispatch/middleware/show_exceptions.rb: 47:incall’
railties (3.0.7) lib/rails/rack/logger.rb:13:in call' rack (1.2.2) lib/rack/runtime.rb:17:incall’
activesupport (3.0.7) lib/active_support/cache/strategy/local_cache.rb:
72:in call' rack (1.2.2) lib/rack/lock.rb:11:incall’
rack (1.2.2) lib/rack/lock.rb:11:in synchronize' rack (1.2.2) lib/rack/lock.rb:11:incall’
actionpack (3.0.7) lib/action_dispatch/middleware/static.rb:30:in
call' railties (3.0.7) lib/rails/application.rb:168:incall’
railties (3.0.7) lib/rails/application.rb:77:in send' railties (3.0.7) lib/rails/application.rb:77:inmethod_missing’
passenger (2.2.10) lib/phusion_passenger/rack/request_handler.rb:92:in
process_request' passenger (2.2.10) lib/phusion_passenger/abstract_request_handler.rb: 207:inmain_loop’
passenger (2.2.10) lib/phusion_passenger/rack/application_spawner.rb:
118:in run' passenger (2.2.10) lib/phusion_passenger/rack/application_spawner.rb: 65:inspawn_application’
passenger (2.2.10) lib/phusion_passenger/utils.rb:184:in safe_fork' passenger (2.2.10) lib/phusion_passenger/rack/application_spawner.rb: 58:inspawn_application’
passenger (2.2.10) lib/phusion_passenger/rack/application_spawner.rb:
41:in spawn_application' passenger (2.2.10) lib/phusion_passenger/spawn_manager.rb:159:inspawn_application’
passenger (2.2.10) lib/phusion_passenger/spawn_manager.rb:287:in
handle_spawn_application' passenger (2.2.10) lib/phusion_passenger/abstract_server.rb:352:insend
passenger (2.2.10) lib/phusion_passenger/abstract_server.rb:352:in
main_loop' passenger (2.2.10) lib/phusion_passenger/abstract_server.rb:196:instart_synchronously’
passenger (2.2.10) bin/passenger-spawn-server:61
Request

Parameters:

{“format”=>“mobile”}
Show session dump

Show env dump

Response

Headers:

None

On Saturday, May 21, 2011 12:24:27 PM UTC-6, Jason FB wrote:

this is my regular site

That’s it – those are all the steps one needs to take to reproduce
this, no gem configuration necessary.

Set it up with Passenger (as test-mobile.local), go to Safrai, load
test-mobile.local, you get “this is my regular site”. Then switch
Develop > User Agent to “Safari iOS 4.1”, reload the page, and bam:

NoMethodError in ApplicationsController#welcome

Hmm, are you sure that your routes.rb file contains the singular form
“application#welcome” and not “applications#welcome” (note the “s” on
“applications”). What does “rake routes” return?

It looks to me like your :root route is mapping to
“applications#welcome”
(plural) as if you’ve got: root :to => “applications#welcome”

The only way to know if it is the routing is to have a rake routes dump.

request.format = :mobile if request.user_agent =~ /Mobile|webOS|iPhone/

Thanks for the feedback. No my problem was that I didn’t (/realize I had
to) set the MIME type for “mobile” in config/initializers/mime_types.rb

Mime::Type.register_alias “text/html”, :mobile

That’s what I was missing – I’m sure of it cause it worked fine after I
set that correctly.

If the error message from Rails said “You didn’t set a MIME type in
config/initializers/mime_types.rb for the format :mobile” that would be
more helpful. It makes perfect sense-- I just didn’t realize that was a
necessary step.

On May 23, 2011, at 4:08 PM, Alpha B. wrote:

request.format = :mobile if request.user_agent =~ /Mobile|webOS|iPhone/

I misread what you posted - my mistake. You also need to set the mime
type, as you stated.

You might also want to do the following, which will make it simpler for
you down the road where managing your views can be a bit tedious.

In application.rb set a config for:

paths.app.views << “app/views/mobile”

Then you can just keep your mobile views separate from other views.

i.e.

\views
\views\home
\views\layouts
\views\mobile
\views\users
etc.

and in \mobile you would have

\mobile
\mobile\home\index.mobile
\mobile\layouts\application.mobile
\mobile\users\index.mobile
etc.

If you want to see some testing scenarios for mobile rails look at this:

http://www.ruby-forum.com/topic/1744072

I wrote it a few days ago. Glad you got it working.