Hoje vou voltar um pouco para o scaffold de post que fiz, vou implementar coisas novas lá, deixar ele com uma "cara" melhor. O que já foi feito:
- Scaffold de Post feito com a gem Simple Form.
- Um Controller Home que vai simular uma página do site.
- Implementação básica do Devise.
- Gravatar.
O projeto está aqui(github.com/vagnerzampieri/zblog).
Primeiro vamos definir visualmente o que seria a capa do site da administração do site, o scaffold post simula o começo de uma administração, então ele precisa ter um layout modificado. Então vamos criar um layout específico para ele.
Entre 'app/views/layouts/' e crie um arquivo chamado 'admin.html.erb', e copie o código abaixo:
<!DOCTYPE html>
<html>
<head>
<title>Blog</title>
<%= stylesheet_link_tag :all %>
<%= javascript_include_tag :defaults %>
<%= csrf_meta_tag %>
</head>
<body>
<container>
<p class="notice"><%= notice %></p>
<p class="alert"><%= alert %></p>
<%= yield %>
</div>
</container>
</html>
Se já teve algum contato com HTML5 vai notar que é um layout do mesmo, o scaffold do rails já faz isso, o que tem de diferente que eu coloquei foi a tag "<container>". No 'app/views/layouts/application.html.erb' coloque esse mesmo HTMl, mas substitua o "<content>". Se você estiver se perguntando o que é "<%= yield %>" é aonde todas as telas que você criar irá entrar. Agora vamos diferenciar o layout no CSS.
Em 'public/stylesheets/scaffold.css, ajuste a primeira linha para isso:
body { background-color: #000; color: #000; }
Depois adicione isto:
th, tr, td {
border: solid 1px black;
}
container, content {
display:block;
}
container {
width: 75%;
margin: 0 auto;
background-color: #ccc;
padding: 20px 40px;
border: solid 1px black;
margin-top: 20px;
}
content {
width: 75%;
margin: 0 auto;
background-color: #493233;
padding: 20px 40px;
border: solid 1px black;
margin-top: 20px;
}
Agora no controller de 'app/controllers/posts_controller.rb', adicione na primeira linha depois que entrar dentro da classe:
layout 'admin'
Ele vai definir o layout que a página vai usar, o padrão é "application" mas eu quero o admin para "posts", então vá olhar como ficou a "home" e "posts". Eu não sou designer e uso layout escuro para não incomodar minha vista.
Se não existir conteúdo em posts, adicione alguns, depois veja como ele está listando. Entre no código da view em "app/views/posts/index.html.erb" e no controller 'app/controllers/posts_controller.rb'. O que vou fazer agora é explicar código, otimizar e trazer para a realidade de Rails3.
No método "index" faremos algumas modificações, esse método gera uma saída para a view "index.html.erb":
def index
@posts = Post.all
respond_to do |format|
format.html
format.xml { render :xml => @posts }
end
end
No Ruby a última linha de um método, ou um bloco é seu retorno, o método respond_to é um bloco que gera duas saídas, uma em html e a outra em xml. O método "index" gera uma lista de todos os posts, essa lista é pega de sua tabela "posts", ela é acessada através da consulta "Post.all", que será atribuída para uma variável chamada "@posts", que é uma variável de instância, ela irá trazer em forma de array todos os posts. O "Post" é o model relativo a tabela posts. Vamos deixar esse código com uma cara de Rails3.
Primeiro, no controller adicione a linha abaixo, logo depois de "layout 'admin'":
respond_to :html, :xml, :js
Depois modifique nosso método index para:
def index
@posts = Post.order "publication DESC"
respond_with @posts
end
Esse novo "respond_to" vai gerar os mesmos formatos que antes mais o formato "js"(javascript), será utilizado depois quando fizermos saídas com ajax, é só passar os parâmetros que quiser. Na primeira linha do método eu modifiquei para que retorne todos os posts em ordem decrescente por data. E o "respond_with" é meu complemento do método "respond_to", eu passo como parâmetro a variável de instância "@posts". Se estiver achando desconfortável a falta de parênteses quando chamo um método, é só adicionar, o espaço simples substitue os parênteses.
def index
@posts = Post.where(:enabled => 1)
respond_with(@posts)
end
Em 'app/views/posts/index.html.erb', note a nossa variável de instância "@posts", é passado um método "each" que irá acessar o array desta linha, e gerar a saída uma por uma de todos os conteúdos de dentro dele, através do seu bloco.
Se colocou em "body" texto suficiente, notou que ficou estranho o layout, vamos formatar isso usando o método "truncate".
<td><%= truncate post.body, :length => 20 %></td>
Estou passando como parâmetros, o campo "body" e um tamanho de caracteres. Vou formatar a data também:
<td><%= post.publication.strftime "%Y-%m-%d %H:%M:%S" %></td>
Nos métodos, "show", "new", "edit" e "destroy", faça a modificação do "respond_with".
Agora vamos otimizar o método create, por enquanto ele está assim:
def create
@post = Post.new params[:post]
respond_to do |format|
if @post.save
format.html { redirect_to(@post, :notice => 'Post was successfully created.') }
format.xml { render :xml => @post, :status => :created, :location => @post }
else
format.html { render :action => "new" }
format.xml { render :xml => @post.errors, :status => :unprocessable_entity }
end
end
end
Ele pega os dados vindos do parâmetro "params[:post]", que vem do formulário que está em "app/views/posts/_form.html.erb". Se os parâmetros estiverem certos, ele salva e avisa que foi criado com sucesso, senão ele se matem na página que está. Vamos otimizar esse código. Outra coisa que irão notar é que eu coloquei :new e não "new", simples explicação, da primeira forma eu crio um símbolo e da segunda é uma string. Usando símbolos, o consumo de memória pode ser drasticamente reduzido, uma vez que você estará usando o mesmo objeto, sem necessidade de crias várias cópias, quando estiver em um projeto grande essas pequenas diferenças fazem diferença no tempo total de processamento.
def create
@post = Post.new params[:post]
if @post.save
flash[:notice] = 'Post was successfully created.'
respond_with @post
else
render :action => :new
end
end
A ideia foi a mesma que já tinha usado, eu diminuo o código quando utilizo o "respond_with". Veja como vai ficar o "update".
def update
@post = Post.find params[:id]
if @post.update_attributes params[:post]
flash[:notice] = 'Post was successfully updated.'
respond_with @post
else
render :action => :edit
end
end
O método "update" pega o id do post em questão, armazena na variável @post, depois atualiza ele passando o parâmetro "params[:post]" que vem do formulário. Para você o "else" funcionar valide a presença dos campos "name" e "body", por exemplo. Faça em "app/models/post.rb"
validates_presence_of :title, :body
Para não deixar esse post grande vou encerrar aqui e falar sobre Rspec no próximo, iremos validar o modelo post.
Até a próxima!!
Nenhum comentário:
Postar um comentário