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.

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
 
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

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

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

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!!

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!!!

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!!

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!!

sexta-feira, 18 de março de 2011

Ruby on Rails do zero, Teste de model com Rspec

  Continuando nosso blog(github.com/vagnerzampieri/zblog), irei de Rspec hoje para validar nossos models.
 
  Rspec:
 
  Vamos fazer então nossos primeiros teste, algo bem simples, vai ser teste de validação de modelo. Certifique que as gems abaixo estão no seu Gemfile:
 
  gem 'rspec'
  gem 'rspec-rails'
 
  Se não existirem, coloque e faça um "bundle install" no terminal. Ainda no terminal instale o rspec no seu projeto fazendo um:
 
  rails g rspec:install
 
  Ele criará isso:
 
  create  .rspec
  create  spec
  create  spec/spec_helper.rb
 
  Entre na pasta "spec" que ele criou, crie uma pasta chamada "models", dentro dela crie o arquivo "post_spec.rb", e adicione o conteúdo abaixo:
 
  require 'spec_helper'

  describe Post do
    it "test"
  end
 
  Primeiro eu dou um "require 'spec_helper'" para ele chamar o arquivo de mesmo nome que está na pasta "spec" para que eu possa utilizar o Rspec. Eu vou testar comportamento e não método, vou usar BDD, testar comportamento e verificar se a ação que o usuário efetuou está de acordo. Para você ver alguma saída rode no terminal:
 
  rake spec:models
 
  Vocé irá ver uma saída em amarelo, e um contador avisando que existe 1 exemplo, e ele está pendente. Isso é só um teste para ver se o Rspec está funcionando da forma certa. A primeira coisa que testaremos é se o Post pode ser criado sem título, sempre tenha em mente, "red", "green", "refactory".
 
  RED, vamos ver nossa ideia quebrar de propósito com esse exemplo abaixo:
 
  describe Post do
    it "should be not created without title" do
      post = Post.new(:title => "", :body => "Texto qualquer em body", :publication => Time.now.strftime("%Y-%m-%d %H:%M:%S"), :enabled => 1)
      post.should be_valid
    end
  end
 
  Saída:
 
  F

  Failures:

    1) Post should be not created without title
       Failure/Error: post.should be_valid
         expected valid? to return true, got false
       # ./spec/models/post_spec.rb:6:in `block (2 levels) in <top (required)>'

  Finished in 0.04851 seconds
  1 example, 1 failure
  rake aborted!
  ruby -S bundle exec rspec ./spec/models/post_spec.rb failed
 
  Pra quem não conhece Rspec, eu descrevou uma situação quem não pode acontecer no "it", mas faço ao contrário no final "post.should be_valid", eu digo que ele "deve validar". Se você ler a saída vai ver o que estou dizendo. Para nossa espectativa funcionar troque o "should", por "should_not" e irá ver que a saída será GREEN. Faça o mesmo teste para "body", já que são os únicos que validamos no post passado em "app/models/post.rb".
 
  describe Post do
    it "should be not created without title" do
      post = Post.new(:title => "", :body => "Text for body", :publication => Time.now.strftime("%Y-%m-%d %H:%M:%S"), :enabled => 1)
      post.should_not be_valid
    end
   
    it "should be not created without body" do
      post = Post.new(:title => "Title", :body => "", :publication => Time.now.strftime("%Y-%m-%d %H:%M:%S"), :enabled => 1)
      post.should be_valid
    end
  end
 
  Ocorreu o mesmo RED de antes, faça ele ficar GREEN e vamos agora para o REFACTORY. Esse código está meio repetitivo, vamos deixar ele mais elegante:
 
  describe Post do
    before(:each) do
      @post = Post.new(:title => "Title", :body => "Text for body", :publication => Time.now.strftime("%Y-%m-%d %H:%M:%S"), :enabled => 1)
    end
   
    it "should be not created without title" do
      @post.title = nil
      @post.should_not be_valid
    end
   
    it "should be not created without body" do
      @post.body = nil
      @post.should_not be_valid
    end
  end
 
  Eu criei um "before(:each)" que criará um post, dentro de cada "it" eu passo o valor que eu quero testar como "nil", irá dar o efeito que quero. Crio um último "it" para todos os dados passem.
 
  it 'should be created with all requirements' do
    @post.should be_valid
  end
 
  Agora façam os mesmos tipos de teste com User, depois conferem se ficou igual ao que eu fiz. Lembre que o Devise faz validação de campos e que você só precisa testar os campos que exigem validação. E também não existe um certo, e sim o que você acha necessário.
 
  describe User do
    before(:each) do
      @user = User.new(:name => 'User Test', :login => 'usertest', :email => 'test@test.com', :password => 'senha123', :password_confirmation => 'senha123' )
    end
   
    it 'should be not created without name' do
      @user.name = nil
      @user.should_not be_valid
    end
   
    it 'should be not created without login' do
      @user.login = nil
      @user.should_not be_valid
    end

    it 'should be not created without email' do
      @user.email = nil
      @user.should_not be_valid
    end
   
    it 'should be not created without password' do
      @user.password = nil
      @user.should_not be_valid
    end
   
    it 'should be not created if password and password_confirmation not equal' do
      @user.password = 'senha123'
      @user.password_confirmation = 'senha'
      @user.password.should_not == @user.password_confirmation
    end
    
    it 'should be created with all requirements' do
      @user.should be_valid
    end 
  end
 
  O único comportamento diferente é o penúltimo que testa se a senha do usuário está diferente.
 
  Vamos voltar a fazer modificações no Post. Temos agora dois layouts simulando a "home" de um site e "admin", mas nossa rota não indica que "posts" faz parte de um admin, então vá no arquivo routes e modifique o path da rota, e depois é só carregar a página, veja como vai ficar abaixo.
 
  resources :posts, :path => 'admin/posts'
 
  Vamos adicionar autor na nossa tabela posts, já que todo post precisa de um autor, e esse autor será o usuário que estiver armazenado na nossa sessão. Primeiro crie um migração nova que adicionará o campo "author_id" na tabela "posts", será um relacionamento de um autor para muitos posts, e somente um post para um usuário. Crie a migração desta forma:
 
  rails g migration add_field_author_id_to_posts
 
  Abra o arquivo que foi criado e faça as modificações abaixo:
 
  class AddFieldAuthorIdToPosts < ActiveRecord::Migration
    def self.up
      add_column :posts, :author_id, :integer
      add_index :posts, :author_id
    end

    def self.down
      remove_index :posts, :author_id
      remove_column :posts, :author_id
    end
  end
 
  Está adicionando uma nova coluna e um novo índice na tabela posts. Agora abra o model "user" e adicione a linha abaixo, na primeira linha depois da classe ter sido criada.
 
  has_many :posts, :foreign_key => "author_id"
 
  Está dizendo que um usuário terá muitos posts, e sua chave estrangeira é "author_id". Agora no model "post" adicione a linha abaixo, na primeira linha depois da classe ter sido criada.
 
  belongs_to :author, :class_name => "User", :foreign_key => "author_id"
 
  Está dizendo que a chave estrangeira "author_id" pertence a classe "User". Como sempre o post será do usuário logado ao sistema que é um autor, a associação de autor e post não será interferida neste momento. Abra o controller "posts" e faça o código abaixo no método create.
 
  def create
    @post = Post.new params[:post]
    @post.author_id = current_user.id
   
    if @post.save
      flash[:notice] = 'Post was successfully created.'
      respond_with @post
    else
      render :action => :new
    end
  end
 
  Você não viu errado, é só adicionar essa linha mesmo, antes de salvar eu adiciono o id do usuário atual no campo "author_id", esse "current_user" é um método do Devise, retorna um hash com os dados do usuário. Nas views "index" e "show" adicione a saída.
 
  index:
 
  <th>Author</th>
 
  <td><%= post.author.name unless post.author.nil? %></td>
 
  show:
 
  <p>
    <b>Author:</b>
    <%= @post.author.name unless @post.author.nil? %>
  </p>
 
  Para quem não conhece esse "unless" é uma negação, só vai executar se author não for nulo.
 
  Chega por hoje, o próximo post deve ser de Rspec, mas teste de controller.
  Até a próxima!!
 

