def browser?(b)
user_agents = {
:ff => /Firefox/,
:iphone=> /(Mobile\/.+Safari)/,
:safari=> /Safari/,
:ie => /MSIE/
}
user_agents[b] &&
request.env["HTTP_USER_AGENT"] &&
request.env["HTTP_USER_AGENT"] =~ user_agents[b]
end
# which browser aliases urls
def whichbrowser
if browser?(:iphone)
@browser="<a href='http://www.apple.com/iphone/features/safari.html'>mobile safari</a>"
elsif browser?(:safari)
@browser="<a href='http://www.apple.com/safari/download/'>safari</a>"
elsif browser?(:ff)
@browser="<a href='http://www.firefox.com/'>firefox</a>"
end
end
# good or bad can be overridden by a param in sinatra for testing purposes, thus @goodorbad = @goodorbad
def goodorbad
if @goodorbad
@goodorbad = @goodorbad
elsif browser?(:iphone) || browser?(:safari) || browser?(:ff)
@goodorbad = "good"
else
@goodorbad = "bad"
end
end
Refactorings
No refactoring yet !
Adam
October 17, 2008, October 17, 2008 05:27, permalink
require 'ostruct'
require 'configatron'
module Browser
class Base < OpenStruct
class AgentNotFound < StandardError; end
class << self
def browser
Configatron.instance.browser
end
def aliases
browser.to_hash.inject([]) do |keys,(key,value)|
keys << key unless value.nil?
keys
end
end
def find(user_agent)
if key = aliases.find { |name| Browser.get(name).match?(user_agent) }
Browser.get(key)
else
raise(AgentNotFound, "#{user_agent} is not a browser")
end
end
def get(alias_name)
attributes = browser.send(alias_name)
raise(AgentNotFound, "#{alias_name} is not a browser") if attributes.nil?
new(attributes.to_hash)
end
end
def good?
good
end
def match?(user_agent)
user_agent.match(match)
end
end
class UserAgent < Base
# Firefox
browser.ff.name = 'Firefox'
browser.ff.match = /Firefox/
browser.ff.url = 'http://www.firefox.com/'
browser.ff.good = true
# MobileSafari
browser.iphone.name = 'MobileSafari'
browser.iphone.match = /(Mobile\/.+Safari)/
browser.iphone.url = 'http://www.apple.com/iphone/features/safari.html'
browser.iphone.good = true
end
end
module BrowserHelper
include Browser
def current_browser
UserAgent.find(request.user_agent)
rescue UserAgent::AgentNotFound
end
def browser(name)
UserAgent.get(name)
rescue UserAgent::AgentNotFound
end
def browser?(name)
UserAgent.get(name).match?(request.user_agent)
rescue UserAgent::AgentNotFound
end
def link_to_browser_download
return unless current_browser
link_to(current_browser.name, current_browser.url) if current_browser.good?
end
end
seaofclouds
October 17, 2008, October 17, 2008 15:12, permalink
@adam - thanks for having a look! this is a huge step in making my code more extensible. i also appreciate the addition of rescues. this is a simple sinatra app and i'd like to keep it as light as possible. could your refactoring work without configatron? i don't mind using yaml, as i am for translation (i think you helped with that refactoring as well).
diovan
January 17, 2011, January 17, 2011 13:57, permalink
I have the same., http://diovan.webeden.co.uk/ diovan free, unf,
I have the same., http://diovan.webeden.co.uk/ diovan free, unf,
i have a simple browser detection script where i detect a users' browser, and using instance variables, associate the browser as being "good" or "bad", and also associate the browser with a url for the browser download page. my code works, but feels sloppy. i bet there's a way to achieve this with an array (below).
the array would be formatted like: "alias", "user agent", "display name", "url", "good or bad" - where "alias", "user agent", and "display name" could be consolidated (see safari and firefox). "good or bad" is optional, defaulting to good.
browsers = [
["ff", "Firefox", "firefox", "http://www.firefox.com/"],
["safari", "http://www.apple.com/safari/download/"]
["ie", "MSIE", "Microsoft Internet Explorer", "http://www.microsoft.com/windows/downloads/ie/getitnow.mspx", "bad"]
]
once refactored, i'd like to be able to do something like:
- if browser?(iphone)
and
- browser(iphone).url - would refer to array
- browser(iphone).name
- browser.url - would use current user_agent