Rails for Dummies
-
date post
12-Sep-2014 -
Category
Technology
-
view
1.826 -
download
0
description
Transcript of Rails for Dummies
Rails for DummiesReinaldo Junior
sábado, 1 de outubro de 11
Reinaldo Junior
• UFES (since 2004)
• Desenvolvimento Web
• phpBB
• Eventos, comunidade, panelinha
sábado, 1 de outubro de 11
Plano de Vôo
• Framework
• Filosofia
• Ruby
• Rails
sábado, 1 de outubro de 11
Rails é um Framework
• “Abstração” (a resposta padrão de qualquer pergunta na computação)
• REUSO
sábado, 1 de outubro de 11
Frameworks
• Frameworks = (components + patterns)Ralph E. Johnson, 1997 (GoF)
• Contexto
• Específico de um Domínio
sábado, 1 de outubro de 11
WIN
• Vocabulário compartilhado
• Restrições inteligentes
• Foco na aplicação (e não no COMO)
sábado, 1 de outubro de 11
RUBY on Rails
• Ruby é a linguagem
• Foco no programador
• Sintaxe elegante e natural
• Extensibilidade
puts "maiusculo".upcase puts -5.abs 5.times do puts "Ruby é Massa!"end
sábado, 1 de outubro de 11
O.o
• Tudo é um objeto
• Classes (begin ... end)
• Métodos (def ... end)
class Pato def quack "Quack!" endend
# Donald Duckdonald = Pato.newdonald.quack#retorna "Quack!"
sábado, 1 de outubro de 11
_Oooo_
class Pato @@asas = 2
def initialize(asas=nil) @asas = [asas.to_i, @@asas].min end
def to_s "Asas: #{@asas}/#{@@asas}" endend
puts Pato.new(2)# Retorna "Asas: 2/2"
puts Pato.new# Retorna "Asas: 0/2"
puts Pato.new(10)# Retorna "Asas: 2/2"
puts Pato.new.quack# Retorna "Quack!"
sábado, 1 de outubro de 11
Mixin
module Mortal def machucado? @asas < @@asas end
def morto? @asas.to_i.zero? end
def machuca @asas = @asas - 1 unless morto? endend
class Pato include Mortalend
class Ganso < Pato # Err...end
class Ganso include Mortal
def quack "Ãhhn, Âhhn!" endend
sábado, 1 de outubro de 11
Duck-typing
def faz_quack_quack(patos) patos.each do |pato| if pato.respond_to? :quack puts pato.quack end endend
coisas = [Pato.new, Ganso.new, Pessoa.new]faz_quack_quack(coisas)
sábado, 1 de outubro de 11
Blocos
people.each do |person| puts "* #{person.name}"end 5.times { puts "Ruby rocks!"} [2,1,3].sort! { |a, b| b <=> a}
(0..10).each{ |i| puts i }
def em_par yield yieldend
em_par { "Tentativa #{i}"}
sábado, 1 de outubro de 11
Enumeráveis
# Array[1, 5, true, "Reinaldo", nil]
# Hashevento = { 'nome' => 'RockAndRails', 'ano' => 2011 }
reinaldo = { :nome => 'Reinaldo', :cidade => 'Vila Velha', :idade => 25}
0..10 # Range
:reinaldo # Simbolo
evento['ano']# 2011
reinaldo[:nome]# ‘Reinaldo’
reinaldo[:dindin]# nil
sábado, 1 de outubro de 11
Ruby Way
def caminho(options={}) default = { :origem => 'Vitória', :destino => 'Vila Velha' } opt = default.merge(options)
"#{opt[:origem]} --> #{opt[:destino]}"end
caminho()caminho(:origem => 'Campos')caminho(:destino => 'São Paulo')caminho :destino => 'Macaé', :origem => 'Manaus'
sábado, 1 de outubro de 11
Ruby on Rails
• DRY - Don’t Repeat Yourself
• COC - Convention Over Configuration
• Preguiça Virtuosa (aka Automatização)
• MVC, REST
• Comunidade
sábado, 1 de outubro de 11
Instalando
• Windows
• http://railsinstaller.org/
• Linux
• apt-get install ruby irb rubygems
• gem update --system
• gem install rails
• Mac (já vem instalado)
sábado, 1 de outubro de 11
Criando uma Aplicação
• Estrutura de arquivos definida
~ $ rails new dummy[...]
~ $ cd dummy
~/dummy $
~/dummy $ ls
Gemfile app db log testREADME config doc public tmpRakefile config.rulib script vendor
sábado, 1 de outubro de 11
Iniciando a App
~/dummy $ rails serverCould not find gem 'sqlite3 (>= 0) ruby' in any of the gem sources listed in your Gemfile.Run `bundle install` to install missing gems.
~/dummy $ bundle installFetching source index for http://rubygems.org/[...]Your bundle is complete! Use `bundle show [gemname]` to see where a bundled gem is installed.
sábado, 1 de outubro de 11
Executando o Web Server
~/dummy $ rails server=> Booting WEBrick=> Rails 3.0.10 application starting in development on http://0.0.0.0:3000=> Call with -d to detach=> Ctrl-C to shutdown server
~/dummy $ rails server -d~/dummy $ tail -f log/development.log
sábado, 1 de outubro de 11
It Just Works™
sábado, 1 de outubro de 11
Gerando o primeiro código
~/dummy $ rails generate scaffold Post title:string body:text rating:decimal viewed:integer
~/dummy $ rails generate model [...]~/dummy $ rails generate migration [...]~/dummy $ rails generate controller [...]
~/dummy $ rails destroy
~/dummy $ rails [comando] --help
sábado, 1 de outubro de 11
“Teste de Integração”
sábado, 1 de outubro de 11
“Teste Unitário”
~/dummy $ rails consoleLoading development environment (Rails 3.0.10):001 > Post => Post(Table doesn't exist)
:002 > Post.allActiveRecord::StatementInvalid: SQLite3::SQLException: no such table: posts: SELECT "posts".* FROM "posts" from [...]
sábado, 1 de outubro de 11
Mais preguiça
~/dummy $ rake db:create[...]
~/dummy $ rake db:migrate== CreatePosts: migrating ==========================-- create_table(:posts) -> 0.0019s== CreatePosts: migrated (0.0020s) =================
sábado, 1 de outubro de 11
Di Grátis
sábado, 1 de outubro de 11
sábado, 1 de outubro de 11
Rails e MVC
Agile Web Development With Rails, 3rd Ed.
sábado, 1 de outubro de 11
Componentes
Agile Web Development With Rails, 3rd Ed.
sábado, 1 de outubro de 11
Arquitetura
sábado, 1 de outubro de 11
Model
• Mantém o estado da aplicação (persistente ou não)
• Regras de negócio que se aplicam ao estado
sábado, 1 de outubro de 11
ActiveRecord = ORM
• OO <=> DB relacional
• tabelas <=> classes
• registros <=> objetos
• colunas <=> propriedades
• Tudo isso SEM SQL
• 90% da sua aplicação
sábado, 1 de outubro de 11
Migrations# db/migrate/20110930150650_create_posts.rbclass CreatePosts < ActiveRecord::Migration def self.up create_table :posts do |t| t.string :title t.text :body t.decimal :rating t.integer :viewed
t.timestamps # created_at e updated_at end end
def self.down drop_table :posts endend
sábado, 1 de outubro de 11
title body viewed
Rock And Rails
Bla bla bla... 3
Inscrições abertas
Etc e tal 2
# app/models/post.rbclass Post < ActiveRecord::Base # Sim, só issoend
novo = Post.new :title => 'O evento começou'post = Post.find(3)Post.destroy(2)
posts
• Tabela no plural
• Classe no singular
• app/models/<classe>.rb
sábado, 1 de outubro de 11
novo = Post.new( :title => 'O evento começou', :body => '...')novo.save
post = Post.find(3)post[:title]post.viewed
post.body = 'Atualizações'post.save
Post.allPost.find_by_title('Rock and Rails')Post.find_all_viewed(3)
Post.where('viewed >= ?', 50).order('title ASC')
sábado, 1 de outubro de 11
Validação
• LT do Uriel (guenta aí)
sábado, 1 de outubro de 11
Associações
~/dummy $ rails generate scaffold User name:string email:string
~/dummy $ rails generate scaffold Comment body:text viewed:integer user:references post:references
class Comment < ActiveRecord::Base belongs_to :user belongs_to :postend
class User < ActiveRecord::Base has_many :comments # fui euend
sábado, 1 de outubro de 11
comentario = Comment.firstcomentario.post # objetocomentario.user_id # id
meus_comentarios = Comment.find_all_by_user_id(3)
eu = User.find_by_name('Reinaldo')eu.comments # [objeto, objeto, ...]eu.comment_ids # [id, id, ...]eu.comments.find(3)eu.comments.where('viewed >=', 50)
~/dummy $ rake db:migrate
sábado, 1 de outubro de 11
eu = User.find_by_name('Reinaldo')
novo = eu.comments.create(:body => 'Massa!')popular = eu.comments.order('viewed DESC').limit(1)
outro = Comment.new(:body => 'Rox!')outro.user = User.find_or_create_by_name_and_email( 'M3nd3s', '[email protected]')outro.save
sábado, 1 de outubro de 11
Many-to-Many
~/dummy $ rails generate model Authorship post:references user:references order:integer
class Post < ActiveRecord::Base has_many :comments has_many :authorships has_many :users, :through => :authorshipsend
class Authorship < ActiveRecord::Base belongs_to :post belongs_to :userend
sábado, 1 de outubro de 11
post = Post.new( :title => 'Give me Fuel!')post.users << User.firstpost.save
post.authorships
post.authorships << Authorship.create( :user => User.find(3), :order => 1)
sábado, 1 de outubro de 11
class Post < ActiveRecord::Base has_many :comments has_many :authorships
has_many :authors, :through => :authorships, :source => :user
has_many :commenters, :through => :comments, :source => :userend
post = Post.firstreinaldo = User.first
post.authors << reinaldopost.authorships
comment = Comment.new( :body => 'Yeah', :user => User.find(2))post.comments << comment
post.savepost.reloadreinaldo.reload
post.commentersreinaldo.posts
class User < ActiveRecord::Base has_many :comments has_many :authorships has_many :posts, :through => :authorshipsend
sábado, 1 de outubro de 11
Rotas
• Avaliam as requisições e encaminham para um Controller + Action
• Criam métodos (helpers) que geram URLs
• Requisição HTTP: caminho (URI) e método HTTP (GET, POST, PUT, DELETE)
sábado, 1 de outubro de 11
Fluxo
• http://localhost:3000/say/hello
• Cliente => Servidor => Web Server
• Rota => Controller => Action => View
• Servidor => Cliente
sábado, 1 de outubro de 11
Configurando as rotas
# config/routes.rbDummy::Application.routes.draw do
# Suas rotas aqui get '/say/hello/', :controller => 'say', :action => 'hello'
get '/say/goodbye' => 'say#goodbye'
post '/say/hey-ya' => 'say#hello'end
sábado, 1 de outubro de 11
~/dummy $ rake routes
say_hello GET /say/hello(.:format) {:controller=>"say", :action=>"hello"}
say_goodbye GET /say/goodbye(.:format) {:controller=>"say", :action=>"goodbye"}
POST /say/hey-ya(.:format) {:controller=>"say", :action=>"hello"}
sábado, 1 de outubro de 11
Métodos
say_hello_path()say_hello_url()
say_goodbye_pathsay_goodbye_url
link_to("Diz olá pra mim!", say_hello_path())link_to "Tchau!", say_goodbye_url
sábado, 1 de outubro de 11
REST
• REST (Representational State Trasfer)
• Roy Fielding (Tese de Ph.D. ), cara do HTTP
• Princípios
• Protocolo sem estado
• Recursos, identificados universalmente (URI)
• Operações bem definidas que se aplicam a todos os recursos
• Múltiplas representações do mesmo recurso
sábado, 1 de outubro de 11
Recursos
resources :postsresources :commentsresources :users
link_to("Listar posts", posts_path())link_to "Veja os posts", posts_pathlink_to "Leia esse post", show_post_url(@post)link_to "Leia esse post", @post
Método Path Action
GET /posts index
GET /posts/new new
POST /posts create
GET /posts/:id show
GET /posts/:id/new edit
PUT /posts/:id update
DELETE /posts/:id destroy
sábado, 1 de outubro de 11
Controllers
• Subclasse de ActionController::Base
• Convenção
• app/controllers/<nome>_controller.rb
• class <Nome>Controller
• Se for um controller de recursos, nome é no plural
sábado, 1 de outubro de 11
Actions
• Métodos do públicos do Controller
• Renderiza Views para gerar a resposta
• Disponibiliza variáveis de instância pra View
• Acesso aos parâmetros pelo hash “params”
• Convenção
• renderiza uma view com o mesmo nome
sábado, 1 de outubro de 11
# app/controllers/say_controller.rbclass SayController < ApplicationController before_filter :get_time
def hello @message = params[:message] || 'Olá amigo!' end
def goodbye @message = params[:message] || 'Até mais, colega!' end protected def get_time @time = Time.now endend
sábado, 1 de outubro de 11
Feels like ASP/PHP
<!-- app/views/say/goodbye.html.erb --><p> <strong><%= @message %></strong><br /> Você está saindo às <em><%= @time %></em>.</p>
<!-- app/views/say/hello.html.erb --><p> <strong><%= @message %></strong><br /> Você chegou às <em><%= @time %></em>.</p>
sábado, 1 de outubro de 11
redirect_to, render# app/controllers/posts_controller.rbclass PostsController < ApplicationController
# POST /posts def create @post = Post.new(params[:post])
if @post.save redirect_to(@post, :notice => 'Post criado com sucesso.') else render :action => "new" end end
end
sábado, 1 de outubro de 11
Views
• Handlers
• ERB, RJS, Builder, RHTML, RXML
• Formats
• html, xml, json, js
• Convenção
• app/views/<controller>/
• <view>.<formato>.<handler>
sábado, 1 de outubro de 11
Rendering
# app/controllers/posts_controller.rbclass PostsController < ApplicationController
def index @posts = Post.all end
end
sábado, 1 de outubro de 11
<!-- app/views/posts/index.html.erb --><h1>Nossos Posts</h1>
<% @posts.each do |post| %> <h2><%= post.title %></h2> <div class="rating"><%= post.rating %></div> <%= link_to 'Leia na íntegra', post %><% end %>
sábado, 1 de outubro de 11
Partials
<!-- app/views/posts/_post.html.erb --><h2><%= post.title %></h2><div class="rating"><%= post.rating %></div><%= link_to 'Leia na íntegra', post %>
<!-- app/views/posts/index.html.erb --><h1>Post em nosso site</h1><%= render @posts %>
sábado, 1 de outubro de 11
Helpers
<%= image_tag('rails.png') %><img alt="Rails" src="/images/rails.png" />
<%= stylesheet_link_tag('application') %><link href="/stylesheets/application.css" media="screen" rel="stylesheet" type="text/css" />
<%= javascript_include_tag('mapa') %><script type="text/javascript" src="/javascripts/mapa.js"></script>
<% time_ago_in_words(post.created_at)%><!-- 3 minutos atrás -->
sábado, 1 de outubro de 11
Form Helpers
<%= form_for(@post) do |f| %> <div class="field"> <%= f.label :title %><br /> <%= f.text_field :title %> </div> <div class="field"> <%= f.label :body %><br /> <%= f.text_area :body %> </div> <div class="actions"> <%= f.submit %> </div><% end %>
sábado, 1 de outubro de 11
ActiveSupport
1.ordinalize # 1st100.ordinalize # 100th1.gigabyte / 512.kilobytes# 2048
"author_id".humanize# Author id
"post".pluralize# posts
"primeiro evento".titleize# Primeiro Evento
1.month.from_now3.days.ago10.minutes.from_now
Time.now + 2.hoursdate.at_beginning_of_week
sábado, 1 de outubro de 11
Perguntas?
• Rails Escala?Saying “Rails doesn’t scale” is like saying “my car doesn’t go infinitely fast”- Pushion Passenger Team
• Posso usar XYZ com Rails? SIM
• Rails é melhor que XYZ? SIM e NÃO
• Rails é bom apenas pra CRUD? NÃO e SIM
• Qual o salário de programador Rails? ...
• Como faço XYZ com Rails? Google!
sábado, 1 de outubro de 11
http://reinaldojunior.net :: @ReinaldoJunior
sábado, 1 de outubro de 11
Créditos das Imagens
• http://vvn.net/wp/2008/09/18/ruby-on-rails-architecture/
• Agile Web Development With Rails, 3rd Ed.
• yUML.me
sábado, 1 de outubro de 11