segunda-feira, 14 de março de 2011

Otimizando seu controller

  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!!

quinta-feira, 10 de março de 2011

Ruby on Rails do zero, Devise

Continuação do post "Ruby on Rails do zero" no repositório github.com/vagnerzampieri/zblog tem o projeto que estamos fazendo aqui.

Devise:
  Agora vamos ver como o Devise funciona, se você for dar uma olhada no post anterior irá notar que já baixamos o Devise, mas ainda não instalamos ele. A linha abaixo é a linha que fica no arquivo Gemfile que fica na raiz principal da sua aplicação.
 
  gem 'devise', '1.1.rc2'
 
  O Devise é um autenticador, através dele você poderá criar usuário, logar, recuperar senha, sessão de usuário aberta pelo tempo que desejar, criptografa senha, e muito mais. É uma ferramenta muito completa e muito usada no mundo Rails e não é difícil de usar, o básico dela qualquer nível de programador pode usar, até o menos experiente. Esse Devise que estou usando provavelmente já deve existir um mais recente, então use um mais recente, não acredito que vai quebrar a aplicação ou algo assim, mas se estiver com receio utilize essa versão mesmo.
 
  Vamos dizer que não fizemos download do Devise, se estiver usando RVM coloque aquela linha que dei um pouco acima e coloque ela em Gemfile e faça um "bundle install". Note que ela será baixada para o seu projeto.
 
  Agora vamos instalar o Devise:
 
  rails g devise:install
 
  Irá instalar dois arquivos na sua aplicação, o mais importante é o arquivo de configuração dele 'config/initializers/devise.rb'. É importante dar uma olhada nele, ele já é bem explicado, quando eu for fazer alguma alteração nele irei explicar o por que, mas saiba que ele existe e é muito útil. Outra coisa legal que ele instala é em 'config/locales/devise.en.yml' para dar a saída na língua que você quiser.
 
  O Devise além de te criar os arquivos vai mostrar uma saída que  pedirá que você faça 3 passos. O primeiro é configirar uma url default, isso é só para quando for desenvolvimento. A segunda é para configurar uma rota padrão, esse passo foi feito no post passado, eu cheguei a criar um controller home e coloquei a rota da forma que pede o arquivo, o Devise pede esse passo por que ele usa a rota "root" para os seus redirecionamentos. O terceiro passo são alertas para o Devise mostrar para o usuário se a ação feita foi correspondida da forma esperada ou se ocorreu algum erro. Faça os 3 passos na sua aplicação, se estiver seguindo o post passado o segundo não precisará fazer, por que já está feito.
 
  Ao usar o Devise é habilitado um gerador, então vamos utilizar ele e ver a mágica dele.
 
  rails g devise User
 
  As importantes coisas que ele faz eu vou listar abaixo:
 
  create    app/models/user.rb
  create    db/migrate/20110307130914_devise_create_users.rb
  route  devise_for :users
 
  Utilizando o model User que você colocou como opção ele cria uma série de arquivos com o nome do seu modelo, mas antes de falar sobre o que ele criou vamos logo adicionar as views do Devise na sua aplicação.
 
  rails g devise:views 
 
  Vou começar pelo model, 'app/models/user.rb':
 
  class User < ActiveRecord::Base
    # Include default devise modules. Others available are:
    # :token_authenticatable, :confirmable, :lockable and :timeoutable
    devise :database_authenticatable, :registerable,
           :recoverable, :rememberable, :trackable, :validatable

    # Setup accessible (or protected) attributes for your model
    attr_accessible :email, :password, :password_confirmation, :remember_me
  end
 
  O Devise inclui alguns modulos que serão usados por ele. Na linha que tem 'attr_accessible' é para habilitar os campos que você for querer utilizar quando criar a tabela 'users', se colocar um campo novo e não adicionar nesta linha do model não vai funcionar. Vamos deixar usuário um pouco mais interessante, coloque como abaixo:
 
  attr_accessible :name, :login, :enabled, :url_image, :email, :password, :password_confirmation, :remember_me
 
  Eu adicionei 'name', 'login', 'enabled', 'url_image', os dois primeiros ta na cara. O 'enabled' é para se eu quiser ativar, ou desativar um usuário, eu não vou precisar excluir ele de vez, é só desativar. O 'url_image' é para se o usuário não quiser usar a opção do Gravatar.
 
  Agora no arquivo 'db/migrate/20110307130914_devise_create_users.rb', ele vai ficar assim com as modificações.
 
  class DeviseCreateUsers < ActiveRecord::Migration
    def self.up
      create_table(:users) do |t|
        t.string :name
        t.string :login
        t.boolean :enabled, :default => true
        t.string :url_image
        t.database_authenticatable :null => false
        t.recoverable
        t.rememberable
        t.trackable

        # t.confirmable
        # t.lockable :lock_strategy => :failed_attempts, :unlock_strategy => :both
        # t.token_authenticatable


        t.timestamps
      end

      add_index :users, :name
      add_index :users, :login, :unique => true
      add_index :users, :enabled
      add_index :users, :url_image
      add_index :users, :email,                :unique => true
      add_index :users, :reset_password_token, :unique => true
      # add_index :users, :confirmation_token,   :unique => true
      # add_index :users, :unlock_token,         :unique => true
    end

    def self.down
      drop_table :users
    end
  end
 
  Se você comparar linha por linha, irá notar que eu adicionaei os 4 campos e adicionei os index deles. Antes de rodar o 'rake db:migrate', vamos nas views do Devise e colocar os campos que agente adicionou.
 
  Em 'app/views/devise/registrations/new.html.erb' e 'app/views/devise/registrations/edit.html.erb' ficará assim:
 
  <h2>Sign up</h2>

  <%= form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f| %>
    <%= devise_error_messages! %>
   
    <p><%= f.label :name %><br />
    <%= f.text_field :name %></p>
   
    <p><%= f.label :email %><br />
    <%= f.text_field :email %></p>

    <p><%= f.label :login %><br />
    <%= f.text_field :login %></p>

    <p><%= f.label :password %><br />
    <%= f.password_field :password %></p>

    <p><%= f.label :password_confirmation %><br />
    <%= f.password_field :password_confirmation %></p>
   
    <p><%= f.label :enabled %><br />
    <%= f.check_box :enabled %></p>
   
    <p><%= f.label :url_image %><br />
    <%= f.text_field :url_image %></p>

    <p><%= f.submit "Sign up" %></p>
  <% end %>

  <%= render :partial => "devise/shared/links" %>
 
  Para você não ficar maluco por que não viu saída de nada até agora, roda 'rake db:create' e 'rake db:migrate' no terminal e vai em 'http://localhost:3000/users/sign_up', mas eu quero duas coisas, uma quero acessar essas rotas através da minha home que criei e quero mudar essas rotas. Primeiro vamos para 'app/home/index'.
 
  <div id="user_nav">
    <% if user_signed_in? %>
      Logado como <%= current_user.email %>. Não é você?
      <%= link_to 'Sair', destroy_user_session_path, :method => :delete %>
      </br>
      <%= link_to 'Post', posts_path %>
    <% else %>
      <%= link_to 'Cadastrar', new_user_registration_path %> ou <%= link_to 'Logar', new_user_session_path %>
    <% end %> 
  </div>
 
  Eu adicionei o código acima, ma o que ele faz, é bem simples. Se o usuário estiver logado ele cai no 'if', que vai mostrar qual email do usuário logado, dar um link para ele destruir a sessão atual dele e um link para 'Post', senão dará duas opções, uma se cadastrar e a outra se logar. Lembre o Devise só faz a autenticação, autorização tem outras formas, se colocar 'posts' na url o Devise não vai te impedir de ir para página. Crie um usuário qualquer. Ao criar irá notar que ele já se loga automaticamente, e mostra uma mensagem que foi logado com sucesso.
 
  Vá na sua tabela users e veja como esse registro de usuário foi criado. Notará que a senha por exemplo está criptografada em 'encrypted_password', que o Devise conta quantas vezes o seu usuário se conectou ao sistema em 'sign_in_count', entre outras informações.
 
  Outra coisa, o model user não tem validação ainda, só para os campos que o Devise criou, então vamos colocar uma validação simples, de pressença, se existe ou não dado naquele campo.
  
  Em 'app/models/user.rb':
 
  validates_presence_of :name, :login
 
  Tente criar um usuário agora sem nome e login para ver o que acontece. Erro, agora tem uma pequena validação, mais a frente vou usar RSpec para testar as nossas validações de formulários.
 
  Se você fez testes se logando viu que a opção é de logar é com email, mas se você não quiser usar email ? Em 'config/initializers/devise.rb' tem uma linha comentada:
 
  config.authentication_keys = [ :email ]
 
  Teste colocando login:
 
  config.authentication_keys = [ :login ]
 
  Em 'app/views/devise/sessions' troque o campo email por login. Vamos configurar um Range de quantos dígitos poderá ter em um password:
 
  config.password_length = 4..20 # Coloquei de 4 à 20 para ilustração.
 
  Leia com atenção as inúmeras codificações que poderá fazer em termos de sessão de usuário. Se quiser configurar a rota para ficar de uma maniera que vai agradar mais você, faça assim:
 
  Em 'config/routes.rb':
 
  devise_for :users, :path => 'usuarios', :path_names => {:sign_in => 'logar', :sign_out => 'sair', :sign_up => 'cadastrar'}
 
  Para encerrar o post de hoje vamos usar o Gravatar. Eu ainda não falei de tudo que da pra fazer com o Devise, quando eu precisar fazer mais coisas nele vou escrever aqui.
 
  O Gravatar é bem simples, coloque a linha abaixo no seu helper, 'app/helpers/application_helper.rb':
 
  def avatar_url(user)
    if user.url_image.present?
      user.url_image
    else
      gravatar_id = Digest::MD5.hexdigest(user.email.downcase)
      "http://gravatar.com/avatar/#{gravatar_id}.png?s=48"
    end
  end
 
  E em 'app/views/home/index.html', chame o helper passando o usuario atual como parâmetro:
 
  Logado como <%= avatar_url(current_user) %> <%= current_user.email %>. Não é você?
 
  O código do método é bem simples, primeiro ele verifica se existe alguma url de imagem no campo 'url_image' que você colocou anteriormente, senão ele vai utilizar o email do usuário como um id para buscar a imagem que está armazenada no Gravatar, o parâmetro 's=48' no final é para definir o tamanho que será dimensionada a imagem.
 
  Chega por hoje, eu decidi fazer logo a autenticação por um simples motivo, todo site tem usuários que tem permissões específicas, áreas que só ele pode entrar, então é geralmente a parte em que se trabalha mais em um site. No próximo post vamos voltar a mexer no scaffold que fizemos de post.
 
  Até a próxima!!

