:: Topo :: doCoding :: Linguagens de Programação :: Ruby :: MVC ::
Ramaze
Introdução
A framework Ramaze tem sido desenvolvida através da aplicação da metodologia BDD. Tem um conjunto mínimo de dependências, tanto que muitas aplicações apenas irão precisar de Ruby e Rack - além da Ramaze - para correrem. A Ramaze é construída para se manter leve e eliminar ou evitar o que não é realmente necessário.
Tem como princípios fundamentais: KISS, POLS, desenho modular, conjunto de dependências mínimo, documentação em código de elevada qualidade, desenvolvimento aberto e livre, recomendar a aplicação de BDD no desenvolvimento.
Background
Tal como descrito pelo autor: Ramaze is a simple, light and modular open-source web-framework written in Ruby. It provides several easy to understand and fully documented abstractions useful for the daily work of a pragmatic webdeveloper.
Os notáveis no projecto são: Aman Gupta, Jonathan Buch and Pistos. Michael Fellinger é o criador do projecto. Muito dos conceitos vieram da framework Nitro.
Referências
Oficiais
Artigos
Tutorials
Características
Além de ser simplista e basear-se em princípios simples, apresenta as seguintes características:
- Agnóstica em relação ao interpretador de Ruby:
- MRI 1.8.x
- MRI 1.9.x
- JRuby 1.x
- Rubinius
- Agnóstica em relação à library ORM a usar nos modelos:
- Sequel
- Data Mapper
- Active Record
- M4DBI
- Stone
- Agnóstica em relação ao templating engine a usar nas views:
- Ezamar
- Erb
- Eruby
- Erubis
- Haml / Sass
- Liquid
- Markaby
- Remarkably
- Amrita / Amrita2
- Tenjin
- Nagoro
- XSLT
- Agnóstica em relação ao servidor HTTP, pois tem como base o Rack.
Exploração
ToDoList
Neste tutorial encontrei alguns pequenos percalços, que aqui registo.
Quando se alterar um Controller, com o serviço em execução, não haverá refrescamento automático do código, pelo que é preciso terminar o serviço e voltar a lança-lo em execução, para que as alterações ao Controller sejam vistas pela Ramaze.
Step 2
Para que não ocorram problemas no Step 3, é preciso editar também o ficheiro model/init.rb:
model/init.rb
# Here goes your database connection and options: # Here go your requires for models: # require 'model/user' require 'model/todo_list'
Step 8
Foi graças ao artigo Ramaze - first impressions que percebi que não existe nem as pastas nem o ficheiro src/element/page.rb, pelo que não consegui entender o uso do Templating Engine Ezamar.
Em alternativa, e porque existe o ficheiro view/page.xhtml, decidi adaptar e efectuei as seguintes alterações:
view/page.xhtml
<?xml version="1.0" ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>TodoList</title> <meta http-equiv="Content-Script-Type" content="text/javascript" /> <meta http-equiv="Content-Style-Type" content="text/css" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta http-equiv="expires" content="0" /> <meta name="description" content="Description for search engines" /> <meta name="generator" content="Ramaze #{Ramaze::VERSION}" /> <meta name="keywords" content="Ramaze, Your own keywords" /> <meta name="author" content="Max Mustermann" /> <meta name="date" content="#{Time.now.iso8601}" /> <style type="text/css"> body { margin: 2em; } #content { margin-left: 2em; } </style> </head> <body> <h1>#{ @title }</h1> <div id="content"> #@content </div> </body> </html>
Step 10
Por omissão, no ficheiro start.rb, vem já a linha:
start.rb
... Ramaze.start :adapter => :webrick, :port => 7000
É preciso comentar essa linha, antes de experimentar iterativamente as várias possibilidade de configurar o servidor:
start.rb
... Ramaze::Global.port = 7000
start.rb
... Ramaze::Global.port = 7000 Ramaze::Global.adapter = :mongrel
start.rb
... Ramaze::Global.setup do | g | g.port = 7000 g.adapter = :mongrel end
start.rb
... Ramaze.start :port => 7000, :adapter => :mongrel
No entanto, optei por não ter qualquer configuração, o que me permite escolher o servidor a executar e o porto onde quero que fique à espera de ligações:
start Ramaze
ramaze --adapter thin --port 7000Considerações
Benchmarking
É importante realizar 2 benchmarkings: uma simples aplicação HelloWord que apresente, por exemplo, a data actual do sistema host; uma aplicação com Modelos, Vistas e Controladores. A primeira para realizar simples benchmarks dos servidores (Webrick, Mongrel, Thin, …) e para mais tarde servir de comparação com outras frameworks e a segunda para avaliar o impacto, fixando o servidor (por exemplo: Mongrel) dos engines para os modelos e para as vistas.
Servers
Algo surpreendente, foi receber os resultados e comprovar que o Ruby sobre Cygwin é mais rápido que o Ruby sobre Windows. No caso do Webrick chega mesmo a ser quase 2x mais rápido.
Confirma-se, portanto, que o Webrick é 50% mais lento que o Mongrel, e que o Thin é mais rápido - se bem que marginalmente (no entanto é cerca de 25% mais rápido em Windows).
Também importa realçar que a máquina Ubuntu, em hardware, é mais lenta que a máquina Windows - sendo ambas Core2 Duo - mas sobre a qual a Ramaze sobre Ruby consegue ser quase 2x mais rápida em qualquer servidor. No entanto, a performance em JRuby é semelhante.
Storage Engines
Para ter mais dados, que tornassem o benchmarking mais credível, decidi codificar um script para popular o storage com 5000 tasks.
A comparação será simplesmente entre Stone e Sequel com SQLite, não havendo tempo para também efectuar benchmarking com M4DBI, ActiveRecord ou DataMapper. Descobri entretanto que o Ramaze::Store é um wrapper sobre o YAML::Store, e que além disso demora imenso tempo - inaceitável - a popular o ficheiro YAML com 5000 entradas.
2009.01.30
Não consegui usar o Stone com a Ramaze. Após ter editado o model TodoList, nem consegui popular com as 5000 entradas nem consegui que a página index fosse sequer mostrada - foi-me devolvido o erro undefined method 'original' for TodoList:Class. Algo semelhante aconteceu com o autor do artigo Ramaze - first impressions continued. Como neste artigo o ORM escolhido foi o Sequel, vou então usar somente o Sequel para o benchmarking.
Depois de concluir as modificações para correr o benchmarking para 25 entradas somente com Sequel::SQLite3 consegui também modificar o código usando Ramaze::Store. Estas modificações permitiram que após serem migradas e adaptadas para Stone que este finalmente conseguisse funcionar com Ramaze quase totalmente. Não consegui, de todo, que:
- a pasta datastore/ com os ficheiros YAML fosse populada, com as 25 entradas.
- que após inserir nova entrada, com sucesso, e validar que o estado alterna, com sucesso entre open e close, também fosse possível apagar a entrada. Na realidade, é apagada do storage, mas o array de @tasks no método index() do MainController continua sempre populado com todas as entradas. Ou é um erro do Stone, ou falta-me ainda resolver essa funcionalidade no MainController.
No entanto, consegui os benchmarks necessários:
- Desta vez o Ruby sobre Windows foi mais rápido do que o Ruby sobre Cygwin quando se usa Ramaze::Store:
- Cygwin: 37.54
- Windows: 47.65
- Mas voltou a repetir-se o Ruby sobre Cygwin ser mais rápido que o Ruby sobre Windows quando se usa Sequel::SQLite (in-memory):
- Cygwin: 56.54
- Windows: 39.46
Importa realçar que enquanto que o Cygwin tem quase o dobro da performance com Sequel do que Ramaze::Store, em Windows ambos conseguem processar o mesmo número de requests por segundo, relativamente.
