Skip to content

Commit 1ab297f

Browse files
committed
perf: evaluate different parsers only when accessing their results
1 parent a4de134 commit 1ab297f

File tree

1 file changed

+82
-40
lines changed

1 file changed

+82
-40
lines changed

lib/device_detector.rb

Lines changed: 82 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -67,58 +67,57 @@ def initialize(user_agent = nil, headers = nil)
6767
end
6868

6969
def name
70-
return unless @client
70+
return unless client_result
7171

72-
@client[:name]
72+
client_result[:name]
7373
end
7474

7575
def full_version
76-
return unless @client
76+
return unless client_result
7777

78-
@client[:version]
78+
client_result[:version]
7979
end
8080

8181
def os_family
82-
presence(@os&.fetch(:family, nil))
82+
presence(os_result[:family])
8383
end
8484

8585
def os_name
86-
presence(@os&.fetch(:name, nil))
86+
presence(os_result[:name])
8787
end
8888

8989
def os_full_version
90-
presence(@os&.fetch(:version, nil))
90+
presence(os_result[:version])
9191
end
9292

9393
def device_name
94-
presence(@model)
94+
presence(device_result[:model])
9595
end
9696

9797
def device_brand
98-
presence(@brand)
98+
presence(device_result[:brand])
9999
end
100100

101101
def device_type
102-
presence(@device)
102+
presence(device_result[:device])
103103
end
104104

105105
def known?
106-
!@client.nil?
106+
!client_result.nil?
107107
end
108108

109109
def bot?
110-
@bot ? true : false
110+
bot_result ? true : false
111111
end
112112

113113
def bot_name
114-
@bot&.fetch(:name, nil)
114+
bot_result&.fetch(:name, nil)
115115
end
116116

117117
def use(user_agent, headers = nil)
118118
reset
119119
self.user_agent = user_agent
120120
self.headers = headers
121-
parse
122121
self
123122
end
124123

@@ -149,40 +148,69 @@ def configure
149148

150149
private
151150

152-
def parse
153-
return if @parsed
151+
def bot_result
152+
return @bot_result if @bot_parsed
154153

155-
@parsed = true
154+
@bot_parsed = true
155+
@bot_result = parse_bot if should_parse?
156+
end
157+
158+
def client_result
159+
return @client_result if @client_parsed
160+
161+
@client_parsed = true
156162

157-
return if (@user_agent.empty? || @user_agent !~ /[a-z]/i) && @client_hints.nil?
163+
@client_result = if bot? || !should_parse?
164+
nil
165+
else
166+
parse_client
167+
end
168+
end
158169

159-
parse_bot
160-
return if bot?
170+
def os_result
171+
return @os_result if @os_parsed
161172

162-
parse_os
163-
parse_client
164-
parse_device
173+
@os_parsed = true
174+
@os_result = if bot? || !should_parse?
175+
{}
176+
else
177+
parse_os
178+
end
179+
end
180+
181+
def device_result
182+
return @device_result if @device_parsed
183+
184+
@device_parsed = true
185+
@device_result = if bot? || !should_parse?
186+
{}
187+
else
188+
parse_device
189+
190+
{
191+
model: @model,
192+
brand: @brand,
193+
device: @device
194+
}
195+
end
165196
end
166197

167-
# COPY_COMPLETE
168198
def parse_bot
169199
@parsers.fetch(:bot, []).each do |parser|
170200
parser.use(@user_agent, @client_hints)
171201

172202
bot = parser.parse
173203

174-
if bot
175-
@bot = bot
176-
break
177-
end
204+
return bot if bot
178205
end
206+
nil
179207
end
180208

181209
def parse_os
182210
parser = @operating_system_parser
183211
parser.use(@user_agent, @client_hints)
184212

185-
@os = parser.parse
213+
parser.parse || {}
186214
end
187215

188216
def parse_client
@@ -191,11 +219,9 @@ def parse_client
191219

192220
client = parser.parse
193221

194-
if client
195-
@client = client
196-
break
197-
end
222+
return client if client
198223
end
224+
nil
199225
end
200226

201227
def parse_device
@@ -327,13 +353,21 @@ def headers=(headers)
327353

328354
# Resets all detected data
329355
def reset
330-
@bot = nil
331-
@client = nil
332-
@device = nil
333-
@os = nil
334-
@brand = nil
356+
@bot_result = nil
357+
@bot_parsed = nil
358+
359+
@client_result = nil
360+
@client_parsed = nil
361+
362+
@os_result = nil
363+
@os_parsed = nil
364+
365+
@device_result = nil
366+
@device_parsed = nil
367+
335368
@model = nil
336-
@parsed = false
369+
@brand = nil
370+
@device = nil
337371
end
338372

339373
def add_parser(parser)
@@ -380,13 +414,21 @@ def desktop?
380414
end
381415

382416
def uses_mobile_browser?
383-
@client&.fetch(:type) == 'browser' && DeviceDetector::Parser::Client::Browser.mobile_only_browser?(name)
417+
client_result&.fetch(:type) == 'browser' && DeviceDetector::Parser::Client::Browser.mobile_only_browser?(name)
384418
end
385419

386420
def touch_enabled?
387421
match_user_agent('Touch')
388422
end
389423

424+
def should_parse?
425+
if (@user_agent.nil? || @user_agent.empty? || @user_agent !~ /[a-z]/i) && @client_hints.nil?
426+
return false
427+
end
428+
429+
true
430+
end
431+
390432
def presence(var)
391433
return nil if var.nil?
392434
return nil if var.empty?

0 commit comments

Comments
 (0)