mobvious 0.1.3 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -48,7 +48,8 @@ fork your front-end code with regard to device type. There is a
48
48
 
49
49
  *This is just a very basic way of setting up Mobvious. If you want to detect
50
50
  tablets separately, or let the user manually switch between interface versions of your
51
- app, or do some funnier stuff, see sections Detection Process and Detection Strategies.*
51
+ app, or do some funnier stuff, see sections Detection Process, Example Configurations
52
+ and Detection Strategies.*
52
53
 
53
54
  ## Detection Process
54
55
 
@@ -60,15 +61,54 @@ strategy is used. If no strategy is successful, the implicit device type is used
60
61
  in the `configure` block).
61
62
 
62
63
 
64
+ ## Example Configurations
65
+
66
+ * Detects only by User-Agent into mobile vs. tablet vs. desktop groups.
67
+
68
+ Mobvious.configure do
69
+ strategies = [ Mobvious::Strategies::MobileESP.new(:mobile_tablet_desktop) ]
70
+ end
71
+
72
+ * Detects by User-Agent into mobile vs. tablet vs. desktop groups, but allows users
73
+ to manually switch interface versions (Cookie strategy is used for this and it is
74
+ the first one, so it has top precedence).
75
+
76
+ Mobvious.configure do
77
+ strategies = [
78
+ Mobvious::Strategies::Cookie.new([:mobile, :tablet, :desktop])
79
+ Mobvious::Strategies::MobileESP.new(:mobile_tablet_desktop)
80
+ ]
81
+ end
82
+
83
+ * Detects by URL into mobile vs. desktop groups (if URL has `m.` subdomain,
84
+ use mobile interface), but only for users coming directly, not via a link
85
+ clicked. For users coming via a link (if HTTP Referer header is set)
86
+ this config will use User-Agent detection.
87
+
88
+ When using this config, you will have to perform redirects in your app if
89
+ the URL which user requested doesn't match their device type.
90
+ (E.g. if the user comes to 'm.foo.com' via a link, but Mobvious tells you
91
+ that their device is a desktop computer, make sure to redirect the user
92
+ immediately to 'www.foo.com'.)
93
+
94
+ Mobvious.configure do
95
+ strategies = [
96
+ Mobvious::Strategies::URL.new(:mobile_path, disable_if_referer_set: true)
97
+ Mobvious::Strategies::MobileESP.new
98
+ ]
99
+ end
100
+
101
+
63
102
  ## Detection Strategies
64
103
 
65
104
  ### MobileESP (User-Agent sniffing)
66
105
 
