radiant-mobile-extension 0.1.5 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +24 -1
- data/config/initializers/radiant_config.rb +6 -4
- data/lib/mobile_page.rb +33 -3
- data/lib/mobile_site_controller.rb +42 -16
- data/lib/radiant-mobile-extension.rb +3 -3
- data/spec/controllers/mobile_site_controller_spec.rb +66 -2
- data/spec/models/mobile_page_spec.rb +7 -0
- metadata +11 -10
data/README.md
CHANGED
@@ -12,6 +12,29 @@ This very simple extension allows you to offer a cache-friendly mobile version o
|
|
12
12
|
|
13
13
|
4. Use the radius tags `<r:if_mobile_>` and `<r:unless_mobile>` to make layout or content decisions based on whether this is a request for the mobile site.
|
14
14
|
|
15
|
+
## Web views
|
16
|
+
|
17
|
+
Any request that whose address begins 'app.', or which matches the configured 'app.host' is considered to be a request from a smartphone app for a web view. Such requests will set the mobile flag and will also set an app flag, so you can use an additional `<r:if_app>` radius tag to distinguish such requests from normal mobile phone usage.
|
18
|
+
|
19
|
+
## Configuration
|
20
|
+
|
21
|
+
You can set configuration entries to determine site addresses:
|
22
|
+
|
23
|
+
* `mobile.host` -> fully-specified mobile host name, eg m.spanner.org
|
24
|
+
* `app.host` -> fully-specified app host name
|
25
|
+
|
26
|
+
and to define the user-agent fragments that identify mobile (and non-mobile) devices:
|
27
|
+
|
28
|
+
* `mobile.ua.positives` -> comma-separated list of mobile UA markers like 'iphone,android,etc'
|
29
|
+
* `mobile.ua.negatives` -> comma-separated list of non-mobile UA markers like 'ipad'
|
30
|
+
* `mobile.ua.required` -> comma-separated list of UA markers that must be present to confirm mobileness
|
31
|
+
|
32
|
+
The logic of mobile device detection is this:
|
33
|
+
|
34
|
+
match any positive && not match any negatives && match any required
|
35
|
+
|
36
|
+
which allows us to pick a path through the messy and regrettable business of browser-sniffing with reasonable accuracy.
|
37
|
+
|
15
38
|
## Possibly AQ
|
16
39
|
|
17
40
|
### Why not just set :format (or use mobile-fu)?
|
@@ -77,7 +100,7 @@ With the `layouts` or `nested_layouts` extension you could create a simple layou
|
|
77
100
|
|
78
101
|
## Status
|
79
102
|
|
80
|
-
|
103
|
+
This has been in use for a couple of years without problems. The app-view part is new but ordinary: you should be able to use this extension with confidence.
|
81
104
|
|
82
105
|
## Bugs and comments
|
83
106
|
|
@@ -1,6 +1,8 @@
|
|
1
1
|
Radiant.config do |config|
|
2
|
-
config.
|
3
|
-
|
4
|
-
|
5
|
-
|
2
|
+
config.define 'app.host', :allow_blank => true
|
3
|
+
config.define 'mobile.host', :allow_blank => true
|
4
|
+
config.define 'mobile.redirect?', :default => true
|
5
|
+
config.define 'mobile.ua.positive', :allow_blank => true, :default => "palm,blackberry,nokia,phone,midp,mobi,symbian,chtml,ericsson,minimo,audiovox,motorola,samsung,telit,upg1,windows,ce,ucweb,astel,plucker,x320,x240,j2me,sgh,portable,sprint,docomo,kddi,softbank,android,mmp,pdxgw,netfront,xiino,vodafone,portalmmm,sagem,mot-,sie-,ipod,webos,amoi,novarra,cdm,alcatel,pocket,iphone,mobileexplorer,mobile"
|
6
|
+
config.define 'mobile.ua.negative', :allow_blank => true, :default => "ipad"
|
7
|
+
config.define 'mobile.ua.required', :allow_blank => true, :default => "mobile"
|
6
8
|
end
|
data/lib/mobile_page.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
module MobilePage
|
2
|
-
attr_accessor :mobile
|
2
|
+
attr_accessor :mobile, :app
|
3
3
|
|
4
4
|
# The extended site controller calls page.mobile = true if we are in a mobile context
|
5
5
|
#
|
@@ -7,11 +7,18 @@ module MobilePage
|
|
7
7
|
!!@mobile
|
8
8
|
end
|
9
9
|
|
10
|
+
# The extended site controller calls page.mobile = true if we are in a mobile context
|
11
|
+
#
|
12
|
+
def app?
|
13
|
+
!!@app
|
14
|
+
end
|
15
|
+
|
10
16
|
include Radiant::Taggable
|
11
17
|
|
12
18
|
desc %{
|
13
19
|
Expands if the url of the current request matches the host name defined in Radiant::Config['mobile.host'].
|
14
|
-
(or if there is no such definition, if the domain begins with m.)
|
20
|
+
(or if there is no such definition, if the domain begins with m.) Note that if there is an app site then it will
|
21
|
+
also be considered mobile.
|
15
22
|
|
16
23
|
*Usage:*
|
17
24
|
<pre><code><r:if_mobile>...</r:if_mobile></code></pre>
|
@@ -22,7 +29,8 @@ module MobilePage
|
|
22
29
|
|
23
30
|
desc %{
|
24
31
|
Expands unless the url of the current request matches the host name defined in Radiant::Config['mobile.host'].
|
25
|
-
(or if there is no such definition, unless it begins with m.)
|
32
|
+
(or if there is no such definition, unless it begins with m.) Note that if there is an app site then it will
|
33
|
+
also be considered mobile.
|
26
34
|
|
27
35
|
*Usage:*
|
28
36
|
<pre><code><r:unless_mobile>...</r:unless_mobile></code></pre>
|
@@ -31,4 +39,26 @@ module MobilePage
|
|
31
39
|
tag.expand unless mobile?
|
32
40
|
end
|
33
41
|
|
42
|
+
desc %{
|
43
|
+
Expands if the url of the current request matches the host name defined in Radiant::Config['app.host'].
|
44
|
+
(or if there is no such definition, if the domain begins with app.)
|
45
|
+
|
46
|
+
*Usage:*
|
47
|
+
<pre><code><r:if_app>...</r:if_app></code></pre>
|
48
|
+
}
|
49
|
+
tag 'if_app' do |tag|
|
50
|
+
tag.expand if app?
|
51
|
+
end
|
52
|
+
|
53
|
+
desc %{
|
54
|
+
Expands unless the url of the current request matches the host name defined in Radiant::Config['app.host'].
|
55
|
+
(or if there is no such definition, unless it begins with app.)
|
56
|
+
|
57
|
+
*Usage:*
|
58
|
+
<pre><code><r:unless_app>...</r:unless_app></code></pre>
|
59
|
+
}
|
60
|
+
tag 'unless_app' do |tag|
|
61
|
+
tag.expand unless app?
|
62
|
+
end
|
63
|
+
|
34
64
|
end
|
@@ -4,40 +4,66 @@ module MobileSiteController
|
|
4
4
|
# we can redirect to the corresponding page in a mobile site, and if we are on the mobile
|
5
5
|
# site we set a flag on the page that radius tags can use to select content.
|
6
6
|
|
7
|
-
|
8
|
-
# approach and UA strings borrowed from mobile-fu
|
9
|
-
# http://github.com/brendanlim/mobile-fu/tree/master
|
10
|
-
MOBILE_USER_AGENTS = 'palm|blackberry|nokia|phone|midp|mobi|symbian|chtml|ericsson|minimo|' +
|
11
|
-
'audiovox|motorola|samsung|telit|upg1|windows ce|ucweb|astel|plucker|' +
|
12
|
-
'x320|x240|j2me|sgh|portable|sprint|docomo|kddi|softbank|android|mmp|' +
|
13
|
-
'pdxgw|netfront|xiino|vodafone|portalmmm|sagem|mot-|sie-|ipod|up\\.b|' +
|
14
|
-
'webos|amoi|novarra|cdm|alcatel|pocket|iphone|mobileexplorer|' +
|
15
|
-
'mobile'
|
16
|
-
|
17
7
|
# Returns true if the requested host matches the defined mobile host
|
18
8
|
# (or in the absence of such a definition, if the host begins m.)
|
19
9
|
#
|
20
10
|
def mobile?
|
21
11
|
mobile_host = Radiant.config['mobile.host']
|
22
|
-
unless mobile_host.blank?
|
12
|
+
match = unless mobile_host.blank?
|
23
13
|
request.host == mobile_host
|
24
14
|
else
|
25
15
|
request.host =~ /^m\./
|
26
16
|
end
|
17
|
+
!!match
|
18
|
+
end
|
19
|
+
|
20
|
+
# Returns true if the requested host matches the defined app host
|
21
|
+
# (or in the absence of such a definition, if the host begins app.)
|
22
|
+
#
|
23
|
+
def app?
|
24
|
+
app_host = Radiant.config['app.host']
|
25
|
+
match = unless app_host.blank?
|
26
|
+
request.host == app_host
|
27
|
+
else
|
28
|
+
request.host =~ /^app\./
|
29
|
+
end
|
30
|
+
!!match
|
27
31
|
end
|
28
32
|
|
29
|
-
# Returns true if the request comes from a mobile device
|
30
|
-
# (based on the supplied user-agent string)
|
33
|
+
# Returns true if the request comes from a mobile device (based on the supplied user-agent string)
|
31
34
|
#
|
32
35
|
def mobile_device?
|
33
|
-
request.user_agent.to_s.downcase
|
36
|
+
ua = request.user_agent.to_s.downcase
|
37
|
+
ua =~ Regexp.new(positive_markers.join('|')) && ua =~ Regexp.new(required_markers.join('|')) && ua !~ Regexp.new(negative_markers.join('|'))
|
38
|
+
end
|
39
|
+
|
40
|
+
# Returns the list of string fragments whose presence indicates that this is a mobile device.
|
41
|
+
# The default list (and the approach) is borrowed from mobile-fu: https://github.com/brendanlim/mobile-fu/blob/master/lib/mobile_fu.rb
|
42
|
+
#
|
43
|
+
def positive_markers
|
44
|
+
@positive_ua_markers ||= Radiant.config['mobile.ua.positive'].split(/,\s*/)
|
45
|
+
end
|
46
|
+
|
47
|
+
# Returns the list of string fragments whose presence indicates that this is a tablet and should not be treated as a mobile device.
|
48
|
+
# eg. Ipad UA includes 'mobile' (which in this context is a false positive) and also 'ipad' (which allows us to eliminate it).
|
49
|
+
#
|
50
|
+
def negative_markers
|
51
|
+
@negative_ua_markers ||= Radiant.config['mobile.ua.negative'].split(/,\s*/)
|
52
|
+
end
|
53
|
+
|
54
|
+
# Returns the list of string fragments that must be present or this is not a mobile device.
|
55
|
+
# eg. android tablet UA includes 'android' but not 'mobile', so we require the mobile flag.
|
56
|
+
#
|
57
|
+
def required_markers
|
58
|
+
@required_ua_markers ||= Radiant.config['mobile.ua.required'].split(/,\s*/)
|
34
59
|
end
|
35
60
|
|
36
|
-
# Extends the process_page method to place a 'mobile'
|
61
|
+
# Extends the process_page method to place a 'mobile' and 'app' flags in the page-rendering
|
37
62
|
# context to support presentation choices in radius tags.
|
38
63
|
#
|
39
64
|
def process_page_with_mobile(page)
|
40
|
-
page.
|
65
|
+
page.app = app?
|
66
|
+
page.mobile = app? || mobile?
|
41
67
|
process_page_without_mobile(page)
|
42
68
|
end
|
43
69
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module RadiantMobileExtension
|
2
|
-
VERSION = '0.
|
3
|
-
SUMMARY = %q{Provide a mobile
|
4
|
-
DESCRIPTION = %q{This extension provides radius tags and a redirection mechanism that makes it
|
2
|
+
VERSION = '0.2.0'
|
3
|
+
SUMMARY = %q{Provide a mobile and app versions of your radiant site from within one page tree, using radius tags to select content.}
|
4
|
+
DESCRIPTION = %q{This extension provides radius tags and a redirection mechanism that makes it simple to provide a mobile version of your site and to serve web views for use in mobile apps.}
|
5
5
|
URL = "http://github.com/spanner/radiant-mobile-extension"
|
6
6
|
AUTHORS = ["William Ross"]
|
7
7
|
EMAIL = ["radiant@spanner.org"]
|
@@ -6,8 +6,11 @@ describe SiteController do
|
|
6
6
|
before do
|
7
7
|
@host = "m.test.host"
|
8
8
|
@page = pages(:first)
|
9
|
-
Radiant
|
10
|
-
Radiant
|
9
|
+
Radiant.config['mobile.host'] = @host
|
10
|
+
Radiant.config['mobile.redirect?'] = true
|
11
|
+
Radiant.config['mobile.ua.positive'] = "palm,blackberry,nokia,phone,midp,mobi,symbian,chtml,ericsson,minimo,audiovox,motorola,samsung,telit,upg1,windows,ce,ucweb,astel,plucker,x320,x240,j2me,sgh,portable,sprint,docomo,kddi,softbank,android,mmp,pdxgw,netfront,xiino,vodafone,portalmmm,sagem,mot-,sie-,ipod,webos,amoi,novarra,cdm,alcatel,pocket,iphone,mobileexplorer,mobile"
|
12
|
+
Radiant.config['mobile.ua.negative'] = "ipad"
|
13
|
+
Radiant.config['mobile.ua.required'] = "mobile"
|
11
14
|
end
|
12
15
|
|
13
16
|
describe "responding to a mobile-site request" do
|
@@ -25,6 +28,23 @@ describe SiteController do
|
|
25
28
|
get :show_page, :url => @page.url
|
26
29
|
end
|
27
30
|
end
|
31
|
+
|
32
|
+
describe "responding to an app-site request" do
|
33
|
+
before do
|
34
|
+
request.stub!(:host).and_return("app.test.host")
|
35
|
+
controller.stub!(:find_page).and_return(@page)
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should notice that this is a request for the app site" do
|
39
|
+
controller.app?.should be_true
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should set both the mobile and app flags on a processed page to true" do
|
43
|
+
@page.should_receive(:mobile=).with(true)
|
44
|
+
@page.should_receive(:app=).with(true)
|
45
|
+
get :show_page, :url => @page.url
|
46
|
+
end
|
47
|
+
end
|
28
48
|
|
29
49
|
describe "responding to a standard-site request" do
|
30
50
|
before do
|
@@ -41,6 +61,50 @@ describe SiteController do
|
|
41
61
|
get :show_page, :url => @page.url
|
42
62
|
end
|
43
63
|
|
64
|
+
describe "detecting devices:" do
|
65
|
+
describe "android phone" do
|
66
|
+
before do
|
67
|
+
request.stub!(:user_agent).and_return("Mozilla/5.0 (Linux; U; Android 2.2.1; en-us; Nexus One Build/FRG83) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1")
|
68
|
+
end
|
69
|
+
it "should be mobile" do
|
70
|
+
controller.mobile_device?.should be_true
|
71
|
+
end
|
72
|
+
end
|
73
|
+
describe "iphone" do
|
74
|
+
before do
|
75
|
+
request.stub!(:user_agent).and_return("Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420+ (KHTML, like Gecko) Version/3.0 Mobile/1C25 Safari/419.3")
|
76
|
+
end
|
77
|
+
it "should be mobile" do
|
78
|
+
controller.mobile_device?.should be_true
|
79
|
+
end
|
80
|
+
end
|
81
|
+
describe "android tablet" do
|
82
|
+
before do
|
83
|
+
request.stub!(:user_agent).and_return("Mozilla/5.0 (Linux; U; Android 2.2.1; en-us; device Build/FRG83) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Safari/533.1")
|
84
|
+
end
|
85
|
+
it "should not be mobile" do
|
86
|
+
controller.mobile_device?.should be_false
|
87
|
+
end
|
88
|
+
end
|
89
|
+
describe "ipad" do
|
90
|
+
before do
|
91
|
+
request.stub!(:user_agent).and_return("Mozilla/5.0 (iPad; U; CPU OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B334b Safari/531.21.10")
|
92
|
+
end
|
93
|
+
it "should not be mobile" do
|
94
|
+
controller.mobile_device?.should be_false
|
95
|
+
end
|
96
|
+
end
|
97
|
+
describe "with configured ua fragments" do
|
98
|
+
before do
|
99
|
+
Radiant.config['mobile.ua.positive'] = 'foo,bar,baz'
|
100
|
+
request.stub!(:user_agent).and_return("Mozilla/5.0 (Foo) Mobile")
|
101
|
+
end
|
102
|
+
it "should be mobile" do
|
103
|
+
controller.mobile_device?.should be_true
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
44
108
|
describe "from a mobile device" do
|
45
109
|
before do
|
46
110
|
controller.stub!(:mobile_device?).and_return(true)
|
@@ -11,4 +11,11 @@ describe Page do
|
|
11
11
|
page.mobile.should be_true
|
12
12
|
page.mobile?.should be_true
|
13
13
|
end
|
14
|
+
|
15
|
+
it "should get and set an app? attribute" do
|
16
|
+
page.app?.should be_false
|
17
|
+
lambda{ page.app = true }.should_not raise_error
|
18
|
+
page.app.should be_true
|
19
|
+
page.app?.should be_true
|
20
|
+
end
|
14
21
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: radiant-mobile-extension
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 23
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
8
|
+
- 2
|
9
|
+
- 0
|
10
|
+
version: 0.2.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- William Ross
|
@@ -15,7 +15,8 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-10-
|
18
|
+
date: 2011-10-20 00:00:00 +01:00
|
19
|
+
default_executable:
|
19
20
|
dependencies:
|
20
21
|
- !ruby/object:Gem::Dependency
|
21
22
|
name: paperclip
|
@@ -33,7 +34,7 @@ dependencies:
|
|
33
34
|
version: 2.3.16
|
34
35
|
type: :runtime
|
35
36
|
version_requirements: *id001
|
36
|
-
description: This extension provides radius tags and a redirection mechanism that makes it
|
37
|
+
description: This extension provides radius tags and a redirection mechanism that makes it simple to provide a mobile version of your site and to serve web views for use in mobile apps.
|
37
38
|
email:
|
38
39
|
- radiant@spanner.org
|
39
40
|
executables: []
|
@@ -56,7 +57,6 @@ files:
|
|
56
57
|
- lib/radiant-mobile-extension.rb
|
57
58
|
- lib/tasks/mobile_extension_tasks.rake
|
58
59
|
- mobile_extension.rb
|
59
|
-
- radiant-mobile-extension-0.1.5.gem
|
60
60
|
- radiant-mobile-extension.gemspec
|
61
61
|
- Rakefile
|
62
62
|
- README.md
|
@@ -65,10 +65,11 @@ files:
|
|
65
65
|
- spec/spec.opts
|
66
66
|
- spec/spec_helper.rb
|
67
67
|
- VERSION
|
68
|
+
has_rdoc: true
|
68
69
|
homepage: http://github.com/spanner/radiant-mobile-extension
|
69
70
|
licenses: []
|
70
71
|
|
71
|
-
post_install_message: "\n Add this to your radiant project with a line in your Gemfile:\n\n gem 'radiant-mobile-extension', '~> 0.
|
72
|
+
post_install_message: "\n Add this to your radiant project with a line in your Gemfile:\n\n gem 'radiant-mobile-extension', '~> 0.2.0'\n\n "
|
72
73
|
rdoc_options: []
|
73
74
|
|
74
75
|
require_paths:
|
@@ -94,10 +95,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
94
95
|
requirements: []
|
95
96
|
|
96
97
|
rubyforge_project:
|
97
|
-
rubygems_version: 1.
|
98
|
+
rubygems_version: 1.5.3
|
98
99
|
signing_key:
|
99
100
|
specification_version: 3
|
100
|
-
summary: Provide a mobile
|
101
|
+
summary: Provide a mobile and app versions of your radiant site from within one page tree, using radius tags to select content.
|
101
102
|
test_files:
|
102
103
|
- spec/controllers/mobile_site_controller_spec.rb
|
103
104
|
- spec/models/mobile_page_spec.rb
|