double_agent 0.2.3 → 1.0.0

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.
data/CHANGELOG CHANGED
@@ -1,3 +1,18 @@
1
+ == Release 1.0.0 (November 11, 2012) ==
2
+
3
+ * Changes to parser API
4
+ * Add "mobile?" method to detect mobile OS's
5
+ * Android's browser isn't part of the Chromium family
6
+ * Android OS isn't part of the GNU/Linux family
7
+ * iOS isn't part of the OS X family
8
+ * Add iPhone and iPad
9
+ * Add Kindle, Kindle Fire
10
+ * Refactor the Logs module
11
+ * Drop Stats module (use the "graphene" gem instead)
12
+ * Drop Logs module
13
+ * Drop icon methods - they just don't make much sense in the library
14
+ * Drop support for Ruby 1.8
15
+
1
16
  == Release 0.2.3 (July 14, 2012) ==
2
17
 
3
18
  * Handle exceptions on encoding errors
data/README.rdoc CHANGED
@@ -3,41 +3,50 @@
3
3
  double_agent is a library for parsing browser and operating system info out of user
4
4
  agent strings. It is designed for parsing large sets for review or analysis.
5
5
 
6
- == Installation
6
+ *NOTE* Support for Ruby 1.8 was dropped after version 0.2.3.
7
7
 
8
- gem install double_agent
8
+ == Installation
9
9
 
10
- == Loading
10
+ [sudo] gem install double_agent
11
+ # Or add "double_agent" to your Gemfile
11
12
 
12
- Double Agent is broken up into modules - Parser, Resources, Stats and Logs.
13
+ Read the full documentation at http://jordanhollinger.com/docs/double_agent/
13
14
 
14
- # Load the core modules (Parser, Resources)
15
- require 'double_agent'
15
+ == Parser
16
16
 
17
- # Load modules individually
18
- require 'double_agent/parser|resources|stats|logs|all'
17
+ user_agent = DoubleAgent.parse("Mozilla/5.0 (X11; Linux i686) AppleWebKit/535.19 (KHTML, like Gecko) Ubuntu/12.04 Chromium/18.0.1025.168 Chrome/18.0.1025.168 Safari/535.19")
19
18
 
20
- = Parser
19
+ user_agent.browser
20
+ => "Chrome 18"
21
21
 
22
- ua_string = "I'm a user agent string for Chrome 11 on Ubuntu"
22
+ user_agent.browser_name
23
+ => "Chrome"
23
24
 
24
- DoubleAgent.browser(ua_string)
25
- => "Chrome 11"
25
+ user_agent.browser_version
26
+ => "18"
26
27
 
27
- DoubleAgent.browser_family(ua_string)
28
+ user_agent.browser_family
28
29
  => "Chromium"
29
30
 
30
- DoubleAgent.os(ua_string)
31
+ user_agent.os
31
32
  => "Ubuntu"
32
33
 
33
- DoubleAgent.os_family(ua_string)
34
+ user_agent.os_family
34
35
  => "GNU/Linux"
35
36
 
36
- See the DoubleAgent module for more.
37
+ user_agent.mobile?
38
+ => false
39
+
40
+ # Or
37
41
 
38
- = Resources
42
+ DoubleAgent.browser("Mozilla/5.0 (X11; Linux i686) AppleWebKit/535.19 (KHTML, like Gecko) Ubuntu/12.04 Chromium/18.0.1025.168 Chrome/18.0.1025.168 Safari/535.19")
43
+ => "Chrome 18"
39
44
 
40
- DoubleAgent::Resource is a mix-in for objects with a user_agent method or attribute.
45
+ See the DoubleAgent module for more info.
46
+
47
+ == Resources
48
+
49
+ DoubleAgent::Resource is a mix-in for objects with a user_agent method.
41
50
  It gives that class's objects all of the above methods and more.
42
51
 
43
52
  class Login
@@ -56,36 +65,13 @@ It gives that class's objects all of the above methods and more.
56
65
  login.os_family
57
66
  => "OS X"
58
67
 
