sexta-feira, 20 de abril de 2012
Criando uma simples RESTful API usando Rails 3 e JSON
O exemplo de API utilizando JSON que vou fazer aqui é bem simples. Alguns podem se perguntar "Por que ele não faz com XML?", e eu respondo, você está no post errado, a busca certa no Sr. Google é "API XML Rails", ou algo parecido com isso. Criei esse post por que precisei fazer uns testes de criação de API, tanto para o meu trabalho, quanto para a faculdade, então compartilho minha experiência com vocês. As referências que utilizei para fazer o meu exemplo estão abaixo.
Utilizei JRuby e PostgreSQL para essa aplicação, coloque o banco e ruby que quiser, se não estiver usando JRuby não copie "jruby -S". Crie uma aplicação rails
jruby -S rails new zapi_blog -d postgresql
Verifique se o seu Gemfile está parecido com esse aqui:
source 'http://rubygems.org'
gem 'rails', '3.1.3'
# Bundle edge Rails instead:
# gem 'rails', :git => 'git://github.com/rails/rails.git'
gem 'activerecord-jdbcpostgresql-adapter'
gem 'jruby-openssl'
gem 'json'
gem 'pg'
gem 'execjs'
gem 'therubyrhino'
gem 'rack-cache', :require => 'rack/cache'
# Gems used only for assets and not required
# in production environments by default.
group :assets do
gem 'uglifier', '>= 1.0.3'
end
gem 'jquery-rails'
Crie um scaffold Post
jruby -s rails g scaffold Post title:string body:text
Crie e rode as migrações criadas no banco. Vamos ao controller para modificar algumas coisas, prefiro ele bem simplificado, mudo de lugar o "respond_to" que o rails gera e coloco de uma forma mais elegante utilizando "respond_with".
respond_to :html, :json
# GET /posts
# GET /posts.json
def index
@posts = Post.all
respond_with @posts
end
Inicie sua app e entre em "/posts.json" e abra uma outra aba com "/posts", elas contém o mesmo resultado, só que mostram de formas diferentes. O Rails facilita muito a vida de quem quer criar uma app, de uma forma bem simples é possível injetar os posts de fora da aplicação. Utilizando o "curl", pode ser feito um teste bem simples.
curl -d 'post[title]=Post1&post[body]=Post1' http://localhost:3000/posts.json
Nesse teste consigo injetar um post utilizando a URL do "/posts.json". Vou criar um script com ruby para criar os posts, o script irá pegar os dados de um banco de dados já criado e populado, através de JSON irá enviar os posts para a aplicação que está rodando no servidor local.
Criei os diretórios "rest_api/lib", coloquei dois aquivoes "api.rb" e "post.rb".
rest_api/lib/post.rb
class Post < ActiveRecord::Base
end
rest_api/lib/api.rb
require 'rubygems'
require 'active_record'
require 'json'
require 'net/http'
require 'uri'
ActiveRecord::Base.establish_connection(
:adapter => "postgresql",
:host => "localhost",
:username => "oquevoceusar",
:password => "suasenhaaquiounao",
:database => "umbancodedadosqualquer"
)
require 'post'
class Api
host = 'localhost:3000'
url = 'http://localhost:3000/posts.json'
uri = URI.parse(url)
post_ws = '/posts.json'
posts = Post.all
posts.each do |p|
post = {'title' => p.title, 'body' => p.body}.to_json
req = Net::HTTP::Post.new(post_ws, initheader = {'Content-Type' => 'application/json'})
req.body = post
response = Net::HTTP.new(uri.host, uri.port).start {|http| http.request(req)}
puts "Response #{response.code} #{response.message}: #{response.body}"
end
end
É possível também passar parametros de usuário e senha, entre outras coisas de segurança por esse script e fazer a verificação na app, mas isso é um outro post. Não vou explicar em detalhes o que esse script faz, se você está olhando esse post é por que já tem uma noção boa de ruby on rails, então vá tirar suas dúvidas na API do Ruby ou do Rails, o Sr. Google também ajuda.
Referências:
https://www.socialtext.net/open/very_simple_rest_in_ruby_part_3_post_to_create_a_new_workspace
http://gavinmorrice.com/blog/posts/21-building-a-rest-api-in-rails-3
http://squarism.com/2011/04/01/how-to-write-a-ruby-rails-3-rest-api/
http://blog.project-sierra.de/archives/1788
Você faz informática?
Quando fui deitar, sempre acabo pensando em algo para escrever, então pensei em umas conversas que ando tendo com amigos e colegas de área, decidi escrever algumas perguntas para reflexão própria e de quem quiser refletir junto. Quem tiver mais algumas mande que coloco no post. Estas perguntas não estão em ordem de importância.
Responda as seguintes perguntas:
Estuda frequentemente fora da faculdade, ou curso?
Participa de listas, fóruns, ou chats de assuntos relacionados a sua área?
Segue pessoas importantes da área no twitter?
Lê artigos, livros, ou posts especializados de pessoas relevantes?
Vai a eventos?
Procura atualizar-se com as novidades constantes que pipocam a todo momento?
Conhece o passado, presente e o possível futuro da informática?
Já está inserido no mercado de trabalho? só vale empregos da sua linha de estudos.
Se a maioria dessas perguntas são respondidas com um "NÃO", você está fazendo isso muito certo ... "só que não". Quando falo isso tenho a certeza ao afirmar que você faz informática por modinha e não por que realmente gosta do assunto, não importa agora a sua área de atuação, se não tem dedicação, você realmente não gosta do assunto. E depois não venha dizer que conhece a área, por que não tem embasamento nenhum para falar de informática.
Responda as seguintes perguntas:
Estuda frequentemente fora da faculdade, ou curso?
Participa de listas, fóruns, ou chats de assuntos relacionados a sua área?
Segue pessoas importantes da área no twitter?
Lê artigos, livros, ou posts especializados de pessoas relevantes?
Vai a eventos?
Procura atualizar-se com as novidades constantes que pipocam a todo momento?
Conhece o passado, presente e o possível futuro da informática?
Já está inserido no mercado de trabalho? só vale empregos da sua linha de estudos.
Se a maioria dessas perguntas são respondidas com um "NÃO", você está fazendo isso muito certo ... "só que não". Quando falo isso tenho a certeza ao afirmar que você faz informática por modinha e não por que realmente gosta do assunto, não importa agora a sua área de atuação, se não tem dedicação, você realmente não gosta do assunto. E depois não venha dizer que conhece a área, por que não tem embasamento nenhum para falar de informática.
sábado, 10 de dezembro de 2011
GRUB error 17
Estava formatando as minhas partições, utilizando o Live CD do Ubuntu 11.04 e o GParted, quando fui reiniciar a máquina me deparei com o chato erro do GRUB error 17, alguns de vocês já devem ter resolvido isso, mas como nunca tinha formatado partições fui atrás do erro, achei este link falando do assunto e consegui adaptar para minha realidade.
O erro acontece quando as partições não estão organizadas e o GRUB precisava ficar na partição do Linux, coisa que não acontecia, então fiz o seguinte:
Antes de começar, TENHA CUIDADO.
Entrei fazendo boot novamente pelo CD, abri o terminal. Virei root.
Listei as partições com:
fdisk -l
A minha saída foi:
No meu caso o GRUB precisa estar em /dev/sda5, sabendo disso montei minha partição com:
Depois que o GRUB descobriu meus drivers, faço o chroot
Assim que acabar essa parte, abra o grub:
Encontre quais os parâmetros que você deve passar no comando root com o find abaixo:
find /boot/grub/stage1
No meu caso a saída foi (hd0,4), passe ele no root:
Por fim rode o setup e feche:
Reinicie a máquina e estará pronto.
O erro acontece quando as partições não estão organizadas e o GRUB precisava ficar na partição do Linux, coisa que não acontecia, então fiz o seguinte:
Antes de começar, TENHA CUIDADO.
Entrei fazendo boot novamente pelo CD, abri o terminal. Virei root.
sudo -i
Listei as partições com:
fdisk -l
A minha saída foi:
Disk /dev/sda: 160.0 GB, 160041885696 bytes
255 heads, 63 sectors/track, 19457 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x4dc5fddf
255 heads, 63 sectors/track, 19457 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x4dc5fddf
Device Boot Start End Blocks Id System
/dev/sda1 1 10 80293+ de Dell Utility
/dev/sda2 * 11 1926 15383099 7 HPFS/NTFS
/dev/sda3 18184 19457 10233405 db CP/M / CTOS / ...
/dev/sda4 1926 18183 130590720 5 Extended
/dev/sda5 1926 17566 125628416 83 Linux
/dev/sda6 17566 18183 4960256 82 Linux swap / Solaris
Partition table entries are not in disk order
/dev/sda1 1 10 80293+ de Dell Utility
/dev/sda2 * 11 1926 15383099 7 HPFS/NTFS
/dev/sda3 18184 19457 10233405 db CP/M / CTOS / ...
/dev/sda4 1926 18183 130590720 5 Extended
/dev/sda5 1926 17566 125628416 83 Linux
/dev/sda6 17566 18183 4960256 82 Linux swap / Solaris
Partition table entries are not in disk order
No meu caso o GRUB precisa estar em /dev/sda5, sabendo disso montei minha partição com:
mount /dev/sad5 /mnt
mount -t proc none /mnt/proc
mount -o bind /dev /mnt/dev
mount -t proc none /mnt/proc
mount -o bind /dev /mnt/dev
Depois que o GRUB descobriu meus drivers, faço o chroot
chroot /mnt /bin/bash
Assim que acabar essa parte, abra o grub:
grub
Encontre quais os parâmetros que você deve passar no comando root com o find abaixo:
find /boot/grub/stage1
No meu caso a saída foi (hd0,4), passe ele no root:
root (hd0,4)
Por fim rode o setup e feche:
setup (hd0)
quit
quit
Reinicie a máquina e estará pronto.
domingo, 19 de junho de 2011
Devise x Authlogic
Aviso aos navegantes que essa é a minha opinião, aconteceu comigo e só estou passando minha experiência para outros devels como eu, então não me julguem, posso estar falando alguma merda, mas pelo que conversei com alguns colegas eles tem uma opinião parecida.
Devise é uma ferramenta FODA, mas tem que saber muito bem que tipo de projeto irá utiliza-la. Se for um projeto rápido que você não quer perder tempo nele, vai ser pequeno, é feijão com arroz, utilize o Devise por que já está pronto. Não perca tempo reinventando a roda ela está pronta, utilize.
Se o seu projeto tiver que ter uma personalização maior, por que o cliente pediu algo diferente, usa o Authlogic. Com o Devise poderá ter dor de cabeça dependendo do que o cliente pedir, fora que pode acontecer dele não fazer tudo que você espera, ou ele fazer demais. Considero que o Devise como muitas outras ferramentas foi feita com um propósito e ele foi atingido com sucesso, mas para a sua utilização ele tem que se encaixar no seu modelo de negócio, já que varia de empresa para empresa. Não quer dizer que você esteja fazendo errado, e sim está fazendo da forma que acredita ser a correta.
Estou dizendo isso por que tive dois projetos que erramos na escolha pelo Devise que fazia muito mais do que precisávamos, depois tivemos que retirar e colocar o Authlogic. Hoje temos uma gem feita com o sistema de Engines do Rails 3.10.beta que com uma linha no terminal instala tudo que precisamos e configura, ela é específica para os nossos interesses por isso a utilização do Devise foi descartada por completo, mas não quer dizer para você não possa utilizar. Planejamento é muito importante para não ter dor de cabeça em uma troca mais tarde. Nosso caso trocamos, sendo que tínhamos um projeto em produção então imagine o trabalho que foi, tivemos que mexer em migração, banco de dados, modelo, nossa da calafrio até de lembrar.
Ps.: Demorei pra postar algo por causa da famosa faculdade, já pensei em alguns posts maneiros para fazer.
Até a próxima!!
Devise é uma ferramenta FODA, mas tem que saber muito bem que tipo de projeto irá utiliza-la. Se for um projeto rápido que você não quer perder tempo nele, vai ser pequeno, é feijão com arroz, utilize o Devise por que já está pronto. Não perca tempo reinventando a roda ela está pronta, utilize.
Se o seu projeto tiver que ter uma personalização maior, por que o cliente pediu algo diferente, usa o Authlogic. Com o Devise poderá ter dor de cabeça dependendo do que o cliente pedir, fora que pode acontecer dele não fazer tudo que você espera, ou ele fazer demais. Considero que o Devise como muitas outras ferramentas foi feita com um propósito e ele foi atingido com sucesso, mas para a sua utilização ele tem que se encaixar no seu modelo de negócio, já que varia de empresa para empresa. Não quer dizer que você esteja fazendo errado, e sim está fazendo da forma que acredita ser a correta.
Estou dizendo isso por que tive dois projetos que erramos na escolha pelo Devise que fazia muito mais do que precisávamos, depois tivemos que retirar e colocar o Authlogic. Hoje temos uma gem feita com o sistema de Engines do Rails 3.10.beta que com uma linha no terminal instala tudo que precisamos e configura, ela é específica para os nossos interesses por isso a utilização do Devise foi descartada por completo, mas não quer dizer para você não possa utilizar. Planejamento é muito importante para não ter dor de cabeça em uma troca mais tarde. Nosso caso trocamos, sendo que tínhamos um projeto em produção então imagine o trabalho que foi, tivemos que mexer em migração, banco de dados, modelo, nossa da calafrio até de lembrar.
Ps.: Demorei pra postar algo por causa da famosa faculdade, já pensei em alguns posts maneiros para fazer.
Até a próxima!!
domingo, 22 de maio de 2011
Quando usar Beta?
Essa é uma perguntinha chata que deve ecoar na cabeça de muito desenvolvedor e gerente de projeto. Eu tenho uma pequena experiência com os dois lados, já desenvolvi com ferramentas estáveis e também com ferramentas betas.
Meu exemplo de ferramenta estável foi de outubro de 2009 até dezembro de 2010, com o Ruby 1.8.7 e o Rails 2.3.5, aonde trabalho. Fizemos coisas bem legais com essas ferramentas, porém no meio do processo vimos a chegada do Rails3, que em caso de atualizar para nova versão iria modificar muita coisa interna e não valeria apena. Fora que as ferramentas que usavamos estavam migrando rapidamente para a nova versão do Rails3 e assim estagnando nossa ferramenta. Basicamente esse é o mal de usar o estável, suas aplicações podem ficar com código defasado muito rápido pelas mudanças constantes das ferramentas que você geralmente utiliza.
Com ferramenta Beta uso desde dezembro de 2010, uso o Ruby estável 1.9.2, mas uso o Beta do Rails o 3.1.0.beta, usava já antes dele virar "--pre". A vantagem disso? Uso funcionalidades que a maioria das pessoas só vai usar em 6 mêses ou mais, modificações realmente necessárias como as Engines que foram colocadas à pouco tempo. Só que existe um preço, se tiver alguma dificuldade para fazer algo, não tem muita documentação existente, vai ter que saber procurar, em listas, foruns, posts que o pessoal do Core Team participa. Outra dificuldade é que outras Gems que seu projeto depende podem não ser compatíveis com o Framework, quer dizer que você vai ter que meter a mão para ajudar a desenvolver. Esses pequenos contratempos fazem que a conclusão do projeto aumente.
E agora? Quando usar Beta? Não sei, depende do propósito, de tempo, equipe, são muitas variáveis para pensar antes de fazer a escolha. O meu pensamento hoje em dia está mais da seguinte forma:
Se for uma ferramenta que me ajude, uso Beta, mais tempo para trabalhar já que provavelmente irá ter muita coisa para fazer. Tendo o cuidado certo não vai ficar ultrapassada.
Se for um site simples, uso estável, sem demora usando gems estáveis que irão me ajudar na conclusão rápida do projeto.
Basicamente o que vai fazer você usar estável ou Beta é o tempo que irá ter que fazer aquela tarefa e que grau de complexidade ele pode vir a ter.
Espero ter ajudado, até a próxima!!!
Meu exemplo de ferramenta estável foi de outubro de 2009 até dezembro de 2010, com o Ruby 1.8.7 e o Rails 2.3.5, aonde trabalho. Fizemos coisas bem legais com essas ferramentas, porém no meio do processo vimos a chegada do Rails3, que em caso de atualizar para nova versão iria modificar muita coisa interna e não valeria apena. Fora que as ferramentas que usavamos estavam migrando rapidamente para a nova versão do Rails3 e assim estagnando nossa ferramenta. Basicamente esse é o mal de usar o estável, suas aplicações podem ficar com código defasado muito rápido pelas mudanças constantes das ferramentas que você geralmente utiliza.
Com ferramenta Beta uso desde dezembro de 2010, uso o Ruby estável 1.9.2, mas uso o Beta do Rails o 3.1.0.beta, usava já antes dele virar "--pre". A vantagem disso? Uso funcionalidades que a maioria das pessoas só vai usar em 6 mêses ou mais, modificações realmente necessárias como as Engines que foram colocadas à pouco tempo. Só que existe um preço, se tiver alguma dificuldade para fazer algo, não tem muita documentação existente, vai ter que saber procurar, em listas, foruns, posts que o pessoal do Core Team participa. Outra dificuldade é que outras Gems que seu projeto depende podem não ser compatíveis com o Framework, quer dizer que você vai ter que meter a mão para ajudar a desenvolver. Esses pequenos contratempos fazem que a conclusão do projeto aumente.
E agora? Quando usar Beta? Não sei, depende do propósito, de tempo, equipe, são muitas variáveis para pensar antes de fazer a escolha. O meu pensamento hoje em dia está mais da seguinte forma:
Se for uma ferramenta que me ajude, uso Beta, mais tempo para trabalhar já que provavelmente irá ter muita coisa para fazer. Tendo o cuidado certo não vai ficar ultrapassada.
Se for um site simples, uso estável, sem demora usando gems estáveis que irão me ajudar na conclusão rápida do projeto.
Basicamente o que vai fazer você usar estável ou Beta é o tempo que irá ter que fazer aquela tarefa e que grau de complexidade ele pode vir a ter.
Espero ter ajudado, até a próxima!!!
quinta-feira, 28 de abril de 2011
Instalando Nginx e Unicorn no Rails 3
Nginx e Unicorn
O Nginx com o Unicorn é uma ótima solução para colocar seu projeto em produção. É bem fácil a instalação deles. Eu utilizo essa combinação na minha máquina para testar meus projetos que desenvolvo. Quer saber mais sobre o que os dois fazem ? Vai pesquisar no Google, eu vou mostrar só a implementação básica.
sudo apt-get install nginx
Para poder usar o Nginx e o Apache sem ter que desligar um deles é só mudar a porta padrão do Nginx. Abra o arquivo default do Nginx para mudar a porta.
sudo nano /etc/nginx/sites-available/default
Comente a linha:
#listen [::]:80 default ipv6only=on; ## listen for ipv6
Modifique a porta, eu coloco 8080:
listen 8080; ## listen for ipv4
Crie um arquivo nesta mesma página com um nome que identifique o site que está fazendo.
sudo nano sua_app
O meu arquivo está assim:
upstream app_server {
# fail_timeout=0 means we always retry an upstream even if it failed
# to return a good HTTP response (in case the Unicorn master nukes a
# single worker for timing out).
# for UNIX domain socket setups:
server unix:/tmp/.sock fail_timeout=0;
# for TCP setups, point these to your backend servers
# server 192.168.0.7:8080 fail_timeout=0;
# server 192.168.0.8:8080 fail_timeout=0;
# server 192.168.0.9:8080 fail_timeout=0;
}
server {
# enable one of the following if you're on Linux or FreeBSD
listen 8080 default deferred; # for Linux
# listen 80 default accept_filter=httpready; # for FreeBSD
client_max_body_size 4G;
server_name sua_app.local;
# ~2 seconds is often enough for most folks to parse HTML/CSS and
# retrieve needed images/icons/frames, connections are cheap in
# nginx so increasing this is generally safe...
keepalive_timeout 5;
# path for static files
root /home/seu_usuario/seu_caminho/sua_app/public;
# Prefer to serve static files directly from nginx to avoid unnecessary
# data copies from the application server.
#
# try_files directive appeared in in nginx 0.7.27 and has stabilized
# over time. Older versions of nginx (e.g. 0.6.x) requires
# "if (!-f $request_filename)" which was less efficient:
# http://bogomips.org/unicorn.git/tree/examples/nginx.conf?id=v3.3.1#n127
try_files $uri/index.html $uri.html $uri @app;
location @app {
# an HTTP header important enough to have its own Wikipedia entry:
# http://en.wikipedia.org/wiki/X-Forwarded-For
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# enable this if and only if you use HTTPS, this helps Rack
# set the proper protocol for doing redirects:
# proxy_set_header X-Forwarded-Proto https;
# pass the Host: header from the client right along so redirects
# can be set properly within the Rack application
proxy_set_header Host $http_host;
# we don't want nginx trying to do something clever with
# redirects, we set the Host: header above already.
proxy_redirect off;
# set "proxy_buffering off" *only* for Rainbows! when doing
# Comet/long-poll stuff. It's also safe to set if you're
# using only serving fast clients with Unicorn + nginx.
# Otherwise you _want_ nginx to buffer responses to slow
# clients, really.
# proxy_buffering off;
proxy_pass http://app_server;
}
# Rails error pages
error_page 500 502 503 504 /500.html;
location = /500.html {
root /home/seu_usuario/seu_caminho/sua_app/public;
}
}
Os pontos importantes desse arquivo são:
# para definir a porta.
listen 8080 default deferred;
# definição do host chamado do navegador.
server_name sua_app.local;
# caminho estático da sua app.
root /home/seu_usuario/seu_caminho/sua_app/public;
Crie um link simbólico em sites-enabled:
cd /etc/nginx/sites-enabled/
sudo ln -s /etc/nginx/sites-available/sua_app sua_app
Defina o nome da sua app no arquivo hosts:
sudo nano /etc/hosts
Dentro do arquivo:
127.0.0.1 sua_app.local
Start no nginx:
sudo /etc/init.d/nginx start
Teste o endereço com http://sua_app.local:8080/, vai dar uma mensagem. Vamos instalar o Unicorn. No arquivo Gemfile de sua app, adicione:
gem 'unicorn', '3.5.0'
Depois rode o 'bundle install' no terminal. Em 'config/' crie um arquivo 'unicorn.rb' e coloque o conteúdo abaixo conforme sua máquina:
# See http://unicorn.bogomips.org/Unicorn/Configurator.html for complete
# documentation.
worker_processes 2
# Help ensure your application will always spawn in the symlinked
# "current" directory that Capistrano sets up.
working_directory "/home/deployer/myapp.com/current"
# listen on both a Unix domain socket and a TCP port,
# we use a shorter backlog for quicker failover when busy
listen "/tmp/myapp.com.sock", :backlog => 64
listen 8080, :tcp_nopush => true
# nuke workers after 30 seconds instead of 60 seconds (the default)
timeout 30
# feel free to point this anywhere accessible on the filesystem
user 'deployer', 'staff'
shared_path = "/home/deployer/myapp.com/shared"
pid "#{shared_path}/pids/unicorn.pid"
stderr_path "#{shared_path}/log/unicorn.stderr.log"
stdout_path "#{shared_path}/log/unicorn.stdout.log"
Esse é o arquivo default dele encontrado aqui. Para colocar o unicorn em produção é só rodar essa linha no terminal dentro da sua app:
unicorn_rails -c config/unicorn.rb -E production -D
Para matar ele é só rodar:
kill -quit `cat tmp/pids/unicorn.pid`
É só isso, bem tranquilo é rápido, se tiver alguma dúvida comenta que eu ajudo no que puder.
Até a próxima!!
O Nginx com o Unicorn é uma ótima solução para colocar seu projeto em produção. É bem fácil a instalação deles. Eu utilizo essa combinação na minha máquina para testar meus projetos que desenvolvo. Quer saber mais sobre o que os dois fazem ? Vai pesquisar no Google, eu vou mostrar só a implementação básica.
sudo apt-get install nginx
Para poder usar o Nginx e o Apache sem ter que desligar um deles é só mudar a porta padrão do Nginx. Abra o arquivo default do Nginx para mudar a porta.
sudo nano /etc/nginx/sites-available/default
Comente a linha:
#listen [::]:80 default ipv6only=on; ## listen for ipv6
Modifique a porta, eu coloco 8080:
listen 8080; ## listen for ipv4
Crie um arquivo nesta mesma página com um nome que identifique o site que está fazendo.
sudo nano sua_app
O meu arquivo está assim:
upstream app_server {
# fail_timeout=0 means we always retry an upstream even if it failed
# to return a good HTTP response (in case the Unicorn master nukes a
# single worker for timing out).
# for UNIX domain socket setups:
server unix:/tmp/.sock fail_timeout=0;
# for TCP setups, point these to your backend servers
# server 192.168.0.7:8080 fail_timeout=0;
# server 192.168.0.8:8080 fail_timeout=0;
# server 192.168.0.9:8080 fail_timeout=0;
}
server {
# enable one of the following if you're on Linux or FreeBSD
listen 8080 default deferred; # for Linux
# listen 80 default accept_filter=httpready; # for FreeBSD
client_max_body_size 4G;
server_name sua_app.local;
# ~2 seconds is often enough for most folks to parse HTML/CSS and
# retrieve needed images/icons/frames, connections are cheap in
# nginx so increasing this is generally safe...
keepalive_timeout 5;
# path for static files
root /home/seu_usuario/seu_caminho/sua_app/public;
# Prefer to serve static files directly from nginx to avoid unnecessary
# data copies from the application server.
#
# try_files directive appeared in in nginx 0.7.27 and has stabilized
# over time. Older versions of nginx (e.g. 0.6.x) requires
# "if (!-f $request_filename)" which was less efficient:
# http://bogomips.org/unicorn.git/tree/examples/nginx.conf?id=v3.3.1#n127
try_files $uri/index.html $uri.html $uri @app;
location @app {
# an HTTP header important enough to have its own Wikipedia entry:
# http://en.wikipedia.org/wiki/X-Forwarded-For
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# enable this if and only if you use HTTPS, this helps Rack
# set the proper protocol for doing redirects:
# proxy_set_header X-Forwarded-Proto https;
# pass the Host: header from the client right along so redirects
# can be set properly within the Rack application
proxy_set_header Host $http_host;
# we don't want nginx trying to do something clever with
# redirects, we set the Host: header above already.
proxy_redirect off;
# set "proxy_buffering off" *only* for Rainbows! when doing
# Comet/long-poll stuff. It's also safe to set if you're
# using only serving fast clients with Unicorn + nginx.
# Otherwise you _want_ nginx to buffer responses to slow
# clients, really.
# proxy_buffering off;
proxy_pass http://app_server;
}
# Rails error pages
error_page 500 502 503 504 /500.html;
location = /500.html {
root /home/seu_usuario/seu_caminho/sua_app/public;
}
}
Os pontos importantes desse arquivo são:
# para definir a porta.
listen 8080 default deferred;
# definição do host chamado do navegador.
server_name sua_app.local;
# caminho estático da sua app.
root /home/seu_usuario/seu_caminho/sua_app/public;
Crie um link simbólico em sites-enabled:
cd /etc/nginx/sites-enabled/
sudo ln -s /etc/nginx/sites-available/sua_app sua_app
Defina o nome da sua app no arquivo hosts:
sudo nano /etc/hosts
Dentro do arquivo:
127.0.0.1 sua_app.local
Start no nginx:
sudo /etc/init.d/nginx start
Teste o endereço com http://sua_app.local:8080/, vai dar uma mensagem. Vamos instalar o Unicorn. No arquivo Gemfile de sua app, adicione:
gem 'unicorn', '3.5.0'
Depois rode o 'bundle install' no terminal. Em 'config/' crie um arquivo 'unicorn.rb' e coloque o conteúdo abaixo conforme sua máquina:
# See http://unicorn.bogomips.org/Unicorn/Configurator.html for complete
# documentation.
worker_processes 2
# Help ensure your application will always spawn in the symlinked
# "current" directory that Capistrano sets up.
working_directory "/home/deployer/myapp.com/current"
# listen on both a Unix domain socket and a TCP port,
# we use a shorter backlog for quicker failover when busy
listen "/tmp/myapp.com.sock", :backlog => 64
listen 8080, :tcp_nopush => true
# nuke workers after 30 seconds instead of 60 seconds (the default)
timeout 30
# feel free to point this anywhere accessible on the filesystem
user 'deployer', 'staff'
shared_path = "/home/deployer/myapp.com/shared"
pid "#{shared_path}/pids/unicorn.pid"
stderr_path "#{shared_path}/log/unicorn.stderr.log"
stdout_path "#{shared_path}/log/unicorn.stdout.log"
Esse é o arquivo default dele encontrado aqui. Para colocar o unicorn em produção é só rodar essa linha no terminal dentro da sua app:
unicorn_rails -c config/unicorn.rb -E production -D
Para matar ele é só rodar:
kill -quit `cat tmp/pids/unicorn.pid`
É só isso, bem tranquilo é rápido, se tiver alguma dúvida comenta que eu ajudo no que puder.
Até a próxima!!
terça-feira, 19 de abril de 2011
Ajax no Rails 3
Era para eu falar neste post sobre teste de controller com RSpec, mas estava fazendo alguns testes com Ajax, então aproveitei o momento para falar de Ajax. Desculpe a demora por novos posts, estava em período de entrega de trabalhos e provas na faculdade, não deu tempo de preparar nada. Todos os códigos que faço aqui estão no Github(github.com/vagnerzampieri/zblog).
Pegue aquele CRUD que fizemos sobre Post, ele vai ser modificado e dará lugar a documentos com extensão '.js.erb'. A ideia é que todas as ações fiquem na index, sendo assim, ficará um carregamento mais rápido e uma página mais dinâmica.
Primeiro coloque a gem 'jquery-rails' no arquivo Gemfile da sua aplicação. A versão que estou usando está com o jquery 1.5.
gem 'jquery-rails', '0.2.7'
Logo em seguida, vá em um terminal e rode o 'bundle install'. Agora rode no terminal 'rails generate jquery:install', ele irá substtuir o prototype pelo jquery.
Primeiro, vamos começar modificando a criação de post. Ele vai ficar da seguinte forma, ao clicar no link 'New' irá carregar abaixo um formulário, ao ser preenchido e enviado irá aparecer na lista o item que foi criado.
Na index, vou modificar a tabela e colocar um id, esse id irá servir depois para identificar aonde irá adicionar na lista o post que for criado.
posts/index.html.erb:
<table id="posts">
Crie um partial que irá virar uma lista dinâmica, já que será muito utilizada no ajax:
posts/_post.html.erb:
<tr id="post_<%= post.id %>">
<td><%= post.title %></td>
<td><%= truncate post.body, :length => 20 %></td>
<td><%= post.publication.strftime "%Y-%m-%d %H:%M:%S" %></td>
<td><%= post.enabled %></td>
<td><%= link_to 'Show', post, :remote => true %></td>
<td><%= link_to 'Edit', edit_post_path(post), :remote => true %></td>
<td><%= link_to 'Destroy', post, :confirm => 'Are you sure?', :method => :delete, :remote => true %></td>
</tr>
Note que coloquei um id dinâmico no 'tr', e nos liks adicionei ':remote => true' é ele que irá fazer a mágica no Ajax, coloque ele também no 'form'.
<%= simple_form_for(@post, :remote => true) do |f| %>
Na index coloque um render para esse partial.
posts/index.html.erb:
<% @posts.each do |post| %>
<%= render post%>
<% end %>
Adicione também o link 'New' um pouco abaixo:
<%= link_to 'New', '/posts/new', :remote => true %>
E uma div onde será chamado o formulário:
<div id="form">
</div>
Crie um arquivo 'new.js.erb' e dentro dele coloque o código abaixo:
$('#form').empty();
$("#form").append("<%= escape_javascript(render(:partial => "form"))%>");
Esse código é bem simples, a primeira linha vai deixar vazio a div 'form', por um simples motivo, se você não colocar essa linha sempre que clicar em um botão ele vai criar um novo elemento em vez de excluir o antigo. A segunda linha chama o partial do 'form'. Crie um arquivo 'create.js.erb' e adicione o código abaixo:
$('#posts').append('<%= escape_javascript(render(@post)) %>');
$("#new_post")[0].reset();
A primeira linha chama o partial 'post' que nós criamos e adiciona mais um elemento na lista. A segunda limpa o formulário para poder ocorrer mais um cadastro. Para finalisar, melhore o controller assim:
def create
@post = Post.new params[:post]
flash[:notice] = 'Post was successfully created.' if @post.save
respond_with @post
end
Agora o 'Show', mais acima irá notar que o link para o 'Show' já fi criado. Adicione a div abaixo na index, ela será o guia que utilizaremos para a aparição do show.
<div id="show">
</div>
Crie um arquivo 'show.js.erb' e adicione o código abaixo:
$('#show').empty();
$('#show').append('<h2>Show post</h2><p><b>Title: </b><%= @post.title %></p><p><b>Body: </b><%= @post.body %></p><p><b>Publication: </b><%= @post.publication.strftime "%Y-%m-%d %H:%M:%S" %></p><p><b>Enabled: </b><%= @post.enabled %></p>');
Como acontece no 'New' a primeira linha é para limpar se existir algo antes. A segunda irá exibir o item ao ser clicado, o append vai exibir tudo que estiver dentro dele. O próximo é o destroy, é o mais simples de todos, crie o arquivo 'destroy.js.erb' e adicione:
$('#post_<%= @post.id %>').remove();
Vai remover a linha exata que você destruir. O último é editar, é bem parecido que o criar, crie os arquivos 'edit.js.erb' e 'update.js.erb':
posts/edit.js.erb:
$('#form').empty();
$("#form").append("<%= escape_javascript(render(:partial => "form"))%>")
Mesma explicação do 'New'.
posts/update.js.erb:
$("#post_<%= @post.id %>").replaceWith("<%= escape_javascript(render(:partial => @post)) %>");
<% @post = Post.new %>
$(".simple_form").replaceWith("<%= escape_javascript(render(:partial => "form"))%>")
Primeira linha, vai adicionar o elemento criado na lista. Segundo e terceira linha, vai resetar a variável de instância para ao editar o formulário, se modifique de edição para criação. Deixe o método update no controller da forma abaixo:
def update
@post = Post.find params[:id]
flash[:notice] = 'Post was successfully updated.' if @post.update_attributes params[:post]
respond_with @post
end
Pode apagar agora os arquivos abaixo, as suas funcionalidades não serão mais necessárias já que foram migradas.
new.html.erb
edit.html.erb
show.html.erb
Chega por hoje, ainda não pensei em um próximo post, talvez um banco de imagem com mais brincadeiras com Ajax.
Até a próxima!!
Pegue aquele CRUD que fizemos sobre Post, ele vai ser modificado e dará lugar a documentos com extensão '.js.erb'. A ideia é que todas as ações fiquem na index, sendo assim, ficará um carregamento mais rápido e uma página mais dinâmica.
Primeiro coloque a gem 'jquery-rails' no arquivo Gemfile da sua aplicação. A versão que estou usando está com o jquery 1.5.
gem 'jquery-rails', '0.2.7'
Logo em seguida, vá em um terminal e rode o 'bundle install'. Agora rode no terminal 'rails generate jquery:install', ele irá substtuir o prototype pelo jquery.
Primeiro, vamos começar modificando a criação de post. Ele vai ficar da seguinte forma, ao clicar no link 'New' irá carregar abaixo um formulário, ao ser preenchido e enviado irá aparecer na lista o item que foi criado.
Na index, vou modificar a tabela e colocar um id, esse id irá servir depois para identificar aonde irá adicionar na lista o post que for criado.
posts/index.html.erb:
<table id="posts">
Crie um partial que irá virar uma lista dinâmica, já que será muito utilizada no ajax:
posts/_post.html.erb:
<tr id="post_<%= post.id %>">
<td><%= post.title %></td>
<td><%= truncate post.body, :length => 20 %></td>
<td><%= post.publication.strftime "%Y-%m-%d %H:%M:%S" %></td>
<td><%= post.enabled %></td>
<td><%= link_to 'Show', post, :remote => true %></td>
<td><%= link_to 'Edit', edit_post_path(post), :remote => true %></td>
<td><%= link_to 'Destroy', post, :confirm => 'Are you sure?', :method => :delete, :remote => true %></td>
</tr>
Note que coloquei um id dinâmico no 'tr', e nos liks adicionei ':remote => true' é ele que irá fazer a mágica no Ajax, coloque ele também no 'form'.
<%= simple_form_for(@post, :remote => true) do |f| %>
Na index coloque um render para esse partial.
posts/index.html.erb:
<% @posts.each do |post| %>
<%= render post%>
<% end %>
Adicione também o link 'New' um pouco abaixo:
<%= link_to 'New', '/posts/new', :remote => true %>
E uma div onde será chamado o formulário:
<div id="form">
</div>
Crie um arquivo 'new.js.erb' e dentro dele coloque o código abaixo:
$('#form').empty();
$("#form").append("<%= escape_javascript(render(:partial => "form"))%>");
Esse código é bem simples, a primeira linha vai deixar vazio a div 'form', por um simples motivo, se você não colocar essa linha sempre que clicar em um botão ele vai criar um novo elemento em vez de excluir o antigo. A segunda linha chama o partial do 'form'. Crie um arquivo 'create.js.erb' e adicione o código abaixo:
$('#posts').append('<%= escape_javascript(render(@post)) %>');
$("#new_post")[0].reset();
A primeira linha chama o partial 'post' que nós criamos e adiciona mais um elemento na lista. A segunda limpa o formulário para poder ocorrer mais um cadastro. Para finalisar, melhore o controller assim:
def create
@post = Post.new params[:post]
flash[:notice] = 'Post was successfully created.' if @post.save
respond_with @post
end
Agora o 'Show', mais acima irá notar que o link para o 'Show' já fi criado. Adicione a div abaixo na index, ela será o guia que utilizaremos para a aparição do show.
<div id="show">
</div>
Crie um arquivo 'show.js.erb' e adicione o código abaixo:
$('#show').empty();
$('#show').append('<h2>Show post</h2><p><b>Title: </b><%= @post.title %></p><p><b>Body: </b><%= @post.body %></p><p><b>Publication: </b><%= @post.publication.strftime "%Y-%m-%d %H:%M:%S" %></p><p><b>Enabled: </b><%= @post.enabled %></p>');
Como acontece no 'New' a primeira linha é para limpar se existir algo antes. A segunda irá exibir o item ao ser clicado, o append vai exibir tudo que estiver dentro dele. O próximo é o destroy, é o mais simples de todos, crie o arquivo 'destroy.js.erb' e adicione:
$('#post_<%= @post.id %>').remove();
Vai remover a linha exata que você destruir. O último é editar, é bem parecido que o criar, crie os arquivos 'edit.js.erb' e 'update.js.erb':
posts/edit.js.erb:
$('#form').empty();
$("#form").append("<%= escape_javascript(render(:partial => "form"))%>")
Mesma explicação do 'New'.
posts/update.js.erb:
$("#post_<%= @post.id %>").replaceWith("<%= escape_javascript(render(:partial => @post)) %>");
<% @post = Post.new %>
$(".simple_form").replaceWith("<%= escape_javascript(render(:partial => "form"))%>")
Primeira linha, vai adicionar o elemento criado na lista. Segundo e terceira linha, vai resetar a variável de instância para ao editar o formulário, se modifique de edição para criação. Deixe o método update no controller da forma abaixo:
def update
@post = Post.find params[:id]
flash[:notice] = 'Post was successfully updated.' if @post.update_attributes params[:post]
respond_with @post
end
Pode apagar agora os arquivos abaixo, as suas funcionalidades não serão mais necessárias já que foram migradas.
new.html.erb
edit.html.erb
show.html.erb
Chega por hoje, ainda não pensei em um próximo post, talvez um banco de imagem com mais brincadeiras com Ajax.
Até a próxima!!
Assinar:
Postagens (Atom)