Upload
mauricio-linhares
View
2.693
Download
4
Embed Size (px)
DESCRIPTION
Material do curso de Ruby on Rails
Citation preview
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 „[email protected]“ } 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 [email protected]”;
} 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 “[email protected]" } 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
[email protected]: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 [email protected]: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)">×</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>