59
- = Stats
60
-
61
- Calculate browser and OS shares for large sets of DoubleAgent::Resource objects with DoubleAgent::Stats::percentages_for.
62
-
63
- logins = Login.all
64
- p logins.size
65
- => 1000
66
-
67
- stats = DoubleAgent::Stats.percentages_for(logins, :browser_family, :os_family)
68
- p stats
69
- => [["Firefox", "Windows", 50.0, 500], ["Internet Explorer", "Windows", 20.0, 200], ["Safari", "OS X", 20.0, 200], ["Firefox", "GNU/Linux", 10.0, 100]]
70
-
71
- stats.each do |browser_family, os_family, percent, real_num|
72
- puts "#{browser_family} on #{os_family} - #{percent}% (#{real_num} hits)"
73
- end
74
- => "Firefox on Windows - 50% (500 hits)"
75
- => "Internet Explorer on Windows - 20% (200 hits)"
76
- => "Safari on OS X - 20% (200 hits)"
77
- => "Firefox on GNU/Linux - 10% (100 hits)"
78
-
79
- = Logs
68
+ See the DoubleAgent::Resource module for more info.
80
69
 
81
- DoubleAgent::Logs::entries parses through Apache and Nginx access logs, instantiating each log line into a DoubleAgent::Logs::Entry
82
- object. It even reads gzipped logs (requires zlib)! Since the DoubleAgent::Logs::Entry class mixes in DoubleAgent::Resource, you
83
- can easily calculate browser and/or OS share on your site.
70
+ == Where did stats and logs go?
84
71
 
85
- entries = DoubleAgent::Logs.entries("/var/log/nginx/my-site.access.log*")
86
- stats = DoubleAgent::Stats.percentages_for(entries, :browser)
72
+ As of version 1.0.0, double_agent underwent a downsizing. Stats were dropped and moved to their own more generic gem called Graphene. More info at https://github.com/jhollinger/graphene. Logs were also dropped; there are several HTTP log parsers for Ruby, including http-log-parser and Beaver.
87
73
 
88
- p stats
89
- => [["Firefox 4", 20.0, 650], ["Internet Explorer 8", 18.0, 587], ...]
74
+ == License
75
+ Copyright 2011 Jordan Hollinger
90
76
 
91
- Check out the DoubleAgent::Logs::Entry class for more methods besides user_agent.
77
+ Licensed under the Apache License
data/data/browsers.yml CHANGED
@@ -1,65 +1,69 @@
1
1
  # The ordering is very important; matches are performed in the specified order.
2
2
  # This allows for greatly simplified regexes.
3
3
 
4
- - :name: Internet Explorer %s
5
- :sym: :msie
4
+ :msie:
5
+ :name: Internet Explorer
6
6
  :regex: msie \d+
7
7
  :version: (?<=msie )[0-9]+
8
- :safe_version: ["msie [0-9]+", "[0-9]+"]
9
8
 
10
- - :name: Chrome %s
11
- :sym: :chrome
9
+ :epiphany:
10
+ :name: Epiphany
11
+ :regex: epiphany
12
+ :version: (?<=epiphany/)[0-9]+
13
+
14
+ :chrome:
15
+ :name: Chrome
12
16
  :family_sym: :chromium
13
17
  :regex: chrome/\d+
14
18
  :version: (?<=chrome/)[0-9]+
15
- :safe_version: ["chrome/[0-9]+", "[0-9]+"]
16
19
 
17
- - :name: Chromium %s
18
- :sym: :chromium
20
+ :chromium:
21
+ :name: Chromium
19
22
  :regex: chromium/\d+
20
23
  :version: (?<=chromium/)[0-9]+
21
- :safe_version: ["chromium/[0-9]+", "[0-9]+"]
22
24
 
23
- - :name: Opera %s
24
- :sym: :opera
25
+ :opera:
26
+ :name: Opera
25
27
  :regex: opera
26
28
  :version: ((?<=version/)[0-9]+)|((?<=opera )[0-9]+)
27
- :safe_version: ["(version/[0-9]+)|(opera [0-9]+)", "[0-9]+"]
28
29
 
29
- - :name: Firefox %s
30
- :sym: :firefox
30
+ :firefox:
31
+ :name: Firefox
31
32
  :regex: firefox
32
33
  :version: (?<=firefox/)[0-9]+
33
- :safe_version: ["firefox/[0-9]+", "[0-9]+"]
34
34
 
35
- - :name: Android %s
36
- :sym: :android
37
- :family_sym: :chromium
35
+ :kindle_fire_silk:
36
+ :name: Kindle Fire (Silk)
37
+ :family_sym: :kindle
38
+ :regex: silk-accelerated
39
+
40
+ :kindle_fire:
41
+ :name: Kindle Fire
42
+ :family_sym: :kindle
43
+ :regex: kindle fire
44
+
45
+ :kindle:
46
+ :name: Kindle
47
+ :regex: kindle
48
+
49
+ :android:
50
+ :name: Android
38
51
  :regex: android