quinta-feira, 3 de março de 2011

Ruby on Rails do zero

No decorrer dos meus posts vou trabalhar sempre na mesma aplicação que começarei neste post, vou disponibilizar ela no Github.
Essa aplicação terá de tudo que um site tem normalmente, Devise, Simple Form, Sphinx, Acts As Taggable On, Gravatar, Autocomplete, Ajax, Rspec, etc.. Vou ajudar a criar tarefas que otimizem o seu tempo, como testar suas aplicações, como fazer um bom código. Muita coisa que vou escrever aqui vocês poderam encontrar fazendo uma busca no Google, mas a diferença é que vai estar tudo em um só lugar e explicado em vários posts para facilitar sua vida, fora que como disse antes, a aplicação ficará no Github para o seu auxílio.

Vou utilizar o Ruby 1.9.2, e estou usando RVM.

Crie uma aplicação nova:

rails new zblog -d mysql

Vá na pasta public e renomeie o arquivo index.

Abra o arquivo Gemfile e adicione as linhas abaixo:

gem 'aws-s3'
gem 'warden', '0.10.7'
gem 'bcrypt-ruby', '2.1.2'
gem 'devise', '1.1.rc2'
gem 'rspec'
gem 'rspec-rails'
gem 'simple_form', '1.3.1'

