En esta práctica extendemos la anterior 46.9 con información estadística acerca de las visitas. Se pide que se presenten gráficos estadísticos (barras, etc.) del número de visitas por día, por país, etc.
La información de las visitas
se guardará en una tabla Visit
.
Cada objeto Visit
representará una visita
a la URL corta y contendrá información acerca de la visita:
Visit
.
class ShortenedUrl include DataMapper::Resource property :id, Serial property :short, Text property :url, Text has n, :visits end
Visit
y que se le asocia con el
objeto de la tabla principal intentaremos obtener la dirección IP
y a partir de ella la información sobre el país.
Veamos una sesión con Pry para obtener el país asociado con una IP:
[1] pry(main)> require 'restclient' => true [2] pry(main)> require 'xmlsimple' => true
[3] pry(main)> xml = RestClient.get "http://api.hostip.info/get_xml.php?ip=193.145.124.21"; [4] pry(main)> puts xml <?xml version="1.0" encoding="ISO-8859-1" ?> <HostipLookupResultSet version="1.0.1" xmlns:gml="http://www.opengis.net/gml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.hostip.info/api/hostip-1.0.1.xsd"> <gml:description>This is the Hostip Lookup Service</gml:description> <gml:name>hostip</gml:name> <gml:boundedBy> <gml:Null>inapplicable</gml:Null> </gml:boundedBy> <gml:featureMember> <Hostip> <ip>193.145.124.21</ip> <gml:name>(Unknown city)</gml:name> <countryName>SPAIN</countryName> <countryAbbrev>ES</countryAbbrev> <!-- Co-ordinates are unavailable --> </Hostip> </gml:featureMember> </HostipLookupResultSet> => nil [5] pry(main)> xml.class => String
[10] pry(main)> cc = XmlSimple.xml_in(xml.to_s) => {"version"=>"1.0.1", "xmlns:gml"=>"http://www.opengis.net/gml", "xmlns:xsi"=>"http://www.w3.org/2001/XMLSchema-instance", "xsi:noNamespaceSchemaLocation"=> "http://www.hostip.info/api/hostip-1.0.1.xsd", "description"=>["This is the Hostip Lookup Service"], "name"=>["hostip"], "boundedBy"=>[{"Null"=>["inapplicable"]}], "featureMember"=> [{"Hostip"=> [{"ip"=>["193.145.124.21"], "name"=>["(Unknown city)"], "countryName"=>["SPAIN"], "countryAbbrev"=>["ES"]}]}]} [11] pry(main)> cc["featureMember"][0]['Hostip'][0]['countryAbbrev'] => ["ES"]
To implement this, we use the after
callback mechanism
in the Visit
object, where we call a method after
the object is created.
after :create, :set_country
Para lograr que cada vez que se crea un objeto Visit
se guarde el país
en la tabla Visit
la clase será algo parecido a esto:
class Visit include DataMapper::Resource property :id, Serial property :created_at, DateTime property :ip, IPAddress property :country, String belongs_to :link after :create, :set_country def set_country xml = RestClient.get "http://api.hostip.info/get_xml.php?ip=#{ip}"·· self.country = XmlSimple.xml_in(xml.to_s, ... self.save end ... end
Este método ilustra múltiples formas de obtener la IP de la visita:
def get_remote_ip(env) puts "request.url = #{request.url}" puts "request.ip = #{request.ip}" if addr = env['HTTP_X_FORWARDED_FOR'] puts "env['HTTP_X_FORWARDED_FOR'] = #{addr}" addr.split(',').first.strip else puts "env['REMOTE_ADDR'] = #{env['REMOTE_ADDR']}" env['REMOTE_ADDR'] end end
Este ejemplo crguezl/sinatra-chartkick-example:
~/sinatra/sinatra-chartkik(master)]$ git remote -v origin git@github.com:crguezl/sinatra-chartkick-example.git (fetch) origin git@github.com:crguezl/sinatra-chartkick-example.git (push) [~/sinatra/sinatra-chartkik(master)]$ pwd -P /Users/casiano/local/src/ruby/sinatra/sinatra-chartkikmuestra como usar chartkick para generar gráficos:
[~/sinatra/sinatra-chartkik(master)]$ cat sinchart2.rb require 'sinatra' require 'sinatra/reloader' if development? require 'chartkick' template :layout do <<LAYOUT <html> <head> <script src="http://www.google.com/jsapi"></script> <script src="chartkick.js"></script> </head> <body> <%= yield %> </body> </html> LAYOUT end template :index do <<INDEX <%= pie_chart({"Football" => 10, "Basketball" => 5}) %> INDEX end get '/' do erb :index end