39
52
  :version: (?<=android )[0-9]+(\.[0-9]+)?
40
- :safe_version: ["android [0-9]+(\\.[0-9]+)?", "[0-9]+(\\.[0-9]+)?"]
41
53
 
42
- - :name: BlackBerry
43
- :sym: :blackberry
54
+ :blackberry:
55
+ :name: BlackBerry
44
56
  :regex: blackberry
45
57
 
46
- - :name: Epiphany
47
- :sym: :epiphany
48
- :regex: epiphany
49
- :version: (?<=epiphany/)[0-9]+
50
- :safe_version: ["epiphany/[0-9]+", "[0-9]+"]
51
-
52
- - :name: Safari %s
53
- :sym: :safari
58
+ :safari:
59
+ :name: Safari
54
60
  :regex: safari
55
61
  :version: (?<=version/)[0-9]+
56
- :safe_version: ["version/[0-9]+", "[0-9]+"]
57
62
 
58
- - :name: Konqueror
59
- :sym: :konqueror
63
+ :konqueror:
64
+ :name: Konqueror
60
65
  :regex: konqueror
61
66
 
62
- - :name: Unknown
63
- :sym: :unknown
67
+ :unknown:
68
+ :name: Unknown
64
69
  :regex: .*
65
- :version: .*
data/data/oses.yml CHANGED
@@ -1,72 +1,98 @@
1
- - :name: Windows 8
2
- :sym: :windows_8
1
+ :windows_8:
2
+ :name: Windows 8
3
3
  :family_sym: :windows
4
4
  :regex: windows nt 6\.2
5
- :icon: windows
6
5
 
7
- - :name: Windows 7
8
- :sym: :windows_7
6
+ :windows_7:
7
+ :name: Windows 7
9
8
  :family_sym: :windows
10
9
  :regex: windows nt 6\.1
11
- :icon: windows
12
10
 
13
- - :name: Windows Vista
14
- :sym: :windows_vista
11
+ :windows_vista:
12
+ :name: Windows Vista
15
13
  :family_sym: :windows
16
14
  :regex: windows nt 6\.0
17
- :icon: windows
18
15
 
19
- - :name: Windows XP
20
- :sym: :windows_xp
16
+ :windows_xp:
17
+ :name: Windows XP
21
18
  :family_sym: :windows
22
19
  :regex: windows nt 5\.[12]
23
- :icon: windows
24
20
 
25
- - :name: Windows
26
- :sym: :windows
21
+ :windows:
22
+ :name: Windows
27
23
  :regex: windows
28
24
 
29
- - :name: iOS
30
- :sym: :ios
31
- :family_sym: :osx
32
- :regex: (iphone)|(ipad)
25
+ :kindle_fire:
26
+ :name: Kindle Fire
27
+ :family_sym: :kindle
28
+ :regex: (kindle fire)|(silk-accelerated)
29
+ :mobile: true
33
30
 