Irei falar de cada um com o tempo. Vamos configurar o Simple Form para você poder fazer os scaffolds já utilizando ele, primeiro instale.

rails g simple_form:install

Arquivos gerados abaixo:

create  config/initializers/simple_form.rb
create  config/locales/simple_form.en.yml
create  lib/templates/erb/scaffold/_form.html.erb

Crie um controller home que será a nossa futura capa:

rails g controller home

Vá em config/routes e coloque:

root :to => "home#index"

Vamos gerar um scaffold de Post para você ver a mágica do Simple Form.

rails g scaffold Post title:string body:text publication:datetime enabled:boolean

Em posts/_form.html.erb:

<%= simple_form_for(@post) do |f| %>
  <%= f.error_notification %>

  <div class="inputs">
    <%= f.input :title %>
    <%= f.input :body %>
    <%= f.input :publication %>
    <%= f.input :enabled %>
  </div>

  <div class="actions">
    <%= f.button :submit %>
  </div>
<% end %>

Se está acostomado com os scaffolds do Rails, você vai logo ver a diferença. Primeiro é adicionado um helper chamado simple_form_for, que é nosso formulário, os inputs criados criam um html automático que você teria que fazer, isso diminui e muito o código a ser colocado no seu arquivo.

Adicione o CSS abaixo para dar uma melhorada no layout:


