Ruby On Rails Regis

1,697 views

Published on

Published in: Technology
0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,697
On SlideShare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
47
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide

Ruby On Rails Regis

  1. 1. Ruby on Rails Regis Pires Magalhães regispiresmag@gmail.com http://regispiresmag.googlepages.com Última atualização em 24/01/2007
  2. 2. Instalação do Ruby 1 – No Linux - http://rubyforge.org/frs/download.php/7858/ruby- 1.8.4.tar.gz tar xvzf ruby-<versão>.tgz ./configure make make install 2 – No Windows - One-Click Installer – já vem com RubyGems: http://rubyforge.org/frs/download.php/11488/ruby184-20.exe
  3. 3. Instalação do RubyGems • Desnecessário no Windows, pois já vem no One-Click Installer • RubyGems - gerenciador de pacotes do Ruby 1 – Descompactar: http://rubyforge.org/frs/download.php/11290/rubygems-0.9.0.zip 2 – Executar: ruby setup.rb
  4. 4. Instalação do Rails • Via Internet: gem install rails --include-dependencies • Local: – Ir para diretório onde estão os arquivos gem e executar: gem install activesupport actionpack actionmailer activerecord actionwebservice rails –-local – Arquivos necessários: • rails-1.1.6.gem • actionmailer-1.2.5.gem • actionpack-1.12.5.gem • actionwebservice-1.1.6.gem • activerecord-1.14.4.gem • activesupport-1.3.1.gem
  5. 5. Instalação do PostgreSQL • No Windows: – Descompactar: • postgresql-8.1.4-1.zip – Executar: • postgresql-8.1.msi
  6. 6. Instalação da biblioteca do PostgreSQL para o Ruby • Via internet: gem install postgres-pr • Local: gem install postgres-pr –-local
  7. 7. Criação do Banco de Dados create database <projeto>_<ambiente> create database livraria_development Ambientes: • Development - desenvolvimento • Test - testes • Production - produção
  8. 8. Criação de tabelas • usuarios • tipos – id serial (PK) – id serial (PK) – nome varchar(75) – descricao varchar(50) – email varchar(75) – senha varchar(10) • telefones – – id serial (PK) admin int4 – – usuario_id int4 img bytea – numero varchar(10) • categorias • produtos – id serial (PK) – id serial (PK) – descricao varchar(50) – descricao varchar(100) – tipo_id int4 – categoria_id int4
  9. 9. Criação do Projeto rails <projeto> >rails livraria create create app/controllers create app/helpers create app/models create app/views/layouts create config/environments create components create db create doc create lib create lib/tasks create log ...
  10. 10. Configuração do acesso a banco de dados • Abrir arquivo config/database.yml: development: adapter: postgresql database: livraria_development username: postgres password: 1234 host: localhost ...
  11. 11. Testando o Servidor WEB ruby script/server ruby script/server –e [development|test|production] • Development é o default.
  12. 12. Geração de um Scaffold • Scaffold - tradução: andaime, palanque, armação , esqueleto • Scaffold é um meio de criar código para um determinado modelo através de um determinado controlador. • É um meio de começarmos rapidamente a ver os resultados no navegador Web e um método muito rápido de implementar o CRUD (Create, Retrieve, Update, Delete) na sua aplicação. ruby script/generate scaffold <Model> <Controller> ruby script/generate scaffold Usuario Admin::Usuario • O controlador Admin::Usuario gerenciará as ações recebidas. O rails irá criar a seguinte estrutura de diretórios: <aplicação>/controllers/admin
  13. 13. Outras gerações comuns • Modelo: ruby script/generate model <Model> • Controlador: ruby script/generate controller <controller>
  14. 14. Diretórios da aplicação • controllers – Classes de controle. – Uma classe controller trata uma requisição Web do usuário. – A URL da requisição Web é mapeada para uma classe de controle e para um método dentro da classe. • views – Armazena as templates de visualização para preenchimento com dados da aplicação, conversão para HTML e retorno para o browser. • models – Armazena as classes que modelam e encapsulam dos dados armazenados nos bancos de dados da aplicação. • helpers – Armazena classes de auxílio usadas para ajudar as classes model, view e controller. Ajudam a manter os códigos de model, view e controller bastante enxutos.
  15. 15. Modelo <aplicação>/app/models/usuario.rb: class Usuario < ActiveRecord::Base end • A classe Usuario já é capaz de gerenciar os dados da tabela no banco de dados. • Não há necessidade de explicitar o mapeamento das colunas do banco com atributos da classe. • Rails não proíbe nada: se for necessário existe como mapear uma coluna para outro atributo de nome diferente. • Nome de tabela diferente da convenção: class EncomendaCliente < ActiveRecord::Base set_table_name quot;encomendas_clientesquot; end
  16. 16. Modelo • Toda entidade é criada no diretório padrão: /app/models/<controller>/<model>.rb • Toda entidade herda diretamente da classe ActiveRecord::Base . • Não há necessidade de mapear manualmente cada coluna da tabela. • Convenção: a classe tem o nome no singular (Usuario), a tabela tem o nome do plural (usuarios). • Convenção: Toda tabela tem uma chave primária chamada id que é de tipo auto-incremento.
  17. 17. Active Record Interativo ruby script/console • Toda entidade criada pode ser manipulada pelo console. • Facilita testes antes de criar as actions.
  18. 18. Acrescentando validação class Usuario < ActiveRecord::Base validates_presence_of :nome validates_length_of :nome, :maximum => 75, :message => quot;Máximo de %d caracteres.quot; end Outros exemplos: validates_uniqueness_of :cpf validates_length_of :cpf, :is => 11 validates_length_of :user_name, :within => 6..20, :too_long => quot;deve ser menorquot;, :too_short => quot;deve ser maiorquot; validates_length_of :first_name, :maximum=>30
  19. 19. Controller • Todo Controller fica no diretório: /app/controllers/<nome>_controller.rb • Todo Controller herda a classe ApplicationController • Todo aplicativo Rails é criado com uma classe chamada ApplicationController que herda de , ActionController::Base e é base de todos os outros , controllers • Todo método de um controller é chamado de Action • Uma classe Controller pode ter quantas Actions quanto necessárias. class Admin::UsuarioController < ApllicationController def index render :text => “Hello World!” end end
  20. 20. Acessando uma Action • Roteamento Customizável (routes.rb) http://localhost:3000/:controller/:action/:id • Exemplo: http://localhost:3000/blog/index • blog = app/controller/blog_controller.rb • index = método index em BlogController
  21. 21. View index.rhtml: <h3>Hello da View!</h3> blog_controller.rb:
  22. 22. Mais convenções • Ao final de toda Action, Rails chamará uma view com o mesmo nome da Action, no seguinte diretório: /app/views/<controller>/<action>.<ext> • A extensão do arquivo pode ser: – .rhtml - Embedded Ruby (HTML+Ruby) – .rxml - XML Builder (Ruby puro) – .rjs - Javascript Generator (Ruby puro) • Este fluxo pode ser interrompido com uma chamada explícita ao método render ou redirect_to.
  23. 23. Modificando a listagem /app/views/admin/usuario/list.rhtml • Podemos alterar o layout ou qualquer código como quisermos.
  24. 24. Layouts • Layouts permitem o compartilhamento de conteúdo. • Todo novo controller automaticamente ganha um layout no diretório: /app/views/layouts/<controller>.rhtml • As views desse controller preenchem o espaço: <%= @content_for_layout %>
  25. 25. Layouts # test_controller.rb class TestController < ApplicationController layout quot;defaultquot; def index end end <!-- default.rhtml --> <html> <head> <title>Teste</title> </head> <body> <h1>Layout Padrao</h1> <%= @content_for_layout %> </body> </html>
  26. 26. Scriptlets <% @usuarios.each do |usuario| %> Faz alguma coisa com usuario <% end %> ... <% if number == quot;7quot; %> Está correto! <% end %>
  27. 27. Flash • flash[:notice] está disponível somente naquela requisição. Usado para comunicação entre ações: passagem de string contendo informação ou erro. • Similar a variáveis de sessão, mas somente existe de uma página para outra. Uma vez que a requisição para a qual foram propagadas acaba, elas são automaticamente removidas do contexto de execução. def three flash[:notice] => quot;Helloquot; flash[:warning] => quot;Mewlquot; flash[:error] => quot;Erro!quot; render end
  28. 28. Logger • Nível de log configurado em: config/environment.rb: config.log_level = :debug • Mensagens escritas em um arquivo no diretório log. O arquivo de log usado depende do ambiente (environment) usado pela aplicação. Ex.: log/development.log logger.warn(quot;I don't think that's a good ideaquot; ) logger.info(quot;Dave's trying to do something badquot; ) logger.error(quot;Now he's gone and broken itquot; ) logger.fatal(quot;I give upquot; )
  29. 29. Paginação • Para todas as ações do Controller: class PersonController < ApplicationController model :person paginate :people, :order => 'last_name, first_name', :per_page => 20 # ... end
  30. 30. Paginação • Para uma única ação do Controller: def list @person_pages, @people = paginate :people, :order => 'last_name, first_name' end
  31. 31. Paginação • Condicional @upcoming_event_pages, @upcoming_events = paginate :upcoming_event, :conditions => quot;event LIKE '%quot;params['upcoming_event']['search'].to_squot;%'quot;, :order_by => quot;date DESCquot;, :per_page => 10
  32. 32. Paginação • Genérica def list @person_pages = Paginator.new self, Person.count, 10, params[:page] @people = Person.find :all, :order => 'last_name, first_name', :limit => @person_pages.items_per_page, :offset => @person_pages.current.offset end
  33. 33. Paginação • paginate(collection_id, options={}) – Retorna um paginator e uma coleção de instâncias de modelo Active Record para a página atual. • Opções: – :singular_name: the singular name to use, if it can‘t be inferred by singularizing the collection name – :class_name: the class name to use, if it can‘t be inferred by camelizing the singular name – :per_page: the maximum number of items to include in a single page. Defaults to 10 – :conditions: optional conditions passed to Model.find(:all, *params) and Model.count – :order: optional order parameter passed to Model.find(:all, *params) – :order_by: (deprecated, used :order) optional order parameter passed to Model.find(:all, *params) – :joins: optional joins parameter passed to Model.find(:all, *params) and Model.count – :join: (deprecated, used :joins or :include) optional join parameter passed to Model.find(:all, *params) and Model.count – :include: optional eager loading parameter passed to Model.find(:all, *params) and Model.count – :select: :select parameter passed to Model.find(:all, *params) – :count: parameter passed as :select option to Model.count(*params)
  34. 34. Paginação • Em um array / collection: def paginate_collection(collection, options = {}) default_options = {:per_page => 10, :page => 1} options = default_options.merge options pages = Paginator.new self, collection.size, options[:per_page], options[:page] first = pages.current.offset last = [first + options[:per_page], collection.size].min slice = collection[first...last] return [pages, slice] end @pages, @users = paginate_collection User.find_custom_query, :page => @params[:page]
  35. 35. Convenção de Nomes
  36. 36. Fluxo do MVC
  37. 37. Parâmetros de Forms
  38. 38. Associações • Todo usuario pode ter vários telefones. • Telefone pertence a Usuario através da coluna usuario_id. • Convenção de Chave Estrangeira: <classe>_id class Usuario < ActiveRecord::Base has_many :telefones # um usuário tem muitos telefones validates_presence_of :nome validates_length_of :nome, :maximum => 75, :message => quot;Máximo de %d caracteres.quot; end class Telefone < ActiveRecord::Base belongs_to :usuario # um telefone pertence a um usuário end
  39. 39. Associações • Um para Um
  40. 40. Associações • Um para Muitos
  41. 41. Associações • Muitos para Muitos
  42. 42. Mapeamento de Tipos
  43. 43. Rake • Programa em Ruby para realizar um conjunto de tarefas (tasks). • Cada tarefa tem um nome, uma lista de tarefas das quais ela depende e uma lista de ações a realizar. • Para ver as tarefas existentes em um arquivo rake (Rakefile): rake --tasks
  44. 44. Testes Unitários • Toda nova entidade ganha um arquivo para teste unitário em: /app/test/unit/<entidade>_test.rb • Devemos seguir os preceitos de Test-Driven Development: “Se não vale a pena testar, para que estamos codificando?” • Os testes acontecem em banco de dados separado do desenvolvimento <projeto>_test • Cada teste roda de maneira isolada: os dados modificados em um teste não afetam outro teste • Cada teste unitário tem um arquivo de “fixture”, carga de dados para testes: /app/test/fixture/<tabela>.yml • Executando todos os testes unitários rake test:units • Executando apenas um teste unitário: ruby test/unit/<entidade>_test.rb
  45. 45. Testes Unitários require File.dirname(__FILE__) + '/../test_helper' class PostTest < Test::Unit::TestCase fixtures :posts # Replace this with your real tests. def test_add_comment # adiciona um post @post = Post.create(:title => 'New Post', :body => 'New Post', :author => 'Anonymous') # adiciona um comment @comment = @post.comments.create(:body => 'New Comment', :author => 'Anonymous') assert_not_equal nil, @comment # recarrega a entidade @post.reload # checa se existe apenas um post assert_equal 3, Post.count # já existem 2 posts na fixture # checa se esse post tem apenas um comment assert_equal 1, @post.comments.count end end
  46. 46. Fixture YAML • “YAML Ain’t a Markup Language” • Maneira de serializar objetos Ruby em forma de texto • Formato humanamente legível • Mais leve e simples que XML
  47. 47. Fixture YAML # Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html ronaldo: id: 1 name: Ronaldo login: ronaldo admin: true email: ronaldo@reflectivesurface.com data: 2004-07-01 00:00:00 hashed_password: <%= Digest::SHA1.hexdigest('abracadabra') %> marcus: id: 2 name: Marcus login: marcus admin: false email: marcus@reflectivesurface.com data: <%= 1.day.from_now.strftime(quot;%Y-%m-%dquot;) %> hashed_password: <%= Digest::SHA1.hexdigest('teste') %>
  48. 48. Fixture YAML
  49. 49. Fixture YAML
  50. 50. Testes Unitários
  51. 51. Testes Unitários
  52. 52. Testes Unitários
  53. 53. Testes Funcionais • Todo novo controller ganha uma classe de teste em: /app/test/functional/<classe>_controller_test.rb • Devemos testar cada action do controller • Métodos como get e post simulam navegação com um browser • Executando todos os testes funcionais: rake test:functionals • Executando apenas um testes funcional: ruby test/functional/<classe>_controller_test.rb
  54. 54. Testes Funcionais require File.dirname(__FILE__) + '/../test_helper' require 'blog_controller' # Re-raise errors caught by the controller. class BlogController; def rescue_action(e) raise e end; end class BlogControllerTest < Test::Unit::TestCase fixtures :posts def setup @controller = BlogController.new @request = ActionController::TestRequest.new @response = ActionController::TestResponse.new end def test_create num_posts = Post.count # checa total de posts atual # simula submit do formulário de criar novo post post :create, :post => {:title => 'New Title', :body => 'New Post', :author => 'Anonymous'} # checa se depois da action fomos redirecionados assert_response :redirect # checa se realmente foi acrescentado um novo post assert_equal num_posts + 1, Post.count end end
  55. 55. Testes Funcionais require File.dirname(__FILE__) + '/../test_helper' require 'users_controller' # Re-raise errors caught by the controller. class UsersController; def rescue_action(e) raise e end; end class UsersControllerTest < Test::Unit::TestCase fixtures :users def setup @controller = UsersController.new @request = ActionController::TestRequest.new @response = ActionController::TestResponse.new end def test_index get :index assert_redirected_to :controller => quot;loginquot;, :action => quot;loginquot; end def test_index_with_login @request.session[:user] = users(:ronaldo).id get :index assert_response :success assert_tag :tag => quot;tablequot;, :children => { :count => User.count + 1, :only => { :tag => quot;trquot; } } assert_tag :tag => quot;tdquot;, :content => users(:ronaldo).name end end
  56. 56. Testes Funcionais
  57. 57. Testes Funcionais
  58. 58. Testes de Integração • Para gerar o teste: script/generate integration_test login • Para executar o teste: rake test:integration
  59. 59. Testes de Integração require quot;#{File.dirname(__FILE__)}/../test_helperquot; class LoginTest < ActionController::IntegrationTest fixtures :users def test_login user = users(:ronaldo) get quot;/homequot; assert_redirected_to quot;/login/loginquot; follow_redirect! assert_response :success post quot;/login/loginquot; assert_response :success assert_equal quot;Invalid login and/or password.quot;, flash[:notice] post quot;/login/loginquot;, :login => user.login, :password => user.password assert_redirected_to quot;/homequot; follow_redirect! assert_tag :tag => quot;divquot;, :attributes => { :id => quot;edit_formquot; } end end
  60. 60. Teste de Performance
  61. 61. Mais Testes • Testes Unitários devem testar todos os aspectos da entidade como associações, validações, callbacks, etc • Testes Funcionais devem testar todas as actions de um mesmo controller, todos os fluxos, redirecionamentos, filtros, etc • Testes Integrados servem para avaliar a navegação e fluxos entre actions de diferentes controllers. Funcionam de maneira semelhante a um teste funcional
  62. 62. Helpers # Global helper para views. module ApplicationHelper # Formata um float com duas casa decimais def fmt_decimal(valor, decimais) sprintf(quot;%0.#{decimais}fquot; valor) , end end
  63. 63. O que NÃO fizemos • Não precisamos recompilar e reinstalar o aplicativo a cada mudança. • Não precisamos reiniciar o servidor a cada mudança. • Não precisamos mapear cada uma das colunas das tabelas para as entidades. • Não precisamos configurar dezenas de arquivos XML. Basicamente colocamos a senha do banco de dados, apenas. • Não precisamos usar Javascript para fazer Ajax: a maior parte pode ser feita com Ruby puro. • Não sentimos falta de taglibs: expressões Ruby, partials foram simples o suficiente. • Não precisamos codificar código-cola, o framework possui “padrões espertos” afinal, todo aplicativo Web tem a mesma infraestrutura.
  64. 64. Referências • Agile Web Development with Rails. 2ª Edição. – Thomas e David Heinemeier Hansson. • Entendendo Rails – Fábio Akita (http://www.esnips.com/web/BalanceOnRails) • Creating a weblog in 15 minutes – http://media.rubyonrails.org/video/rails_take2_with_sound.mov • Tutorial de Rails do TaQ – http://www.eustaquiorangel.com/downloads/tutorialrails.pdf • Tutorial de Ruby on Rails do Ronaldo Ferraz – http://kb.reflectivesurface.com/br/tutoriais/rubyOnRails • Rolling with Ruby on Rails by Curt Hibbs – http://www.onlamp.com/pub/a/onlamp/2005/01/20/rails.html • Tutorial de Ruby do TaQ – http://www.eustaquiorangel.com/downloads/tutorialruby.pdf

×