34
- - :name: OS X
35
- :sym: :osx
31
+ :kindle:
32
+ :name: Kindle
33
+ :regex: kindle
34
+ :mobile: true
35
+
36
+ :ipod:
37
+ :name: iPod
38
+ :family_sym: :ios
39
+ :regex: \(ipod;
40
+ :mobile: true
41
+
42
+ :iphone:
43
+ :name: iPhone
44
+ :family_sym: :ios
45
+ :regex: \(iphone;
46
+ :mobile: true
47
+
48
+ :ipad:
49
+ :name: iPad
50
+ :family_sym: :ios
51
+ :regex: \(ipad;
52
+ :mobile: true
53
+
54
+ :ios:
55
+ :name: iOS
56
+ :regex: \(i\w+; .* like mac os x;
57
+ :mobile: true
58
+
59
+ :osx:
60
+ :name: OS X
36
61
  :regex: macintosh
37
62
 
38
- - :name: Android
39
- :sym: :android
40
- :family_sym: :linux
63
+ :android:
64
+ :name: Android
41
65
  :regex: android
66
+ :mobile: true
42
67
 
43
- - :name: Ubuntu
44
- :sym: :ubuntu
68
+ :ubuntu:
69
+ :name: Ubuntu
45
70
  :family_sym: :linux
46
71
  :regex: ubuntu
47
72
 
48
- - :name: Fedora
49
- :sym: :fedora
73
+ :fedora:
74
+ :name: Fedora
50
75
  :family_sym: :linux
51
76
  :regex: fedora
52
77
 
53
- - :name: Slackware
54
- :sym: :slackware
78
+ :slackware:
79
+ :name: Slackware
55
80
  :family_sym: :linux
56
81
  :regex: slackware
57
82
 
58
- - :name: GNU/Linux
59
- :sym: :linux
83
+ :linux:
84
+ :name: GNU/Linux
60
85
  :regex: linux
61
86
 
62
- - :name: FreeBSD
63
- :sym: :freebsd
87
+ :freebsd:
88
+ :name: FreeBSD
64
89
  :regex: freebsd
65
90
 
66
- - :name: BlackBerry
67
- :sym: :blackberry
91
+ :blackberry:
92
+ :name: BlackBerry
68
93
  :regex: blackberry
94
+ :mobile: true
69
95
 
70
- - :name: Unknown
71
- :sym: :unknown
96
+ :unknown:
97
+ :name: Unknown
72
98
  :regex: .*
@@ -0,0 +1,60 @@
1
+ # A browser user agent string parser. Use DoubleAgent.parse(user_agent) to return a DoubleAgent::UserAgent object, which you can
2
+ # query with methods like "browser_name" or "os". The DoubleAgent module itself responds to those same method - just
3
+ # pass the user agent string as an argument.
4
+ module DoubleAgent
5
+ # A hash of browser data, the basis for browser parsing. You may edit this data and call load_browsers! to customize parsing.
6
+ BROWSER_DATA = Psych.load_file(File.expand_path('../../../data/browsers.yml', __FILE__))
7
+
8
+ # A hash of OS hashes, the basis for OS parsing. You may edit this data and call load_oses! to customize parsing.
9
+ OS_DATA = Psych.load_file(File.expand_path('../../../data/oses.yml', __FILE__))
10
+
11
+ BROWSER_PARSERS, OS_PARSERS = {}, {} # :nodoc:
12
+
13
+ # Returns a new UserAgent object
14
+ def self.parse(user_agent_string)
15
+ UserAgent.new(user_agent_string)
16
+ end
17
+
18
+ # Forwards calls to a UserAgent object
19
+ def self.method_missing(method, *args, &block)
20
+ parse(args.first).send(method)
21
+ end
22
+
23
+ # Transforms BROWSER_DATA into a case statement inside of the _browser_sym method
24
+ def self.load_browsers!
25
+ BROWSER_PARSERS.clear.merge! Hash[BROWSER_DATA.map { |sym, data| [sym, BrowserParser.new(sym, data)] }]
26
+
27
+ module_eval <<-CODEZ
28
+ def self._browser_sym(user_agent)
29
+ case user_agent.to_s
30
+ #{BROWSER_DATA.map { |sym, data| "when %r{#{data[:regex]}}i then :\"#{sym}\"" }.join("\n")}
31
+ end
32
+ end
33
+ CODEZ
34
+ end
35
+
36
+ # Transforms OS_DATA into a case statement inside of the _os_sym method
37
+ def self.load_oses!
38
+ OS_PARSERS.clear.merge! Hash[OS_DATA.map { |sym, data| [sym, OSParser.new(sym, data)] }]
39
+
40
+ module_eval <<-CODEZ
41
+ def self._os_sym(user_agent)
42
+ case user_agent.to_s
43
+ #{OS_DATA.map { |sym, data| "when %r{#{data[:regex]}}i then :\"#{sym}\"" }.join("\n")}
44
+ end
45
+ end
46
+ CODEZ
47
+ end
48
+
49
+ private
50
+
51
+ # Returns the correct BrowerParser for the given user agent or symbol
52
+ def self.browser_parser(ua_or_sym)
53
+ BROWSER_PARSERS[ua_or_sym.is_a?(Symbol) ? ua_or_sym : _browser_sym(ua_or_sym)]
54
+ end
55
+
56
+ # Returns the correct OSParser for the given user agent or symbol
57
+ def self.os_parser(ua_or_sym)
58
+ OS_PARSERS[ua_or_sym.is_a?(Symbol) ? ua_or_sym : _os_sym(ua_or_sym)]
59
+ end
60
+ end
@@ -1,192 +1,72 @@
1
- begin
2
- require 'psych'
3
- rescue LoadError
4
- end
5
- require 'yaml'
6
-
7
1
  module DoubleAgent
8
- # An array of "browser knowledge hashes," the basis of browser parsing. You may edit this data and call load_browsers! to customize parsing.
9
- BROWSER_DATA = YAML.load_file(File.expand_path('../../../data/browsers.yml', __FILE__))
10
-
11
- # An array of "OS knowledge hashes," the basis of OS parsing. You may edit this data and call load_oses! to customize parsing.
12
- OS_DATA = YAML.load_file(File.expand_path('../../../data/oses.yml', __FILE__))
13
-
14
- # An array of BrowserParser objects created from the data in BROWSER_DATA.
15
- BROWSERS = {}
16
-
17
- # An array of OSParser objects created from the data in OS_DATA.
18
- OSES = {}
19
-
20
2
  # Each browser in BROWSER_DATA gets its own BrowserParser object. These
21
3
  # parser objects are then used to parse specific data out of a user agent string.
22
-
23
4
  class BrowserParser
24
- BLANK = ''
25
- MIN_VERSION = '1.9.2'
26
- attr_reader :sym, :family_sym, :icon
5
+ # The browser name
6
+ attr_reader :name
7
+ # The browser name as a symbol
8
+ attr_reader :sym
9
+ # The browser family name as a symbol
10
+ attr_reader :family_sym
27
11
 
28
12
  # Instantiate a new BrowserParser using a "browser family" element from BROWSER_DATA
29
- def initialize(attrs={})
30
- @sym = attrs[:sym]
13
+ def initialize(sym, attrs={})
14
+ @sym = sym
31
15
  @family_sym = attrs[:family_sym] || @sym
32
16
  @name = attrs[:name]
33
- @icon = attrs[:icon] || @sym
34
- if RUBY_VERSION < MIN_VERSION and attrs[:safe_version]
35
- @safe_version = attrs[:safe_version].map { |r| Regexp.new r, Regexp::IGNORECASE }
36
- elsif attrs[:version]
37
- @version = Regexp.new(attrs[:version], Regexp::IGNORECASE)
17
+ if attrs[:version]
18
+ @version_pattern = Regexp.new(attrs[:version], Regexp::IGNORECASE)
38
19
  end
39
20
  end
40
21
 
41
22
  # Returns the browser's name. If you provide a user agent string as an argument,
42
23
  # it will attempt to also return the major version number. E.g. "Firefox 4".
43
24
  def browser(ua=nil)
44
- if ua and (@version or @safe_version)
45
- @name % version(ua)
46
- else
47
- (@name % BLANK).rstrip
48
- end
25
+ (ua and @version_pattern) ? "#{name} #{version(ua)}" : name
26
+ end
27
+
28
+ # Attempts to parse and return the browser's version from a user agent string. Returns
29
+ # nil if nothing is found.
30
+ def version(ua)
31
+ ua.slice(@version_pattern)
49
32
  end
50
33
 
51
34
  # Returns the BrowserParser for this BrowserParser object's Family. E.g. the Chrome
52
35
  # BrowserParser would return the Chromium BrowserParser. For browsers that are their
53
36
  # own family (e.g. Firefox, IE) it will end up returning itself.
54
37
  def family
55
- BROWSERS[@family_sym]
56
- end
57
-
58
- private
59
-
60
- # Attempts to parse and return the browser's version from a user agent string. Returns
61
- # nil if nothing is found.
62
- def version(ua)
63
- if @safe_version
64
- ua.slice(@safe_version[0]).slice(@safe_version[1]) rescue nil
65
- else
66
- ua.slice(@version)
67
- end
38
+ BROWSER_PARSERS[family_sym]
68
39
  end
69
40
  end
70
41
 
71
- # Each OS in OS_DATA gets its own OSParser object. In theory, these parser
72
- # objects can then be used to grab further info from user agent strings, though
73
- # that is not currently happening.
74
-
42
+ # Each OS in OS_DATA gets its own BrowserParser object. These
43
+ # parser objects are then used to parse specific data out of a user agent string.
75
44
  class OSParser
76
- attr_reader :os, :sym, :family_sym, :icon
45
+ # The operating system name
46
+ attr_reader :os
47
+ # The operating system name as a symbol
48
+ attr_reader :sym
49
+ # The operating system family name as a symbol
50
+ attr_reader :family_sym
77
51
 
78
52
  # Instantiate a new OSParser using an "OS family" element from OS_DATA
79
- def initialize(attrs={})
80
- @sym = attrs[:sym]
53
+ def initialize(sym, attrs={})
54
+ @sym = sym
81
55
  @family_sym = attrs[:family_sym] || @sym
82
56
  @os = attrs[:name]
83
- @icon = attrs[:icon] || @sym
57
+ @mobile = attrs[:mobile] || false
58
+ end
59
+
60
+ # Returs true if this is mobile OS, false if not
61
+ def mobile?
62
+ @mobile
84
63
  end
85
64
 
86
65
  # Returns the OSParser for this OSParser object's Family. E.g. the Ubuntu
87
66
  # OSParser would return the GNU/Linux OSerParser. For OSes that are their own
88
67
  # family (e.g. OS X) it will end up returning itself.
89
68
  def family
90
- OSES[@family_sym]
91
- end
92
- end
93
-
94
- # Returns the browser's name, possibly including the version number, e.g. "Chrome 12"
95
- def self.browser(ua)
96
- browser_parser(ua).browser(ua)
97
- end
98
-
99
- # Returns the browser's symbol name, e.g. :chrome
100
- def self.browser_sym(user_agent)
101
- # This method is overwitten by load_browsers!
102
- end
103
-
104
- # Returns the browser's icon name, e.g. :chrome
105
- def self.browser_icon(ua)
106
- browser_parser(ua).icon
107
- end
108
-
109
- # Returns the browser's family name, e.g. "Chromium"
110
- def self.browser_family(ua)
111
- browser_parser(ua).family.browser
112
- end
113
-
114
- # Returns the browser's family's symbol name, e.g. :chromium
115
- def self.browser_family_sym(ua)
116
- browser_parser(ua).family_sym
117
- end
118
-
119
- # Returns the browser's family's icon name, e.g. :chromium
120
- def self.browser_family_icon(ua)
121
- browser_parser(ua).family.icon
122
- end
123
-
124
- # Returns the OS's name, e.g. "Ubuntu"
125
- def self.os(ua)
126
- os_parser(ua).os
127
- end
128
-
129
- # Returns the OS's symbol name, e.g. :ubuntu
130
- def self.os_sym(user_agent)
131
- # This method is overwitten by load_oses!
132
- end
133
-
134
- # Returns the OS's icon name, e.g. :ubuntu
135
- def self.os_icon(ua)
136
- os_parser(ua).icon
137
- end
138
-
139
- # Returns the OS's family, e.g. "GNU/Linux"
140
- def self.os_family(ua)
141
- os_parser(ua).family.os
142
- end
143
-
144
- # Returns the OS's family's symbol name, e.g. :linux
145
- def self.os_family_sym(ua)
146
- os_parser(ua).family_sym
147
- end
148
-
149
- # Returns the OS's family's symbol icon, e.g. :linux
150
- def self.os_family_icon(ua)
151
- os_parser(ua).family.icon
152
- end
153
-
154
- # Returns the correct BrowerParser for the given user agent or symbol
155
- def self.browser_parser(ua_or_sym)
156
- BROWSERS[ua_or_sym.is_a?(Symbol) ? ua_or_sym : browser_sym(ua_or_sym)]
157
- end
158
-
159
- # Returns the correct OSParser for the given user agent or symbol
160
- def self.os_parser(ua_or_sym)
161
- OSES[ua_or_sym.is_a?(Symbol) ? ua_or_sym : os_sym(ua_or_sym)]
162
- end
163
-
164
- # Parses BROWSER_DATA into BROWSERS, a hash of BrowserParser objects indexed by their symbol names.
165
- # Parses and evals BROWSER_DATA into a case statement inside of the browser_sym method.
166
- def self.load_browsers!
167
- BROWSERS.clear
168
- str = "case user_agent.to_s\n"
169
- BROWSER_DATA.each do |data|
170
- BROWSERS[data[:sym]] = BrowserParser.new(data)
171
- str << " when %r{#{data[:regex]}}i then :#{data[:sym]}\n"
69
+ OS_PARSERS[family_sym]
172
70
  end
173
- str << 'end'
174
- module_eval "def self.browser_sym(user_agent); #{str}; end"
175
- end
176
-
177
- # Parses OS_DATA into OSES, a hash of OSParser objects indexed by their symbol names.
178
- # Parses and evals OS_DATA into a case statement inside of the os_sym method.
179
- def self.load_oses!
180
- OSES.clear
181
- str = "case user_agent.to_s\n"
182
- OS_DATA.each do |data|
183
- OSES[data[:sym]] = OSParser.new(data)
184
- str << " when %r{#{data[:regex]}}i then :#{data[:sym]}\n"
185
- end
186
- str << 'end'
187
- module_eval "def self.os_sym(user_agent); #{str}; end"
188
71
  end
189
72
  end
190
-
191
- DoubleAgent.load_browsers!
192
- DoubleAgent.load_oses!