mobu 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: da134026fb867c20abc5643f4bcc92a6a8e2127a
4
+ data.tar.gz: 17fc0c55249510e0e3f6b7492f7fa2925258049c
5
+ SHA512:
6
+ metadata.gz: b70d4036ed1820fcac7964d860cb25dbbd492158fd4cf478591bb2f44f74cf2cb39043fe49516620e5dcc30d82c28192924c25e7330d2d2fbfd9f59679a6fb6a
7
+ data.tar.gz: 1c70eaaac08ffaf397ef9d21edf3a9c1907da5d2a52d39028b66f02411e7b04a9f2706c086cc6bc5d3249b2453dae17ce50c10e18327b8663e1cef0c6515bf53
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
@@ -0,0 +1 @@
1
+ ruby-2.0.0
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - 2.0.0
5
+
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Neighborland, Inc.
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,61 @@
1
+ # Mobu
2
+
3
+ [![Build Status](https://api.travis-ci.org/neighborland/mobu.png)](https://travis-ci.org/neighborland/mobu)
4
+ [![Code Climate](https://codeclimate.com/github/neighborland/mobu.png)](https://codeclimate.com/github/neighborland/mobu)
5
+
6
+ Mobu provides a Rails controller concern called DetectMobile.
7
+ Mobu does server-side User Agent detection to categorize requests as mobile, tablet, or default.
8
+ Mobu modifies your rails view paths based on the request type.
9
+
10
+ ## Install
11
+
12
+ Add this line to your Gemfile:
13
+
14
+ ```ruby
15
+ gem 'mobu'
16
+ ```
17
+
18
+ Include the module in your ApplicationController:
19
+
20
+ ```ruby
21
+ class ApplicationController
22
+ include Mobu::DetectMobile
23
+ ```
24
+
25
+ Create directories for `views_mobile` and `views_tablet`:
26
+
27
+ ```sh
28
+ mkdir app/views_mobile
29
+ mkdir app/views_tablet
30
+ ```
31
+
32
+ ## Usage
33
+
34
+ Put the view/partial files that you want to override in the appropriate directories.
35
+
36
+ To allow mobile users to switch to the full site view, add a link to a mobile view:
37
+
38
+ ```sh
39
+ app/views_mobile/_footer.haml
40
+ ```
41
+ ```haml
42
+ = link_to("View Full Site", prefer_full_site_url)
43
+ ```
44
+
45
+ To allow full site users to switch to the mobile view, add a link to a default view:
46
+
47
+ ```sh
48
+ app/views_mobile/_footer.haml
49
+ ```
50
+ ```haml
51
+ - if mobile_browser?
52
+ = link_to("View Mobile Site", prefer_mobile_site_url)
53
+ ```
54
+
55
+ ## Credits
56
+
57
+ The view path modification techinique was taken from Scott W. Bradley's post
58
+ [here](http://scottwb.com/blog/2012/02/23/a-better-way-to-add-mobile-pages-to-a-rails-site/)
59
+
60
+ A similar project is Brendan Lim's [mobile-fu](https://github.com/brendanlim/mobile-fu)
61
+
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ task default: [:test]
5
+
6
+ Rake::TestTask.new(:test) do |t|
7
+ t.libs << 'test'
8
+ t.test_files = %w(test/**/*.rb)
9
+ t.verbose = false
10
+ end
@@ -0,0 +1,2 @@
1
+ require 'mobu/version'
2
+ require 'mobu/detect_mobile'
@@ -0,0 +1,107 @@
1
+ require 'active_support/concern'
2
+ require 'active_support/core_ext/object/to_param'
3
+ require 'active_support/core_ext/object/to_query'
4
+ require 'rack/utils'
5
+ require 'uri'
6
+
7
+ module Mobu
8
+ module DetectMobile
9
+ extend ActiveSupport::Concern
10
+
11
+ # List of mobile agents from mobile_fu:
12
+ # https://github.com/brendanlim/mobile-fu/blob/master/lib/mobile_fu.rb
13
+ MOBILE_USER_AGENTS = 'palm|blackberry|nokia|phone|midp|mobi|symbian|chtml|ericsson|minimo|' +
14
+ 'audiovox|motorola|samsung|telit|upg1|windows ce|ucweb|astel|plucker|' +
15
+ 'x320|x240|j2me|sgh|portable|sprint|docomo|kddi|softbank|android|mmp|' +
16
+ 'pdxgw|netfront|xiino|vodafone|portalmmm|sagem|mot-|sie-|ipod|up\\.b|' +
17
+ 'webos|amoi|novarra|cdm|alcatel|pocket|iphone|mobileexplorer|mobile'
18
+
19
+ TABLET_USER_AGENTS = 'ipad|android 3.0|xoom|sch-i800|playbook|tablet|kindle|honeycomb|gt-p1000'
20
+
21
+ included do
22
+ before_filter :check_mobile_site
23
+
24
+ helper_method :mobile_request?,
25
+ :mobile_browser?,
26
+ :prefer_full_site_url,
27
+ :prefer_mobile_site_url,
28
+ :tablet_request?,
29
+ :tablet_browser?
30
+ end
31
+
32
+ private
33
+
34
+ def mobile_views_path
35
+ @@mobile_views_path ||= Rails.root + 'app' + 'views_mobile'
36
+ end
37
+
38
+ def tablet_views_path
39
+ @@tablet_views_path ||= Rails.root + 'app' + 'views_tablet'
40
+ end
41
+
42
+ def prefer_full_site_url
43
+ _view_url "f"
44
+ end
45
+
46
+ def prefer_mobile_site_url
47
+ _view_url "m"
48
+ end
49
+
50
+ # preference: m, f (mobile, full)
51
+ def _view_url(preference)
52
+ uri = URI(request.url)
53
+ query = Rack::Utils.parse_nested_query(uri.query)
54
+ query["prefer"] = preference
55
+ uri.query = query.to_param
56
+ uri.to_s
57
+ end
58
+
59
+ def force_full_site
60
+ session[:prefer_full_site]
61
+ end
62
+
63
+ def mobile_request?
64
+ if defined?(@mobile_request)
65
+ @mobile_request
66
+ else
67
+ @mobile_request = !force_full_site && !tablet_request? && mobile_browser?
68
+ end
69
+ end
70
+
71
+ def mobile_browser?
72
+ user_agent_matches(MOBILE_USER_AGENTS)
73
+ end
74
+
75
+ def tablet_request?
76
+ if defined?(@tablet_request)
77
+ @tablet_request
78
+ else
79
+ @tablet_request = tablet_browser?
80
+ end
81
+ end
82
+
83
+ def tablet_browser?
84
+ user_agent_matches(TABLET_USER_AGENTS)
85
+ end
86
+
87
+ def check_mobile_site
88
+ case params.delete(:prefer)
89
+ when "f"
90
+ session[:prefer_full_site] = 1
91
+ when "m"
92
+ session.delete :prefer_full_site
93
+ end
94
+
95
+ if mobile_request?
96
+ prepend_view_path mobile_views_path
97
+ elsif tablet_request?
98
+ prepend_view_path tablet_views_path
99
+ end
100
+ end
101
+
102
+ def user_agent_matches(regex)
103
+ !!( request.user_agent.to_s.downcase =~ /(#{regex})/ )
104
+ end
105
+
106
+ end
107
+ end
@@ -0,0 +1,3 @@
1
+ module Mobu
2
+ VERSION = "0.0.2"
3
+ end
@@ -0,0 +1,31 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'mobu/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "mobu"
8
+ spec.version = Mobu::VERSION
9
+ spec.authors = ["Tee Parham"]
10
+ spec.email = ["tee@neighborland.com"]
11
+ spec.description = %q{Rails User Agent Dependent View Paths}
12
+ spec.summary = %q{Rails server-side User Agent detection, plus view path modifications.}
13
+ spec.homepage = "https://github.com/neighborland/mobu"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ["lib"]
19
+ spec.executables = []
20
+
21
+ spec.required_ruby_version = ">= 1.9.3"
22
+
23
+ spec.add_development_dependency "bundler", ">= 1.3"
24
+ spec.add_development_dependency "rake", ">= 10.1"
25
+ spec.add_development_dependency "test-unit", ">= 2.5"
26
+ spec.add_development_dependency "mocha", ">= 0.14"
27
+ spec.add_development_dependency "shoulda-context", ">= 1.1.5"
28
+
29
+ spec.add_runtime_dependency "rack", "~> 1.4"
30
+ spec.add_runtime_dependency "activesupport", ">= 3.2"
31
+ end
@@ -0,0 +1,158 @@
1
+ require 'test_helper'
2
+ require 'active_support/concern'
3
+ require 'active_support/core_ext/object/to_param'
4
+ require 'active_support/core_ext/object/to_query'
5
+ require 'rack/utils'
6
+ require 'uri'
7
+
8
+ class MobuFake
9
+ class << self
10
+ def before_filter(*args) end
11
+ def helper_method(*methods) end
12
+ end
13
+
14
+ def params
15
+ {}
16
+ end
17
+
18
+ include Mobu::DetectMobile
19
+ end
20
+
21
+ class Rails
22
+ def self.root
23
+ Pathname.new("LIB_ROOT/..")
24
+ end
25
+ end
26
+
27
+ class MobuTest < Test::Unit::TestCase
28
+
29
+ IPAD_USER_AGENT = "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"
30
+ IPHONE_USER_AGENT = "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_3 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5"
31
+ FIREFOX_USER_AGENT = "Mozilla/5.0 (Windows NT 6.2; rv:22.0) Gecko/20130405 Firefox/23.0"
32
+
33
+ context "controller" do
34
+ setup do
35
+ @request = mock
36
+ @session = MockCookies.new
37
+ @controller = MobuFake.new
38
+ @controller.stubs session: @session
39
+ @controller.stubs request: @request
40
+ end
41
+
42
+ should "set and cache mobile_request?" do
43
+ @controller.stubs :mobile_browser?
44
+ @controller.stubs :tablet_request?
45
+ refute @controller.send :mobile_request?
46
+ @controller.stubs mobile_browser?: true # should ignore
47
+ refute @controller.send :mobile_request?
48
+ end
49
+
50
+
51
+ should "detect tablet and not detect mobile for iPad user agent" do
52
+ @request.stubs user_agent: IPAD_USER_AGENT
53
+ assert @controller.send(:tablet_request?)
54
+ refute @controller.send(:mobile_request?)
55
+ end
56
+
57
+ context "with mobile user agent" do
58
+ setup do
59
+ @request.stubs user_agent: IPHONE_USER_AGENT
60
+ end
61
+
62
+ should "prepend mobile views" do
63
+ expect_mobile_views
64
+ expect_no_tablet_views
65
+ @controller.send :check_mobile_site
66
+ end
67
+
68
+ should "prepend mobile views with mobile preference" do
69
+ @controller.stubs params: {prefer: "m"}
70
+ expect_mobile_views
71
+ expect_no_tablet_views
72
+ @controller.send :check_mobile_site
73
+ end
74
+
75
+ should "not prepend mobile views with prefer_full_site cookie" do
76
+ @session[:prefer_full_site] = 1
77
+ expect_no_mobile_views
78
+ expect_no_tablet_views
79
+ @controller.send :check_mobile_site
80
+ end
81
+ end
82
+
83
+ context "with tablet user agent" do
84
+ setup do
85
+ @request.stubs user_agent: IPAD_USER_AGENT
86
+ end
87
+
88
+ should "prepend tablet views" do
89
+ expect_tablet_views
90
+ expect_no_mobile_views
91
+ @controller.send :check_mobile_site
92
+ end
93
+ end
94
+
95
+ context "with browser user agent" do
96
+ setup do
97
+ @request.stubs user_agent: FIREFOX_USER_AGENT
98
+ end
99
+
100
+ should "prepend no views" do
101
+ expect_no_tablet_views
102
+ expect_no_mobile_views
103
+ @controller.send :check_mobile_site
104
+ end
105
+
106
+ should "prepend no views with prefer_full_site cookie" do
107
+ @session[:prefer_full_site] = 1
108
+ expect_no_tablet_views
109
+ expect_no_mobile_views
110
+ @controller.send :check_mobile_site
111
+ end
112
+ end
113
+
114
+ context "#prefer_full_site_url" do
115
+ should "add prefer=f" do
116
+ @request.stubs url: "https://neighborland.com/xyz"
117
+ assert_equal "https://neighborland.com/xyz?prefer=f", @controller.send(:prefer_full_site_url)
118
+ end
119
+
120
+ should "keep existing query params" do
121
+ @request.stubs url: "https://neighborland.com/xyz?monkeys=true&bananas=yeller"
122
+ assert_equal "https://neighborland.com/xyz?bananas=yeller&monkeys=true&prefer=f", @controller.send(:prefer_full_site_url)
123
+ end
124
+ end
125
+
126
+ context "#prefer_mobile_site_url" do
127
+ should "add prefer=m" do
128
+ @request.stubs url: "https://neighborland.com/xyz"
129
+ assert_equal "https://neighborland.com/xyz?prefer=m", @controller.send(:prefer_mobile_site_url)
130
+ end
131
+
132
+ should "strip existing prefer value" do
133
+ @request.stubs url: "https://neighborland.com/xyz?prefer=f"
134
+ assert_equal "https://neighborland.com/xyz?prefer=m", @controller.send(:prefer_mobile_site_url)
135
+ end
136
+ end
137
+ end
138
+
139
+ private
140
+
141
+ def expect_mobile_views
142
+ @controller.expects(:mobile_views_path).returns("mobile_views_path").once
143
+ @controller.expects(:prepend_view_path).with("mobile_views_path")
144
+ end
145
+
146
+ def expect_tablet_views
147
+ @controller.expects(:tablet_views_path).returns("tablet_views_path").once
148
+ @controller.expects(:prepend_view_path).with("tablet_views_path")
149
+ end
150
+
151
+ def expect_no_mobile_views
152
+ @controller.expects(:mobile_views_path).never
153
+ end
154
+
155
+ def expect_no_tablet_views
156
+ @controller.expects(:tablet_views_path).never
157
+ end
158
+ end
@@ -0,0 +1,17 @@
1
+ require 'test/unit'
2
+ require 'shoulda-context'
3
+ require 'mocha/setup'
4
+ require 'mobu'
5
+
6
+ class MockCookies < Hash
7
+ attr_accessor :permanent
8
+
9
+ def initialize
10
+ @permanent = {}
11
+ super
12
+ end
13
+
14
+ def delete(cookie, opts={})
15
+ super cookie
16
+ end
17
+ end
metadata ADDED
@@ -0,0 +1,157 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mobu
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Tee Parham
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-10-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '10.1'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '10.1'
41
+ - !ruby/object:Gem::Dependency
42
+ name: test-unit
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '2.5'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '2.5'
55
+ - !ruby/object:Gem::Dependency
56
+ name: mocha
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0.14'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0.14'
69
+ - !ruby/object:Gem::Dependency
70
+ name: shoulda-context
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: 1.1.5
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: 1.1.5
83
+ - !ruby/object:Gem::Dependency
84
+ name: rack
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ~>
88
+ - !ruby/object:Gem::Version
89
+ version: '1.4'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ~>
95
+ - !ruby/object:Gem::Version
96
+ version: '1.4'
97
+ - !ruby/object:Gem::Dependency
98
+ name: activesupport
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - '>='
102
+ - !ruby/object:Gem::Version
103
+ version: '3.2'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '3.2'
111
+ description: Rails User Agent Dependent View Paths
112
+ email:
113
+ - tee@neighborland.com
114
+ executables: []
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - .gitignore
119
+ - .ruby-version
120
+ - .travis.yml
121
+ - Gemfile
122
+ - LICENSE.txt
123
+ - README.md
124
+ - Rakefile
125
+ - lib/mobu.rb
126
+ - lib/mobu/detect_mobile.rb
127
+ - lib/mobu/version.rb
128
+ - mobu.gemspec
129
+ - test/detect_mobile_test.rb
130
+ - test/test_helper.rb
131
+ homepage: https://github.com/neighborland/mobu
132
+ licenses:
133
+ - MIT
134
+ metadata: {}
135
+ post_install_message:
136
+ rdoc_options: []
137
+ require_paths:
138
+ - lib
139
+ required_ruby_version: !ruby/object:Gem::Requirement
140
+ requirements:
141
+ - - '>='
142
+ - !ruby/object:Gem::Version
143
+ version: 1.9.3
144
+ required_rubygems_version: !ruby/object:Gem::Requirement
145
+ requirements:
146
+ - - '>='
147
+ - !ruby/object:Gem::Version
148
+ version: '0'
149
+ requirements: []
150
+ rubyforge_project:
151
+ rubygems_version: 2.1.5
152
+ signing_key:
153
+ specification_version: 4
154
+ summary: Rails server-side User Agent detection, plus view path modifications.
155
+ test_files:
156
+ - test/detect_mobile_test.rb
157
+ - test/test_helper.rb