mobu 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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