Aprendendo Ruby on Rails – Aula 2


                     Maurício Linhares
Começando a usar Git e GitHub
}    Crie uma conta no GitHub J

}    Na sua máquina, crie uma chave SSH:
      }    ssh-keygen -t rsa -C „seu@email.com“
      }    Não coloque senha, deixe em branco;

}    Vá até https://github.com/account e procure por “SSH
      public keys”;

}    Copie o arquivo “~/.ssh/id_rsa.pub” para o campo no
      GitHub;
Começando a usar Git e GitHub
}    Teste a conexão com “ssh git@github.com”;

}    Crie um repositório pra você com o nome “linuxfi-loja”;

}    Entre dentro da pasta do seu projeto na sua máquina e :
      }    git config --global user.name “Seu Nome“
      }    git config --global user.email “seu@email.com"
      }    git init .
Criando o arquivo .gitignore
}    Dentro da raiz do seu projeto, crie um arquivo chamado
      “.gitignore”;
      }    gedit .gitignore


}    O conteúdo do arquivo deve ser o seguinte:
      }    *.log
      }    *.pid
      }    .idea/*
Preparando para enviar os arquivos
}    Adicionando arquivos ao controle de versão:
      }    git add .
      }    “.” adiciona todos os arquivos, você também pode adicionar os
            arquivos um a um;


}    Aplicando as mudanças ao repoistório:
      }    git commit –m “Código inicial da loja”
      }    “commit” aplica as mudanças e salva todas as alterações
            aplicadas desde o último “commit”
Enviando as alterações para o servidor do
GitHub
}    Adicionando o servidor do GitHub como servidor
      remoto do seu código:
      }    git remote add origin
            git@github.com:usuario-do-github/linuxfi-loja.git


}    Enviando as alterações para o servidor remoto do
      GitHub
      }    git push origin master


}    Para baixar o projeto em outra máquina:
      }    git clone git@github.com:usuario-do-github/linuxfi-loja.git
Workflow do trabalho no GitHub
}    Desenvolva suas alterações;

}    Adicione os arquivos para alteração
      }    git add .

}    Salve as alterações no repositório local:
      }    git commit –m “mensagem”

}    Atualize o seu repositório local com as alterações do
      repositório remoto:
      }    git pull

}    Envie suas alterações para o servidor remoto:
      }    git push
Adicionando as mensagens em pt-BR ao
Rails
}    Configurar no “config/application.rb” para utilizar “pt-BR”
      como língua padrão:
      }    config.i18n.default_locale = :'pt-BR'


}    Baixar o arquivo de I18N de:
      }    http://github.com/svenfuchs/rails-i18n/blob/master/rails/locale/
            pt-BR.yml


}    Salvar o arquivo em “config/locales/pt-BR.yml”;
Preparando o carrinho de compras
}    Os produtos vão ser relacionar com pedidos;

}    Os pedidos não se relacionam diretamente com
      produtos, mas com uma tabela itens, que vai fazer a
      associação entre eles e adicionar atributos ao
      relacionamento, como quantidade;

}    Duas novas entidades surgem, Pedido e Item;
Gerando a migração para pedidos e itens

rails generate migration criar_pedidos_e_itens
Código da migration
def self.up
  create_table :pedidos do |t|
    t.string :estado, :default => 'carrinho', :null => false
    t.timestamps
  end
  create_table :itens do |t|
    t.integer :pedido_id, :null => false
    t.integer :produto_id, :null => false
    t.integer :quantidade
  end
  add_index :itens, :pedido_id
end

def self.down
  drop_table :pedidos
  drop_table :itens
end
Criando a classe Item
class Item < ActiveRecord::Base

 belongs_to :produto
 belongs_to :pedido

 validates_presence_of :produto_id, :pedido_id, :quantidade

end
Detalhes da classe item
}    Itens se associam com produtos e pedidos, a tabela
      “itens” guarda chaves estrangeiras para as duas outras
      tabelas, então o relacionamento é um “belongs_to” para
      cada uma delas;

}    O plural de “item” é “itens” e não “items” como seria no
      inglês, então é necessário configurar o inflector do Rails
      para agir segundo essa regra;
config/inflections.rb


ActiveSupport::Inflector.inflections do |inflect|
 inflect.irregular 'item', 'itens'
end
Criando a classe Pedido
class Pedido < ActiveRecord::Base

 has_many :itens
 has_many :produtos, :through => :items

end
Detalhes da classe Pedido
}    Cada pedido contém vários itens, então há um
      relacionamento “has_many” para a classe “Item”;

}    Com o relacionamento entre Pedido e Item, também é
      necessário saber exatamente quais são os produtos
      relacionados ao pedido, isso é feito através do
      relacionamento “has_many :through” entre as duas
      classes;

}    O “has_many :through” simplifica o acesso a objetos que
      sejam internos a um relacionamento já definido da classe
      em questão;
Adicionando a flash aos layouts
}    A flash é um espaço que existe entre as requisições para
      se guardar informações;

}    Normalmente é utilizada para mostrar mensagens para o
      usuário;

}    Os dados colocados na requisição atual, serão apagados
      ao fim da próxima requisição (depois do redirect);
Mas antes disso – Twitter Bootstrap!
}    Conjunto de folhas de estilo e JavaScript padrões
      desenvolvidos pelo Twitter;

}    Contém vários componentes visuais comuns e que
      podem ser utilizados em várias aplicações;

}    Facilita a estilização das suas páginas através de um CSS
      limpo e bem organizado;

}    http://twitter.github.com/bootstrap/
Adicione ele como dependência no seu
Gemfile
}    gem 'less-rails-bootstrap', '1.3.3’

}    Execute o bundler:
      }    bundle install


}    Adicione ele no seu app/assets/javascripts/application.js:
      }    //= require twitter/bootstrap


}    Adicione ele no seu app/assets/stylesheets/application.css:
      }    *= require twitter/bootstrap
Alterando o app/views/layout/
application.html.erb
<body>

  <div class="container">

   <% [:success, :warning, :error, :info].each do |key| %>
     <% unless flash[key].blank? %>
        <div class="alert-message <%= key %>">
          <a class="close" href="javascript:void(0)">&times;</a>
          <p><strong><%= flash[key] %></strong></p>
        </div>
     <% end %>
   <% end %>

   <%= yield %>
  </div>

</body>
Chamada para fechar o alerta – app/assets/
javascripts/main.js

jQuery( function () {

   jQuery(".alert-message").alert();

} );
Definindo método pedido_atual em
ApplicationController
helper_method :pedido_atual

protected

def pedido_atual
  if @pedido_atual.nil? && !session[:pedido_id].blank?
    @pedido_atual =
 Pedido.find_by_id( session[:pedido_id] )
  end
  @pedido_atual ||= Pedido.new
end
Adicionando itens ao pedido
}    O pedido atual fica guardado na sessão do usuário, o
      método que faz isso é o “pedido_atual” que vai ser
      definido em ApplicationController;

}    O método “pedido_atual” também precisa ficar disponível
      nas páginas da aplicação;

}    A chamada a “helper_method :pedido_atual” faz com que
      o método seja copiado para as visualizações também;
Implementando a adição de produtos em
Item
class Pedido < ActiveRecord::Base

 has_many :itens
 has_many :produtos, :through => :items

 def adicionar_produto(produto, quantidade)

  if item = self.itens.detect { |elemento| elemento.produto == produto }
    item.incrementar_quantidate(quantidade)
    item.save
  else
    self.itens.create(:produto => produto, :quantidade => quantidade)
  end

 end

end
Implementação do incrementar_quantidade
em Item

class Item < ActiveRecord::Base

 belongs_to :produto
 belongs_to :pedido

 validates_presence_of :produto_id, :pedido_id, :quantidade
 validates_numericality_of :quantidade, :greater_than => 0, :allow_nil => true

 def incrementar_quantidade(quantidade)
  self.quantidade += quantidade
 end

end
Implementação da adição de produto no
carrinho no ItensController
class ItensController < ApplicationController

 def create
  pedido_atual.save
  session[:pedido_id] = pedido_atual.id

  pedido_atual.adicionar_produto(Produto.find(params[:produto_id]), params[:quantidade])

  respond_to do |format|
   format.html do
     flash[:success] = 'O produto foi adicionado com sucesso a o seu carrinho'
     redirect_to produtos_path
   end
  end
 end

end
Adicionar rota para o ItensController



resources :itens
Montando o formulário para adição de
produtos ao carrinho

<%= form_tag itens_path, :html => { :method => :post }
 do %>
  <%= hidden_field_tag :produto_id, produto.id %>
  <p>
     <%= text_field_tag :quantidade, 1 %>
     <%= submit_tag 'Adicionar ao carrinho' %>
 </p>
<% end %>
Adicionando link para visualizar o carrinho
no application.html.erb
<div class="topbar-wrapper" style="z-index: 5;">
 <div class="topbar">
  <div class="topbar-inner">
    <div class="container">
     <h3> <%= link_to 'Minha Loja', root_url %> </h3>
     <% unless pedido_atual.itens.blank? %>
         <ul class="nav secondary-nav">
          <li>
           <%= link_to 'Veja o seu carrinho', itens_path %>
          </li>
         </ul>
     <% end %>
    </div>
  </div>
 </div>
</div>
Complementando a classe Item
class Item < ActiveRecord::Base

 # outros métodos aqui

 def preco_unitario
  self.produto.preco
 end

 def nome
  self.produto.nome
 end

 def preco_total
  self.produto.preco * self.quantidade
 end

end
Porque preco_unitario e nome
implementados em Item?
}    Referência a Lei de Demeter (deusa grega da Agricultura)
      ou o princípio do menor conhecimento;

}    Objetos devem falar somente com suas dependências
      diretas (variáveis de instância ou objetos recebidos como
      parâmetro);

}    Fazer com que um objeto dependa somente de outros
      objetos que estejam no mesmo “grupo” que ele;
Complementando a classe Pedido
class Pedido < ActiveRecord::Base

 # outros métodos

 def preco_total
  self.itens.inject( 0 ) do |acumulado, item|
   acumulado+ item.preco_total
  end
 end

end
Cabeçalho do carrinho de compras
<thead>
   <tr>
     <th>Produto</th>
     <th>Quantidade</th>
     <th>Preço Unitário</th>
     <th>Preço Total</th>
   </tr>
</thead>
Tabela principal do carrinho de compras
<table>
<tbody>
    <% pedido_atual.itens.each do |item| %>
     <tr>
       <td> <%= item.nome %> </td>
       <td> <%= item.quantidade %> </td>
       <td> <%= number_to_currency item.preco_unitario %></td>
       <td> <%= number_to_currency item.preco_total %> </td>
     </tr>
    <% end %>
 </tbody>
</table>
Rodapé do carrinho de compras
<tfoot>
   <tr>
     <td colspan="2"></td>
     <td> Preço Total </td>
     <td> <%= number_to_currency
 pedido_atual.preco_total %> </td>
   </tr>
  </tfoot>

Curso de Ruby on Rails - Aula 02

  • 1.
    Aprendendo Ruby onRails – Aula 2 Maurício Linhares
  • 2.
    Começando a usarGit e GitHub }  Crie uma conta no GitHub J }  Na sua máquina, crie uma chave SSH: }  ssh-keygen -t rsa -C „seu@email.com“ }  Não coloque senha, deixe em branco; }  Vá até https://github.com/account e procure por “SSH public keys”; }  Copie o arquivo “~/.ssh/id_rsa.pub” para o campo no GitHub;
  • 3.
    Começando a usarGit e GitHub }  Teste a conexão com “ssh git@github.com”; }  Crie um repositório pra você com o nome “linuxfi-loja”; }  Entre dentro da pasta do seu projeto na sua máquina e : }  git config --global user.name “Seu Nome“ }  git config --global user.email “seu@email.com" }  git init .
  • 4.
    Criando o arquivo.gitignore }  Dentro da raiz do seu projeto, crie um arquivo chamado “.gitignore”; }  gedit .gitignore }  O conteúdo do arquivo deve ser o seguinte: }  *.log }  *.pid }  .idea/*
  • 5.
    Preparando para enviaros arquivos }  Adicionando arquivos ao controle de versão: }  git add . }  “.” adiciona todos os arquivos, você também pode adicionar os arquivos um a um; }  Aplicando as mudanças ao repoistório: }  git commit –m “Código inicial da loja” }  “commit” aplica as mudanças e salva todas as alterações aplicadas desde o último “commit”
  • 6.
    Enviando as alteraçõespara o servidor do GitHub }  Adicionando o servidor do GitHub como servidor remoto do seu código: }  git remote add origin git@github.com:usuario-do-github/linuxfi-loja.git }  Enviando as alterações para o servidor remoto do GitHub }  git push origin master }  Para baixar o projeto em outra máquina: }  git clone git@github.com:usuario-do-github/linuxfi-loja.git
  • 7.
    Workflow do trabalhono GitHub }  Desenvolva suas alterações; }  Adicione os arquivos para alteração }  git add . }  Salve as alterações no repositório local: }  git commit –m “mensagem” }  Atualize o seu repositório local com as alterações do repositório remoto: }  git pull }  Envie suas alterações para o servidor remoto: }  git push
  • 8.
    Adicionando as mensagensem pt-BR ao Rails }  Configurar no “config/application.rb” para utilizar “pt-BR” como língua padrão: }  config.i18n.default_locale = :'pt-BR' }  Baixar o arquivo de I18N de: }  http://github.com/svenfuchs/rails-i18n/blob/master/rails/locale/ pt-BR.yml }  Salvar o arquivo em “config/locales/pt-BR.yml”;
  • 9.
    Preparando o carrinhode compras }  Os produtos vão ser relacionar com pedidos; }  Os pedidos não se relacionam diretamente com produtos, mas com uma tabela itens, que vai fazer a associação entre eles e adicionar atributos ao relacionamento, como quantidade; }  Duas novas entidades surgem, Pedido e Item;
  • 10.
    Gerando a migraçãopara pedidos e itens rails generate migration criar_pedidos_e_itens
  • 11.
    Código da migration defself.up create_table :pedidos do |t| t.string :estado, :default => 'carrinho', :null => false t.timestamps end create_table :itens do |t| t.integer :pedido_id, :null => false t.integer :produto_id, :null => false t.integer :quantidade end add_index :itens, :pedido_id end def self.down drop_table :pedidos drop_table :itens end
  • 12.
    Criando a classeItem class Item < ActiveRecord::Base belongs_to :produto belongs_to :pedido validates_presence_of :produto_id, :pedido_id, :quantidade end
  • 13.
    Detalhes da classeitem }  Itens se associam com produtos e pedidos, a tabela “itens” guarda chaves estrangeiras para as duas outras tabelas, então o relacionamento é um “belongs_to” para cada uma delas; }  O plural de “item” é “itens” e não “items” como seria no inglês, então é necessário configurar o inflector do Rails para agir segundo essa regra;
  • 14.
  • 15.
    Criando a classePedido class Pedido < ActiveRecord::Base has_many :itens has_many :produtos, :through => :items end
  • 16.
    Detalhes da classePedido }  Cada pedido contém vários itens, então há um relacionamento “has_many” para a classe “Item”; }  Com o relacionamento entre Pedido e Item, também é necessário saber exatamente quais são os produtos relacionados ao pedido, isso é feito através do relacionamento “has_many :through” entre as duas classes; }  O “has_many :through” simplifica o acesso a objetos que sejam internos a um relacionamento já definido da classe em questão;
  • 17.
    Adicionando a flashaos layouts }  A flash é um espaço que existe entre as requisições para se guardar informações; }  Normalmente é utilizada para mostrar mensagens para o usuário; }  Os dados colocados na requisição atual, serão apagados ao fim da próxima requisição (depois do redirect);
  • 18.
    Mas antes disso– Twitter Bootstrap! }  Conjunto de folhas de estilo e JavaScript padrões desenvolvidos pelo Twitter; }  Contém vários componentes visuais comuns e que podem ser utilizados em várias aplicações; }  Facilita a estilização das suas páginas através de um CSS limpo e bem organizado; }  http://twitter.github.com/bootstrap/
  • 19.
    Adicione ele comodependência no seu Gemfile }  gem 'less-rails-bootstrap', '1.3.3’ }  Execute o bundler: }  bundle install }  Adicione ele no seu app/assets/javascripts/application.js: }  //= require twitter/bootstrap }  Adicione ele no seu app/assets/stylesheets/application.css: }  *= require twitter/bootstrap
  • 20.
    Alterando o app/views/layout/ application.html.erb <body> <div class="container"> <% [:success, :warning, :error, :info].each do |key| %> <% unless flash[key].blank? %> <div class="alert-message <%= key %>"> <a class="close" href="javascript:void(0)">&times;</a> <p><strong><%= flash[key] %></strong></p> </div> <% end %> <% end %> <%= yield %> </div> </body>
  • 21.
    Chamada para fecharo alerta – app/assets/ javascripts/main.js jQuery( function () { jQuery(".alert-message").alert(); } );
  • 22.
    Definindo método pedido_atualem ApplicationController helper_method :pedido_atual protected def pedido_atual if @pedido_atual.nil? && !session[:pedido_id].blank? @pedido_atual = Pedido.find_by_id( session[:pedido_id] ) end @pedido_atual ||= Pedido.new end
  • 23.
    Adicionando itens aopedido }  O pedido atual fica guardado na sessão do usuário, o método que faz isso é o “pedido_atual” que vai ser definido em ApplicationController; }  O método “pedido_atual” também precisa ficar disponível nas páginas da aplicação; }  A chamada a “helper_method :pedido_atual” faz com que o método seja copiado para as visualizações também;
  • 24.
    Implementando a adiçãode produtos em Item class Pedido < ActiveRecord::Base has_many :itens has_many :produtos, :through => :items def adicionar_produto(produto, quantidade) if item = self.itens.detect { |elemento| elemento.produto == produto } item.incrementar_quantidate(quantidade) item.save else self.itens.create(:produto => produto, :quantidade => quantidade) end end end
  • 25.
    Implementação do incrementar_quantidade emItem class Item < ActiveRecord::Base belongs_to :produto belongs_to :pedido validates_presence_of :produto_id, :pedido_id, :quantidade validates_numericality_of :quantidade, :greater_than => 0, :allow_nil => true def incrementar_quantidade(quantidade) self.quantidade += quantidade end end
  • 26.
    Implementação da adiçãode produto no carrinho no ItensController class ItensController < ApplicationController def create pedido_atual.save session[:pedido_id] = pedido_atual.id pedido_atual.adicionar_produto(Produto.find(params[:produto_id]), params[:quantidade]) respond_to do |format| format.html do flash[:success] = 'O produto foi adicionado com sucesso a o seu carrinho' redirect_to produtos_path end end end end
  • 27.
    Adicionar rota parao ItensController resources :itens
  • 28.
    Montando o formuláriopara adição de produtos ao carrinho <%= form_tag itens_path, :html => { :method => :post } do %> <%= hidden_field_tag :produto_id, produto.id %> <p> <%= text_field_tag :quantidade, 1 %> <%= submit_tag 'Adicionar ao carrinho' %> </p> <% end %>
  • 29.
    Adicionando link paravisualizar o carrinho no application.html.erb <div class="topbar-wrapper" style="z-index: 5;"> <div class="topbar"> <div class="topbar-inner"> <div class="container"> <h3> <%= link_to 'Minha Loja', root_url %> </h3> <% unless pedido_atual.itens.blank? %> <ul class="nav secondary-nav"> <li> <%= link_to 'Veja o seu carrinho', itens_path %> </li> </ul> <% end %> </div> </div> </div> </div>
  • 30.
    Complementando a classeItem class Item < ActiveRecord::Base # outros métodos aqui def preco_unitario self.produto.preco end def nome self.produto.nome end def preco_total self.produto.preco * self.quantidade end end
  • 31.
    Porque preco_unitario enome implementados em Item? }  Referência a Lei de Demeter (deusa grega da Agricultura) ou o princípio do menor conhecimento; }  Objetos devem falar somente com suas dependências diretas (variáveis de instância ou objetos recebidos como parâmetro); }  Fazer com que um objeto dependa somente de outros objetos que estejam no mesmo “grupo” que ele;
  • 32.
    Complementando a classePedido class Pedido < ActiveRecord::Base # outros métodos def preco_total self.itens.inject( 0 ) do |acumulado, item| acumulado+ item.preco_total end end end
  • 33.
    Cabeçalho do carrinhode compras <thead> <tr> <th>Produto</th> <th>Quantidade</th> <th>Preço Unitário</th> <th>Preço Total</th> </tr> </thead>
  • 34.
    Tabela principal docarrinho de compras <table> <tbody> <% pedido_atual.itens.each do |item| %> <tr> <td> <%= item.nome %> </td> <td> <%= item.quantidade %> </td> <td> <%= number_to_currency item.preco_unitario %></td> <td> <%= number_to_currency item.preco_total %> </td> </tr> <% end %> </tbody> </table>
  • 35.
    Rodapé do carrinhode compras <tfoot> <tr> <td colspan="2"></td> <td> Preço Total </td> <td> <%= number_to_currency pedido_atual.preco_total %> </td> </tr> </tfoot>