User Tools

Site Tools


inf:ruby:rozdz_10

Tworzenie pliku Gem

Kroki do utworzenia Gemu:

  1. organizacja kodu i innych plikow w odpowiednia strukture,
    1. Tworzymy folder z nazwa gemu (string_extend w przypadku naszego string_extend.rb),
    2. lib - kod zwiazany z biblioteka,
    3. pkg - tymczasowy katalog, w ktorym zostanie wygenerowany Gem,
    4. test - testy jednostkowe, etc.,
    5. doc - dokumentacja,
    6. bin - narzedzia i skrypty systemowe,
  2. tworzenie pliku specyfikacyjnego z informacjami o Gemie (string_extend.gemspec),
require 'rubygems'
 
spec = Gem::Specification.new do |s|
    s.name                  = 'string_extend'
    s.version               = '0.0.1'
    s.summary               = "StringExtend adds useful features..."
    s.files                 = Dir.glob("**/**/**")
    s.test_files            = Dir.glob("test/*_test.rb")
    s.author                = "Your Name"
    s.email                 = "your-email-address@email.com"
    s.has_rdoc              = false
    s.required_ruby_version = '>= 1.8.2'
end
  1. uzycie programu gem do stworzenia Gemu z plikow zrodlowych i specyfikacji: gem build string_extend.gemspec utworzy plik Gem string_extend-0.0.1.gem.

Jest tez prostszy sposob, za pomoca Gema newgem: newgem your_lib_name.

Udostepnianie aplikacji jako zewnetrznej uslugi

CGI Scripts

Jedna z metod udostepniania swoich plikow Rubego jest wykorzystanie skryptow CGI. CGI to standard, umozliwiajacy serwerowi http uruchamiac programy i przesylac dane pomiedzy nimi a klientem.

Plik CGI moglby wygladac tak:

#!/usr/bin/ruby
 
puts "Content-type: text/html\n\n"
puts "<html><body>This is a test.</body></html>"

W Rubym istnieje specjalna biblioteka wspomagajaca pisanie skryptow dla CGI. Jesli mielibysmy formularz HTML z elementem <input>, ktory wysylalby cos do naszego skryptu CGI, mozna do tych danych dostac sie tak:

#!/usr/bin/ruby
 
require 'cgi'
 
cgi = CGI.new
 
text = cgi['text']
 
puts cgi.header
puts "<html><body>#{text.reverse}</body></html>"

Odchodzi sie od skryptow CGI z powodow wydajnosciowych i koniecznosci uruchamiania interpretatora Rubego dla kazdego odwolania.

Serwery HTTP

WEBrick

# webrick.rb
 
require 'webrick'
 
server = WEBrick::GenericServer.new(:Port => 1234)
 
trap("INT") { server.shutdown }
 
server.start do |socket|
    socket.puts Time.now
end

Duzo bardziej potezna technika zwiazana jest z serwletami, ktore istnieja w swojej wlasnej klasie i maja wiecej kontroli nad zadaniami i odpowiedziami do nich skierowanymi:

# webrick_2.rb
 
require 'webrick'
 
class MyServlet < WEBrick::HTTPServlet::AbstractServlet
    def do_GET(request, response)
        response.status = 200
        response.content_type = "text/plain"
        response.body = "Hello, world!"
    end
end
 
server = WEBrick::HTTPServer.new(:Port => 1234)
server.mount "/", MyServlet
 
trap("INT") { server.shutdown }
server.start
# webrick_3.rb
 
require 'webrick'
 
class MyNormalClass
    def MyNormalClass.add(a, b)
        a.to_i + b.to_i
    end
 
    def MyNormalClass.subtract(a, b)
        a.to_i - b.to_i
    end
end
 
class MyServlet < WEBrick::HTTPServlet::AbstractServlet
    def do_GET(request, response)
        if request.query['a'] && request.query['b']
            a = request.query['a']
            b = request.query['b']
            response.status = 200
            response.content_type = 'text/plain'
            result = nil
 
            case request.path
                when '/add'
                    result = MyNormalClass.add(a, b)
                when '/subtract'
                    result = MyNormalClass.subtract(a, b)
                else
                    result = "No such method."
            end
 
            response.body = result.to_s + "\n"
 
        else
 
            response.status = 400
            response.body = "No parameters, you n00b."
 
        end
 
    end
 
end
 
server = WEBrick::HTTPServer.new(:Port => 1234)
server.mount '/', MyServlet
trap('INT') { server.shutdown }
server.start

http://microjet.ath.cx/WebWiki/WEBrick.html

Mongrel

Mongrel to szybszy, stabilniejszy serwer HTTP.

# mongrel.rb
 
require 'rubygems'
require 'mongrel'
 
class BasicServer < Mongrel::HttpHandler
    def process(request, response)
        response.start(200) do |headers, output|
            headers["Content-Type"] = 'text/html'
            output.write('<html><body><h1>Hello!</h1></body></html>')
        end
    end
end
 
s = Mongrel::HttpServer.new("0.0.0.0", "1234")
s.register("/", BasicServer.new)
s.run.join

RPC

Tam, gdzie jeden program wykorzystuje procedury i metody udostepniane przez inny, mozna skorzystac z RPC (Remote Procedure Call). W Rubym mamy XML-RPC, SOAP i Drb.

XML-RPC

Protokół przesyla dane jako XML, do transportu wykorzystujac HTTP. Zaleta takiego rozwiazania jest to, ze mozna napisac kilka programow w roznych jezykach, a i tak beda one mogly sie dogadac ze soba.

# xmlrpc_2.rb
require 'xmlrpc/client'
 
server = XMLRPC::Client.new2("http://www.rubyinside.com/book/xmlrpctest.cgi")
ok, results = server.call2("sample.sumAndDifference", 5, 3)
 
if ok
    puts results.inspect
else
    puts results.faultCode
    puts results.faultString
end

Output:

{"sum"=>8, "difference"=>2}

Tworzenie serwera XMLRPC:

# xmlrpc_server.rb
 
require 'xmlrpc/server'
 
server = XMLRPC::Server.new(1234)
server.add_handler("sample.sumAndDifference") do |a, b|
    { "sum" => a.to_i + b.to_i,
      "difference" => a.to_i - b.to_i }
end
 
trap("INT") { server.shutdown }
server.serve

DRb

DRb (Distributed Ruby) to biblioteka Rubego, na pierwszy rzut oka podobna do XML-RPC. Jesli komunikowac maja sie tylko programy napisane w Rubym, oferuje wiecej mozliwosci. Jest zorientowana obiektowo.

Klient:

# drb_client.rb
 
require 'drb'
 
remote_object = DRbObject.new nil, 'druby://sqbell-gentoo:45073'
puts remote_object.some_method

Serwer:

# drb_server.rb
 
require 'drb'
 
class OurClass
    def some_method
        "Some test text."
    end
end
 
DRb.start_service nil, OurClass.new
puts "DRb server running at #{DRb.uri}"
trap("INT") {DRb.stop_service }
DRb.thread.join
inf/ruby/rozdz_10.txt · Last modified: 2021/02/16 09:56 (external edit)