forked from carezone/mobylette
/
respond_to_mobile_requests.rb
189 lines (164 loc) · 5.72 KB
/
respond_to_mobile_requests.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
module Mobylette
module Controllers
# Mobylette::Controllers::RespondToMobileRequests includes the respond_to_mobile_requests
# to your ActionController::Base.
#
# The respond_to_mobile_requests method enables the controller mobile handling
module RespondToMobileRequests
extend ActiveSupport::Concern
included do
helper_method :is_mobile_request?
helper_method :is_mobile_view?
# List of mobile agents, from mobile_fu (https://github.com/brendanlim/mobile-fu)
MOBILE_USER_AGENTS = %w(
alcatel
amoi
android
astel
audiovox
blackberry
cdm
chtml
docomo
ericsson
ipad
iphone
ipod
j2me
kddi
midp
minimo
mmp
mobi
mobile
mobileexplorer
mot-
motorola
netfront
nokia
novarra
palm
pdxgw
phone
plucker
pocket
portable
portalmmm
sagem
samsung
sgh
sie-
softbank
sprint
symbian
telit
ucweb
up.b
upg1
vodafone
webos
windows\ ce
x240
x320
xiino
)
end
module ClassMethods
# This method enables the controller do handle mobile requests
#
# You must add this to every controller you want to respond differently to mobile devices,
# or make it application wide calling it from the ApplicationController
#
# Options:
# * fall_back: :html
# You may pass a fall_back option to the method, it will force the render
# to look for that other format, in case there is not a .mobile file for the view.
# By default, it will fall back to the format of the original request.
# If you don't want fall back at all, pass fall_back: false
# * skip_xhr_requests: true/false
# By default this is set to true. When a xhr request enters in, it will skip the
# mobile verification. This will let your ajax calls to work as intended.
# You may disable this (actually you will have to) if you are using JQuery Mobile, or
# other js framework that uses ajax. To disable, set skip_xhr_requests: false
def respond_to_mobile_requests(options = {})
return if self.included_modules.include?(Mobylette::Controllers::RespondToMobileRequestsMethods)
options.reverse_merge!({
skip_xhr_requests: true
})
cattr_accessor :mobylette_options
# works on 1.9, but not on 1.8
#valid_options = [:fall_back, :skip_xhr_requests]
#self.mobylette_options = options.reject {|option| !valid_options.include?(option)}
options[:except] = Array(options[:except]).map {|ua| ua.to_s}
self.mobylette_options = options
self.send(:include, Mobylette::Controllers::RespondToMobileRequestsMethods)
end
def add_mobile_user_agent(agent)
MOBILE_USER_AGENTS << agent
end
def remove_mobile_user_agent(agent)
MOBILE_USER_AGENTS.delete agent
end
end
private
# :doc:
# This helper returns exclusively if the request's user_aget is from a mobile
# device or not.
def is_mobile_request?
request.user_agent.to_s.downcase =~ Regexp.union(MOBILE_USER_AGENTS)
end
# :doc:
# This helper returns exclusively if the current format is mobile or not
def is_mobile_view?
true if (request.format.to_s == "mobile") or (params[:format] == "mobile")
end
end
# RespondToMobileRequestsMethods is included by respond_to_mobile_requests
#
# This will check if the request is from a mobile device and change
# the request format to :mobile
module RespondToMobileRequestsMethods
extend ActiveSupport::Concern
included do
before_filter :handle_mobile
end
private
# Returns true if this request should be treated as a mobile request
def respond_as_mobile?
processing_xhr_requests? and skip_mobile_param_not_present? and (force_mobile_by_session? or allow_mobile_response? or (params[:format] == 'mobile'))
end
def allow_mobile_response?
user_agent_included? && is_mobile_request?
end
def user_agent_included?
request.user_agent.to_s.downcase !~ Regexp.union(self.class.mobylette_options[:except])
end
# Returns true if the visitor has de force_mobile session
def force_mobile_by_session?
session[:mobylette_override] == :force_mobile
end
# Returns true when ?skip_mobile=true is not passed to the request
def skip_mobile_param_not_present?
params[:skip_mobile] != 'true'
end
# Returns true only if treating XHR requests (when skip_xhr_requests are set to false) or
# or when this is a non xhr request
def processing_xhr_requests?
not self.mobylette_options[:skip_xhr_requests] && request.xhr?
end
# :doc:
# Changes the request.form to :mobile, when the request is from
# a mobile device
def handle_mobile
return if session[:mobylette_override] == :ignore_mobile
if respond_as_mobile?
original_format = request.format.to_sym
request.format = :mobile
if self.mobylette_options[:fall_back] != false
request.formats << Mime::Type.new(self.mobylette_options[:fall_back] || original_format)
end
end
end
end
end
end