Page 106 of 169

Ruby – Sprawdzanie dostępności linku ze znakami z UTF-8

Przed kilkoma dniami natrafiłem na pewien problem. Mianowicie open-uri i metoda open nie działają dla znaków z utf-8 (czyli między innymi dla stron gdzie fragment URLa ma "ogonki"). W związku z czym, taki fragment kodu będzie zawsze zwracał fałsz, mimo tego, że pod adresem istnieje strona:

# coding: utf-8
# Wesja rzecz jasna uproszczona - bez obsługi timeoutów itd
url = 'http://www.nina.gov.pl/nina/czołówka'
io_thing = open(url)
correct = io_thing.status[0] == '200'

Zasadniczo bez obsługi błędów będziemy dostawać taki oto wyjątek:

 bad URI(is not URI?): www.nina.gov.pl/nina/czołówka (URI::InvalidURIError)

Rozwiązanie tego problemu może nie jest zbyt eleganckie ale działa:

# coding: utf-8
require 'open-uri'
require 'net/http'

url = 'http://www.nina.gov.pl/nina/czołówka'
url = URI.parse(URI.encode(url))

correct = false
level = 0
while(!correct && level < 10) do
  requst = Net::HTTP.new(url.host, url.port)
  if url.to_s.include?('https')
    requst.use_ssl = true
    requst.verify_mode = OpenSSL::SSL::VERIFY_NONE
  end
  
  requst.start do |http|
    http = http.head(url.request_uri)
    if http.code == "200"
      correct = true
    else
      url = URI.parse(URI.encode(http.header['location'] ))
    end
    level += 1
  end
end

http.head nie podąża za przekierowaniami więc musimy robić to sami.

Mongoid, Kaminari i Padrino (Sinatra)

Część z Was już pewnie zauważyła, że w nowej wersji Mongoida (2.0.2) zrezygnowano z will_paginate. Will_paginate okazał się niezbyt efektywny, ponieważ nie obsługiwał opcji limit i kilku innych rzeczy, w skutek czego paginacja dużych zbiorów stawała się bardzo powolna. Zamiast tego jako podstawową metodę paginacji dla nowych wersji Mongoida zaleca się Kaminari. O Kaminari już parokrotnie wspominałem. Jest świetne. Niestety - nie jest aż tak wesoło kiedy trzeba je połączyć z aplikacją która nie jest napisana w Railsach. Zwykłe:

gem 'kaminari'
# i ew. gdzieś tam w kodzie jakby kogoś naszło
require 'kaminari'

na niewiele się zda.

Brak Kaminari skutkuje tego typu błędami:

NoMethodError: undefined method `page' for Note:Class
	/home/mencio/Rails/app/webui/app/controllers/notes.rb:7:in `GET /notes'
	/home/mencio/.rvm/gems/ruby-1.8.7-p299@app/gems/padrino-core-0.9.19/lib/padrino-core/application/routing.rb:340:in `call'
	/home/mencio/.rvm/gems/ruby-1.8.7-p299@app/gems/padrino-core-0.9.19/lib/padrino-core/application/routing.rb:340:in `route'
	/home/mencio/.rvm/gems/ruby-1.8.7-p299@app/gems/sinatra-1.1.3/lib/sinatra/base.rb:649:in `instance_eval'
	/home/mencio/.rvm/gems/ruby-1.8.7-p299@app/gems/sinatra-1.1.3/lib/sinatra/base.rb:649:in `route_eval'
	/home/mencio/.rvm/gems/ruby-1.8.7-p299@app/gems/padrino-core-0.9.19/lib/padrino-core/application/routing.rb:605:in `route!'
	/home/mencio/.rvm/gems/ruby-1.8.7-p299@app/gems/padrino-core-0.9.19/lib/padrino-core/application/routing.rb:605:in `catch'
	/home/mencio/.rvm/gems/ruby-1.8.7-p299@app/gems/padrino-core-0.9.19/lib/padrino-core/application/routing.rb:605:in `route!'
	/home/mencio/.rvm/gems/ruby-1.8.7-p299@app/gems/padrino-core-0.9.19/lib/padrino-core/application/routing.rb:596:in `catch'
	/home/mencio/.rvm/gems/ruby-1.8.7-p299@app/gems/padrino-core-0.9.19/lib/padrino-core/application/routing.rb:596:in `route!'
        # cd ...

Kaminari "z pudełka" średnio współpracuje z (całkiem fajną) mieszanką Padrino (frameworku zbudowanego na Sinatrze) oraz Mongoida. Rozwiązanie jest jednak bajecznie proste (chociaż niezbyt eleganckie). Tworzymy sobie plik config/preload/kaminari.rb a w nim umieszczamy poniższy kod:

require 'kaminari/railtie'
require 'kaminari/engine'
require 'kaminari/config'
require 'kaminari/helpers/action_view_extension'
require 'kaminari/helpers/paginator'
require 'kaminari/models/page_scope_methods'
require 'kaminari/models/configuration_methods'
require 'kaminari/models/mongoid_extension'
::Mongoid::Document.send :include, Kaminari::MongoidExtension::Document
::Mongoid::Criteria.send :include, Kaminari::MongoidExtension::Criteria

Następnie w pliku config/boot.rb umieszczamy (w sekcji Padrino.before_load):

  require File.expand_path("config/preload/kaminari", Padrino.root)

Copyright © 2025 Closer to Code

Theme by Anders NorenUp ↑