.simple_form label {
  float: left;
  width: 100px;
  text-align: right;
  margin: 2px 10px;
}

.simple_form div.input {
  margin-bottom: 10px;
}

.simple_form div.boolean, .simple_form input[type='submit'] {
  margin-left: 120px;
}

.simple_form div.boolean label, .simple_form label.collection_radio {
  float: none;
  margin: 0;
}

.simple_form label.collection_radio {
  margin-right: 10px;
  margin-left: 2px;
}

.simple_form .error {
  clear: left;
  margin-left: 120px;
  font-size: 12px;
  color: #D00;
  display: block;
}

.simple_form .hint {
  clear: left;
  margin-left: 120px;
  font-size: 12px;
  color: #555;
  display: block;
  font-style: italic;
}

Depois disso faça alguns teste utilizando o Simple Form, como adicionar um "hint" no input "title":

<%= f.input :title, :hint => "title" %>

também teste validação no seu model, e veja como fica o layout:

class Post < ActiveRecord::Base
  validates_presence_of :title, :body
end

Existe um arquivo em config/initializers/simple_form.rb que você poderá configurar e um arquivo em config/locales/simple_form.en.yml, para tradução, se criar um arquivo simple_form.pt-br.yml, irá poder traduzir os inputs gerados pelo Simple Form. Mas se for traduzir tem que especificar em config/application.rb, qual será a língua padrão:

config.i18n.default_locale = 'pt-br'

Para não alongar muito o post e deixar cansativo, vou encerrar ele por aqui, no próximo vou mostrar o Devise e o Gravatar. Vou mostrar mais sobre o Simple Form com o tempo, por enquanto paro por aqui. Essa aplicação já está no Github(github.com/vagnerzampieri/zblog), você irá notar que tem código a mais do que foi mostrado aqui, mas nós chegaremos lá.
Até a pŕoxima.

terça-feira, 8 de fevereiro de 2011

Não sabe um caminho para seguir na programação? tente este aqui, parte 6/6

Comunidades, não tenha medo delas, elas só existem para ajudar.

Terminar essa saga parece um parto, mas enfim consegui. Vou falar de comunidades e do que elas me ajudaram até agora.
Quando eu comecei a programar de verdade (foi quando eu arrumei meu primeiro emprego e único em 09/2009), eu nem fazia ideia de como construir uma futura carreira, na realidade se eu não tivesse no terceiro período da faculdade eu tinha desistido de informática no meu primeiro dia de trabalho. Eu tive que instalar um monte de parada na máquina, sem nunca ter mexido em um Linux direito, nem sabia configurar o PHP naquela época, linguagem na qual não trabalhei dois mês e mudamos para Ruby :). Eu imaginei naquela época que não ia durar no emprego, que programação não era para mim, que aquilo não fazia lógica, mas ao mesmo tempo que eu senti aquele medo absurdo que não fazia ideia de onde vinha, me lembrei de algo que eu sigo em minha vida inteira, não desisto das coisas que acredito. Falei para mim mesmo, existe Ctrl-z pra que, pra usar, se errar faço de novo, e tive a ajuda de um grande mestre jedi que virou meu amigo, que é o Fernando Kosh, o cara me ensinou o caminho das pedras, mas ao mesmo tempo fazia o "se vira", que é muito útil.
E uma das coisas que ele mais me falava/fala é das comunidades open source que existe na área, a primeira delas foi o #horaextra que acontece no centro do Rio em uma mesa de bar todas às segundas. Os caras falam de tecnologia a noite toda praticamente. Mas não parou por ela ao ser apresentado ao mundo Ruby on Rails e Linux conheci uma quantidade grande de pessoas que participam de comunidades e incentivam a sua participação nelas.
Só que mesmo assim eu não participava delas, eu pensava que não precisava, que o mais importante era eu estudar, me desenvolver sozinho, só que tem um problema nisso. Quando você faz uma busca no Google por algo relacionado a programação, algum erro que você não consegue tirar, ou algum script que você quer fazer mas não tem ideia de como começar. É por causa das comunidades, dos fóruns, das listas que sua dúvida é tirada, é por causa dessa interação com outros programadores que você vai conseguir tirar as suas dúvidas e ajudar outros programadores que vão ter dúvidas que você já teve, e agora tem conhecimento adquirido para ajudar.
A minha ficha só caiu de verdade em relação a participação foi quando eu fui na palestra do Henrique Bastos no DevInRio de 2010, a palestra foi tão boa que eu me senti um idiota por não participar das comunidades, naquela mesma semana fui ao #horaextra, #dojorio, tive uma ideia de evento maneira para fazer (que não foi concretizada ainda, já que eu parei no hospital tempos depois por uma arritimia no coração que me deixou parado um tempo, mas isso não vem ao caso, mas por causa disso eu perdi o RubyConf de 2010, foi dias antes, rssr). Eu posso não ter conseguido colocar minha ideia em prática, mas estou ajudando nos encontros de #ForkinRio na Cidadelas, empresa que trabalho, estudamos Rails3 e tem sido uma experiência muito boa, confeço que não participo do #rubyonrio como queria, ou das outras comunidades, mas faço o possível para conparecer e ajudar no que puder.
Hoje aquele cara que começou na área com medo, achando que programação é uma viagem, que nunca ia conseguir, já foi promovido, elogiado pelo seu trabalho e comprometimento com a empresa, e virou víciado em desafios, programar coisas diferentes e difíceis, e encara uma missão com calma e racionalidade, por que sabe hoje que programação não é um bicho de sete cabeças.
Espero que eu consiga ajudar alguém com minha experiência, vou tentar postar regurlamente as minhas experiências com programação, principalmente falando de Ruby e Linux.
Até a próxima !!

sexta-feira, 21 de janeiro de 2011

Não sabe um caminho para seguir na programação? tente este aqui, parte 5/6

O que é NoSQL ?

Fui fazer uma pesquisa sobre NoSQL, para fazer um bom resumo para quem está começando. Achei o 2 posts do Jean Nascimento muito interessante e decidi não escrever nada a respeito e só encaminha-los para eles, são o que vocês precisam para entender o que é NoSQL. O Jean Nascimento é um dos evangelistas de NoSQL no Brasil.
NoSQL - você realmente sabe do que estamos falando?
3 razões para usar MongoDB
Boa leitura e até a próxima.