67
- `Mobvious::Strategies::MobileESP`
106
+ `Mobvious::Strategies::MobileESP` | [view docs](http://rdoc.info/github/jistr/mobvious/master/Mobvious/Strategies/MobileESP)
68
107
 
69
108
  Selects the device type using information present in the User-Agent HTTP header.
70
109
 
71
- Constructor takes a detection procedure.
110
+ [Constructor](http://rdoc.info/github/jistr/mobvious/master/Mobvious/Strategies/MobileESP#initialize-instance_method)
111
+ takes a detection procedure.
72
112
  Detection procedure decides what device type it should return based on the
73
113
  information it can dig out of MobileESPConverted::UserAgentInfo instance.
74
114
 
@@ -84,12 +124,18 @@ There are two predefined detection procedures (and you can write your own):
84
124
 
85
125
  ### URL (URL pattern matching)
86
126
 
87
- `Mobvious::Strategies::URL`
127
+ `Mobvious::Strategies::URL` | [view docs](http://rdoc.info/github/jistr/mobvious/master/Mobvious/Strategies/URL)
88
128
 
89
129
  Selects the device type by matching a pattern against the request's URL (whole URL,
90
130
  including protocol information).
91
131
 
92
- Constructor takes a hash of rules in format `/regular_expression/ => :device_type`.
132
+ [Constructor](http://rdoc.info/github/jistr/mobvious/master/Mobvious/Strategies/URL#initialize-instance_method)
133
+ takes a hash of rules in format `{ /regular_expression/ => :device_type }` and options. Using the options you
134
+ can disable this strategy for requests that have the Referer HTTP header set or matching / not matching some
135
+ regular expression
136
+ ([see docs](http://rdoc.info/github/jistr/mobvious/master/Mobvious/Strategies/URL#initialize-instance_method)).
137
+ This is useful if you want to exclude URL detection for users coming via links from other sites and let the
138
+ User-Agent detection take precedence.
93
139
 
94
140
  There is one predefined rule set:
95
141
 
@@ -99,7 +145,7 @@ There is one predefined rule set:
99
145
 
100
146
  ### Cookie (remembering user's manual choice)
101
147
 
102
- `Mobvious::Strategies::Cookie`
148
+ `Mobvious::Strategies::Cookie` | [view docs](http://rdoc.info/github/jistr/mobvious/master/Mobvious/Strategies/Cookie)
103
149
 
104
150
  This strategy is useful when user should be able to make a manual switch between
105
151
  interface versions and you want all the interface versions running on the exact same URL.
@@ -114,7 +160,8 @@ In Rails it is accessible simply by writing `response`, as shown in the code exa
114
160
  Make sure to put the Cookie strategy high enough in your strategies array
115
161
  (the first entry?) so it does not get overriden by some other strategy.
116
162
 
117
- Constructor takes array of allowed device types ("whitelist") that your
163
+ [Constructor](http://rdoc.info/github/jistr/mobvious/master/Mobvious/Strategies/Cookie#initialize-instance_method)
164
+ takes an array of allowed device types ("whitelist") that your
118
165
  application supports. This is a countermeasure to users tampering with cookies. When
119
166
  the device type read from cookie is not whitelisted, the strategy passes the detection
120
167
  process to other strategies.
@@ -23,10 +23,17 @@ module Mobvious
23
23
  # Creates a new instance of MobileESP strategy.
24
24
  #
25
25
  # @param detection_procedure
26
- # A lambda function that gets one parameter (`MobileESPConverted::UserAgentInfo` instance)
27
- # and returns device type symbol or nil.
28
- def initialize(detection_procedure = DEVICE_TYPES_MOBILE_DESKTOP)
29
- @detection_procedure = detection_procedure
26
+ # a lambda function that gets one parameter (`MobileESPConverted::UserAgentInfo` instance)
27
+ # and returns device type symbol or nil.
28
+ # **or**
29
+ # a symbol for one of predefined detection procedures (`:mobile_desktop`,
30
+ # `:mobile_tablet_desktop`)
31
+ def initialize(detection_procedure = :mobile_desktop)
32
+ if detection_procedure.is_a? Symbol
33
+ @detection_procedure = eval("DEVICE_TYPES_#{detection_procedure.to_s.upcase}")
34
+ else
35
+ @detection_procedure = detection_procedure
36
+ end
30
37
  end
31
38
 
32
39
  # Gets device type using user-agent sniffing. Can return nil if the used
@@ -3,14 +3,16 @@ module Mobvious
3
3
  # Mobvious device detection strategy that uses URL pattern matching.
4
4
  class URL
5
5
  # Rule set with only one rule for domains that begin with `m.` matching as `:mobile`.
6
- MOBILE_PATH_RULES = { /^\w+:\/\/m\./ => :mobile }
6
+ RULES_MOBILE_PATH = { /^\w+:\/\/m\./ => :mobile }
7
7
 
8
8
  # Creates a new URL strategy instance.
9
9
  #
10
10
  # @param rules
11
11
  # A hash containing regular expressions mapped to symbols. The regular expression
12
12
  # is evaluated against the whole URL of the request (including `http://`). If matching,
13
- # the corresponding symbol is returned as the device type.
13
+ # the corresponding symbol is returned as the device type.
14
+ # **or**
15
+ # a symbol for one of predefined detection rules (`:mobile_path_rules`)
14
16
  # @param options
15
17
  # A hash with strategy options.
16
18
  # `disable_if_referer_set: true` disables the strategy if HTTP Referer header is set
@@ -18,8 +20,12 @@ module Mobvious
18
20
  # given regular expression
19
21
  # `disable_unless_referer_matches: /regex/` disables the strategy if HTTP Referer
20
22
  # doesn't match given regular expression
21
- def initialize(rules = MOBILE_PATH_RULES, options = {})
22
- @rules = rules
23
+ def initialize(rules = :mobile_path, options = {})
24
+ if rules.is_a? Symbol
25
+ @rules = eval("RULES_#{rules.to_s.upcase}")
26
+ else
27
+ @rules = rules
28
+ end
23
29
 
24
30
  default_options = {
25
31
  disable_if_referer_set: false,
@@ -1,3 +1,3 @@
1
1
  module Mobvious
2
- VERSION = "0.1.3"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -3,14 +3,17 @@ require_relative '../../spec_helper'
3
3
  module Mobvious::Strategies
4
4
  class MobileESPSpec < MiniTest::Spec
5
5
  describe MobileESP do
6
- describe "using mobile_desktop strategy" do
6
+ before do
7
+ @request = mock 'request'
8
+ @env = mock 'env'
9
+
10
+ @request.stubs(:env).returns(@env)
11
+ @env.stubs('[]').with('HTTP_ACCEPT').returns('text/html')
12
+ end
13
+
14
+ describe "using default (mobile_desktop) strategy" do
7
15
  before do
8
16
  @strategy = Mobvious::Strategies::MobileESP.new
9
- @request = mock 'request'
10
- @env = mock 'env'
11
-
12
- @request.stubs(:env).returns(@env)
13
- @env.stubs('[]').with('HTTP_ACCEPT').returns('text/html')
14
17
  end
15
18
 
16
19
  it "categorizes iPhone as :mobile" do
@@ -31,13 +34,7 @@ module Mobvious::Strategies
31
34
 
32
35
  describe "using mobile_tablet_desktop strategy" do
33
36
  before do
34
- @strategy = Mobvious::Strategies::MobileESP.new(
35
- Mobvious::Strategies::MobileESP::DEVICE_TYPES_MOBILE_TABLET_DESKTOP)
36
- @request = mock 'request'
37
- @env = mock 'env'
38
-
39
- @request.stubs(:env).returns(@env)
40
- @env.stubs('[]').with('HTTP_ACCEPT').returns('text/html')
37
+ @strategy = Mobvious::Strategies::MobileESP.new(:mobile_tablet_desktop)
41
38
  end
42
39
 
43
40
  it "categorizes iPhone as :mobile" do
@@ -55,6 +52,20 @@ module Mobvious::Strategies
55
52
  @strategy.get_device_type(@request).must_equal :desktop
56
53
  end
57
54
  end
55
+
56
+ describe "custom strategy" do
57
+ before do
58
+ procedure = lambda {|mobileesp|
59
+ return :test
60
+ }
61
+ @strategy = Mobvious::Strategies::MobileESP.new(procedure)
62
+ end
63
+
64
+ it "categorizes anything as :test" do
65
+ @request.stubs(:user_agent).returns("Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.46 Safari/535.11")
66
+ @strategy.get_device_type(@request).must_equal :test
67
+ end
68
+ end
58
69
  end
59
70
  end
60
71
  end
@@ -27,7 +27,7 @@ class URLSpec < MiniTest::Spec
27
27
 
28
28
  describe "disabled if referer is set" do
29
29
  before do
30
- @strategy = URL.new(URL::MOBILE_PATH_RULES, disable_if_referer_set: true)
30
+ @strategy = URL.new(:mobile_path, disable_if_referer_set: true)
31
31
  @env.merge!({
32
32
  'HTTP_REFERER' => 'http://localhost'
33
33
  })
@@ -40,7 +40,7 @@ class URLSpec < MiniTest::Spec
40
40
 
41
41
  describe "disabled if referer is set" do
42
42
  before do
43
- @strategy = URL.new(URL::MOBILE_PATH_RULES, disable_if_referer_set: true)
43
+ @strategy = URL.new(:mobile_path, disable_if_referer_set: true)
44
44
  @env.merge!({
45
45
  'HTTP_REFERER' => 'http://localhost'
46
46
  })
@@ -59,10 +59,10 @@ class URLSpec < MiniTest::Spec
59
59
  end
60
60
 
61
61
  it "returns nil even when matching rule found" do
62
- @strategy = URL.new(URL::MOBILE_PATH_RULES, disable_if_referer_matches: /local/)
62
+ @strategy = URL.new(:mobile_path, disable_if_referer_matches: /local/)
63
63
  @strategy.get_device_type(@request).must_equal nil
64
64
 
65
- @strategy = URL.new(URL::MOBILE_PATH_RULES, disable_if_referer_matches: /nothing/)
65
+ @strategy = URL.new(:mobile_path, disable_if_referer_matches: /nothing/)
66
66
  @strategy.get_device_type(@request).must_equal :mobile
67
67
  end
68
68
  end
@@ -75,13 +75,23 @@ class URLSpec < MiniTest::Spec
75
75
  end
76
76
 
77
77
  it "returns nil even when matching rule found" do
78
- @strategy = URL.new(URL::MOBILE_PATH_RULES, disable_unless_referer_matches: /nothing/)
78
+ @strategy = URL.new(:mobile_path, disable_unless_referer_matches: /nothing/)
79
79
  @strategy.get_device_type(@request).must_equal nil
80
80
 
81
- @strategy = URL.new(URL::MOBILE_PATH_RULES, disable_unless_referer_matches: /local/)
81
+ @strategy = URL.new(:mobile_path, disable_unless_referer_matches: /local/)
82
82
  @strategy.get_device_type(@request).must_equal :mobile
83
83
  end
84
84
  end
85
+
86
+ describe "using custom rules" do
87
+ before do
88
+ @strategy = URL.new(/\.foo\./ => :test)
89
+ end
90
+
91
+ it "returns :test for any url" do
92
+ @strategy.get_device_type(@request).must_equal :test
93
+ end
94
+ end
85
95
  end
86
96
  end
87
97
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mobvious
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-04-17 00:00:00.000000000 Z
12
+ date: 2012-04-18 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rack
16
- requirement: &21675260 !ruby/object:Gem::Requirement
16
+ requirement: &11301980 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 1.2.0
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *21675260
24
+ version_requirements: *11301980
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: mobileesp_converted
27
- requirement: &21764500 !ruby/object:Gem::Requirement
27
+ requirement: &11391240 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: 0.2.0
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *21764500
35
+ version_requirements: *11391240
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: pry
38
- requirement: &21763900 !ruby/object:Gem::Requirement
38
+ requirement: &11390700 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *21763900
46
+ version_requirements: *11390700
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: minitest
49
- requirement: &21763120 !ruby/object:Gem::Requirement
49
+ requirement: &11389880 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '0'
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *21763120
57
+ version_requirements: *11389880
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: mocha
60
- requirement: &21762380 !ruby/object:Gem::Requirement
60
+ requirement: &11389100 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: '0'
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *21762380
68
+ version_requirements: *11389100
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rack-test
71
- requirement: &21761700 !ruby/object:Gem::Requirement
71
+ requirement: &11388480 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ! '>='
@@ -76,10 +76,10 @@ dependencies:
76
76
  version: '0'
77
77
  type: :development
78
78
  prerelease: false
79
- version_requirements: *21761700
79
+ version_requirements: *11388480
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: guard
82
- requirement: &21761140 !ruby/object:Gem::Requirement
82
+ requirement: &11387880 !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
85
  - - ! '>='
@@ -87,10 +87,10 @@ dependencies:
87
87
  version: '0'
88
88
  type: :development
89
89
  prerelease: false
90
- version_requirements: *21761140
90
+ version_requirements: *11387880
91
91
  - !ruby/object:Gem::Dependency
92
92
  name: guard-minitest
93
- requirement: &21760420 !ruby/object:Gem::Requirement
93
+ requirement: &11387220 !ruby/object:Gem::Requirement
94
94
  none: false
95
95
  requirements:
96
96
  - - ! '>='
@@ -98,10 +98,10 @@ dependencies:
98
98
  version: '0'
99
99
  type: :development
100
100
  prerelease: false
101
- version_requirements: *21760420
101
+ version_requirements: *11387220
102
102
  - !ruby/object:Gem::Dependency
103
103
  name: rb-inotify
104
- requirement: &21759620 !ruby/object:Gem::Requirement
104
+ requirement: &11386380 !ruby/object:Gem::Requirement
105
105
  none: false
106
106
  requirements:
107
107
  - - ! '>='
@@ -109,10 +109,10 @@ dependencies:
109
109
  version: '0'
110
110
  type: :development
111
111
  prerelease: false
112
- version_requirements: *21759620
112
+ version_requirements: *11386380
113
113
  - !ruby/object:Gem::Dependency
114
114
  name: libnotify
115
- requirement: &21846540 !ruby/object:Gem::Requirement
115
+ requirement: &11473360 !ruby/object:Gem::Requirement
116
116
  none: false
117
117
  requirements:
118
118
  - - ! '>='
@@ -120,10 +120,10 @@ dependencies:
120
120
  version: '0'
121
121
  type: :development
122
122
  prerelease: false
123
- version_requirements: *21846540
123
+ version_requirements: *11473360
124
124
  - !ruby/object:Gem::Dependency
125
125
  name: turn
126
- requirement: &21846100 !ruby/object:Gem::Requirement
126
+ requirement: &11472940 !ruby/object:Gem::Requirement
127
127
  none: false
128
128
  requirements:
129
129
  - - ! '>='
@@ -131,7 +131,7 @@ dependencies:
131
131
  version: '0'
132
132
  type: :development
133
133
  prerelease: false
134
- version_requirements: *21846100
134
+ version_requirements: *11472940
135
135
  description: Rack middleware for choosing a version of an interface to render for
136
136
  given request
137
137
  email:
@@ -175,7 +175,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
175
175
  version: '0'
176
176
  segments:
177
177
  - 0
178
- hash: -439395585953181489
178
+ hash: 416472323923315110
179
179
  required_rubygems_version: !ruby/object:Gem::Requirement
180
180
  none: false
181
181
  requirements:
@@ -184,7 +184,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
184
184
  version: '0'
185
185
  segments:
186
186
  - 0
187
- hash: -439395585953181489
187
+ hash: 416472323923315110
188
188
  requirements: []
189
189
  rubyforge_project:
190
190
  rubygems_version: 1.8.11