RSS Feed
  1. [Quick Post] – Migrations Para Models Já Existentes.

    October 21, 2011 by urieljuliatti

    Fala pessoal, beleza? Hoje vou demonstrar rapidamente sobre migrations para modelos já existentes.

    A necessidade surgiu quando tive a necessidade de criar um campo/atributo booleano para um modelo já existente.

    Presume-se que você já tenha um modelo, no meu caso é o User, que possui apenas um atributo “name” e “email.

    O Rails fornece um recurso interessante: Migrations, que vai te ajudar bastante a organizar sua base de dados e todo o fluxo possível.

    Para criar uma migration para um model existente você fará assim:

    1
    
    rails g migration AddHiddenToUser hidden:boolean
    rails g migration AddHiddenToUser hidden:boolean

    Onde o hidden será o campo novo para o modelo User que já existe. O console trará o seguinte:

    1
    2
    
    invoke  active_record
    create    db/migrate/20111021182503_add_hidden_to_user.rb
    invoke  active_record
    create    db/migrate/20111021182503_add_hidden_to_user.rb

    Ele chama o Active Record e cria um arquivo baseado na linha que você digitou. Aproveite e abra a sua migration gerada, logo você obterá:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    
    class AddHiddenToUser < ActiveRecord::Migration
     
    def self.up
     
    add_column :users, :hidden, :boolean
     
    end
     
    def self.down
     
    remove_column :users, :hidden
     
    end
     
    end
    class AddHiddenToUser < ActiveRecord::Migration
    
    def self.up
    
    add_column :users, :hidden, :boolean
    
    end
    
    def self.down
    
    remove_column :users, :hidden
    
    end
    
    end

    Lindo! O Rails reconheceu que você quer adicionar um atributo do tipo boolean para uma tabela Users (add_column :users, :hidden, :boolean)

    Até agora o rails fez todo o esqueleto, porém nada ainda funciona. Para isso funcionar, você vai ter que rodar um rake db:migrate, onde o rails executa uma função que adiciona literalmente o atributo “hidden” a sua tabela Users.

    Veja o log após a execução do comando:

    1
    2
    3
    4
    
    <pre>==  AddHiddenToUser: migrating ================================================
    -- add_column(:users, :hidden, :boolean)
       -> 0.0081s
    ==  AddHiddenToUser: migrated (0.0082s) =======================================</pre>
    <pre>==  AddHiddenToUser: migrating ================================================
    -- add_column(:users, :hidden, :boolean)
       -> 0.0081s
    ==  AddHiddenToUser: migrated (0.0082s) =======================================</pre>

    Lindezidade total, hein?

    Para finalizar, basta adicionar o field na view:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    
    <pre><%= form_for(@user) do |f| %>
      <%= render "shared/error_messages", :target => @user %>
     
      <div class="field">
        <%= f.label :name %><%= mark_required(@user, :name) %><br />
        <%= f.text_field :name %>
      </div>
      <div class="field">
        <%= f.label :email %><%= mark_required(@user, :email) %><br />
        <%= f.text_field :email %>
      </div>
     <div class="field"></strong>
         <%= f.label :hidden %><br />
         <%= f.check_box :hidden %>
     </div>
      <div class="actions">
        <%= f.submit %>
      </div>
    <% end %>
    <pre><%= form_for(@user) do |f| %>
      <%= render "shared/error_messages", :target => @user %>
    
      <div class="field">
        <%= f.label :name %><%= mark_required(@user, :name) %><br />
        <%= f.text_field :name %>
      </div>
      <div class="field">
        <%= f.label :email %><%= mark_required(@user, :email) %><br />
        <%= f.text_field :email %>
      </div>
     <div class="field"></strong>
         <%= f.label :hidden %><br />
         <%= f.check_box :hidden %>
     </div>
      <div class="actions">
        <%= f.submit %>
      </div>
    <% end %>

    Antes de concluir, um detalhe importante que percebi ao implementar essa funcionalidade é que o Rails fornece funcionalidades bacanas ao acrescentar uma migration dessa forma. Abra o seu console e teste da seguinte forma:

    1
    2
    3
    4
    
    ruby-1.9.2-p136 :004 > user = User.first
     => #<User id: 1, name: "Uriel", email: "uriel.juliattivalle@gmail.com", created_at: "2011-10-21 18:39:36", updated_at: "2011-10-21 18:39:36", hidden: true>
    ruby-1.9.2-p136 :005 > user.hidden?
     => true
    ruby-1.9.2-p136 :004 > user = User.first
     => #<User id: 1, name: "Uriel", email: "uriel.juliattivalle@gmail.com", created_at: "2011-10-21 18:39:36", updated_at: "2011-10-21 18:39:36", hidden: true>
    ruby-1.9.2-p136 :005 > user.hidden?
     => true

    Uma vez que seu atributo é do tipo Boolean, o rails fornece um helper method chamado “hidden?” que retorna true ou false. Muito útil, uma vez que outras situações teríamos que fazê-lo na mão, apesar de simples tomaria um certo tempo.

    Semana que vem tem RubyConf2011! Ainda dá tempo de se cadastrar http://rubyconf2011.akitaonrails.com/en/

    É isso aí rapazeada, vamo que vamo!


  2. Desafios no Caminho.

    September 16, 2011 by urieljuliatti

    A Vida.

    Desde quando comecei a minha jornada no mundo do desenvolvimento na Giran (@giran_br), tenho tido contato com inúmeras novidades, entre elas:

    • A prática do versionar software (Git).
    • Documentação de Software.
    • Metodologias Ágeis.
    • Uso freqüente do terminal (o/).
    •  Simpatia pelo Macbook (não consigo me imaginar utilizando outra máquina ou qualquer outro SO que não seja baseado no kernel Unix).
    • Testes (Um alô para Flávia Missi (@flaviamissi) e por todo o legado de preocupações com testes que ela deixou enquanto estava no time).
    • Participações em coding dojos.
    • Pão Caseiro (via @m3nd3s).
    • A comunicação diária usando a língua inglesa por conta do nosso parceiro Petros (Grego Belezidade!) me deixa muito motivado.
    • Essa equipe é fo**!
    • Existe empresa que se esforça para cuidar do seu funcionário, sem balelas ou merchanda gratuito.

    São inúmeras, eu não listei todas. Entretanto, todas elas têm mudado aos poucos minha visão como desenvolvedor, profissional e sim, é possível, como ser humano.

    O Dojo.

    Digamos que o conceito de coding dojo seja, além de ser um desafio para programadores, é também se divertir, e, “através de uma metodologia pragmática, melhorar suas habilidades de programação e de trabalho em grupo”.

    Pois é, pode aparentar irrisório o que vou falar, mas nem só de vitórias vivemos.. E as minhas últimas experiências com dojo têm sido frustrantes quanto ao meu desempenho pessoal, mas o dojo em si está sendo uma experiência sensacional e desafiadora.

    Falando sobre a pseudo frustração, se você conhece alguém que nunca tenha tido um deslize, com certeza essa pessoa não é humana. Erros são inerentes à natureza (e não só a nossa, acredite), a única diferença é de como enfrentamos.

    Só fui dar conta ultimamente , pois estava codando de maneira afobada e ansiosa por resultados instantâneos. E a minha ficha caiu de verdade quando eu congelei em um dojo com amigos na empresa. Eu poderia descrever inúmeros fatores que contribuíram para esse infortúnio, falar que sou “iniciante” e afobado ao mesmo tempo contaria como 80% da causa (haha :P ), certo? Errado, há motivos para se importar por tão pouco!? Conclusão que só cheguei com ajuda de amigos na empresa e pessoas mais próximas fora dela.

    É óbvio que nesse post não vou postar sobre as soluções que vou tomar daqui para frente, pois estou buscando-as, mas ao contrário do que até mesmo eu esperava, ao me deparar com uma derrapada dessas tive uma vontade ainda maior de aprender mais e mais.

    O Código e o Caminho do Guerreiro.

    Depois dessas lamúrias sobre o dojo.. Um desafio eu enfrentar escolhi (Ahhh Yoda!!).

    Acostumado a acompanhar os livros e viciado a não praticar com exemplos mais , digamos assim, “relevantes”, resolvi tomar uma iniciativa mais aprimorada (é claro que vai depender do seu ponto de vista e experiência).

    Escolhi um problema de um dojo (http://dojopuzzles.com/problemas/exibe/jokenpo/) como referência e resolvi praticá-lo “sozinho” na hora do meu almoço, sem seguir as regras do dojo.

    OBS: Sozinho?! Oi?! Seria uma blasfêmia dizer que fiz um dojo sozinho, não faz sentido, mas vocês entenderam! :)

    Para acessar o repositório git com a resolução: http://www.github.com/urieljuliatti/ruby-challenges

    Todo e qualquer feedback será bem vindo! Pode descer a lenha também, eu aceitarei o desafio :)


  3. Tipo de Dados e Objetos em Ruby – Objetos

    September 16, 2011 by urieljuliatti

    Provavelmente essa cobertura será uma das maiores até então, pois tratarei de explicar os Objetos em ruby. Apesar de extensa, ela é essencial para se entender ruby. Pesquisei algumas referências na internet, mas a maior parte delas será a do livro que estou acompanhando: The Ruby Programming Language, com um foco direcionado ao Ruby 1.9.x .

    Inicialmente, o ruby é uma linguagem quase toda orientada a objetos, eu disse “quase” porque existem uns que dizem que não, outros dizem que sim, a discussão é bem longa. Todavia, em ruby todos os valores são objetos e não há uma distinção entre valores primitivos e objetos, como acontece em outras linguagens. Todos os objetos herdam da classe Object e compartilham entre si métodos definidos por essa classe.

    Não.
    Não vou ensinar orientação a objetos. Para ler esse artigo, presume-se que já entenda os conceitos básicos da orientação a objetos.

    Bora lá?

    Referências a objetos.
    A classe Object define dois métodos muito parecidos para copiar objetos.
    Quando trabalhamos com objetos em ruby, estamos nada mais nada a menos do que trabalhando com a sua referência, não o objeto em si.

    Nada melhor do que um código para visualizar o que acontece:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
    ruby-1.9.2-p136 :090 > s = "Ruby"
     => "Ruby"
    ruby-1.9.2-p136 :091 > t = s
     => "Ruby"
    ruby-1.9.2-p136 :092 > t[-1] = ""
     => ""
    ruby-1.9.2-p136 :093 > print s
    Rub => nil
    ruby-1.9.2-p136 :094 > t = "Java"
     => "Java"
    ruby-1.9.2-p136 :095 > print s,t
    RubJava => nil
    ruby-1.9.2-p136 :096 >
    ruby-1.9.2-p136 :090 > s = "Ruby"
     => "Ruby"
    ruby-1.9.2-p136 :091 > t = s
     => "Ruby"
    ruby-1.9.2-p136 :092 > t[-1] = ""
     => ""
    ruby-1.9.2-p136 :093 > print s
    Rub => nil
    ruby-1.9.2-p136 :094 > t = "Java"
     => "Java"
    ruby-1.9.2-p136 :095 > print s,t
    RubJava => nil
    ruby-1.9.2-p136 :096 >

    Na ordem, criamos um objeto do tipo String e guardamos uma referência para ele em s. Em seguida, copiamos a mesma referência para o t, onde s e t agora estão fazendo uma referência para o mesmo objeto.
    Na terceira linha nós modificamos o objeto em que a referência está guardada em t e mandamos printá-lo na linha seguida, retornando modificado.
    Na penúltima linha, referenciamos para um novo objeto (s), diferente de t.
    E por fim, na última linha printamos os dois objetos.

    Nota interessante: Engraçado é que se você está acostumado com C ou C++, fatalmente pensará que estamos lidando diretamente com ponteiros. Ô, ô! Engana-se quem pensa, pois ruby não permite você usar ponteiros para manipulação , aritimética e desreferenciação, como alguns já devem ter visto. As referências em ruby são implícitas na implementação, completamante abstraídas.

    Quando passamos um objeto para um método uma referência ao objeto é passada, não o objeto em si e nem mesmo uma referência para a referência. A maneira mais segura de dizer é que os argumentos são passados por valor.

    Tempo de vida do objeto.
    Para dar início ao ciclo de vida de um objeto em Ruby necessitamos de um método chamado “new” existente na classe Class. Ele aloca memória para o novo objeto e então inicializa seu estado como vazio ao chamar um outro método “initialize”. Como padrão, boa parte das classes possuem um inicializador para executar qualquer tipo de inicialização (caso necessário) para as instâncias.

    Os objetos em ruby não precisam ser explicitamente desalocados, assim como é feito em C ou C++ onde precisamos executar um free() para desalocar. O ruby usa uma técnica já conhecida, a de garbage collection, para destruir automaticamente objetos que não estão sendo necessários. Um objeto se torna candidato do garbage quando ele está “inalcançável” , isto é, quando não existem referências para aquele objeto a não ser de outros objetos “inalcançáveis”.

    Obs1: Aqueles que desejam um aprofundamento sobre o assunto, existem alguns artigos na Ruby Inside sobre o GC, tal como esse aqui, por exemplo.

    Obs2: Apesar de usar o GC , isto não significa que problemas com alocação de memória não existam em Ruby.

    A classe Object e o tipo Object.

    Há várias maneiras de determinar uma classe de um objeto em Ruby. A forma mais simplista é acrescentar um .class no objeto para o interpretador devolver a classe.
    Ex:

    1
    2
    3
    4
    
    ruby-1.9.2-p136 :022 > objeto = "teste"
     => "teste"
    ruby-1.9.2-p136 :023 > objeto.class
     => String
    ruby-1.9.2-p136 :022 > objeto = "teste"
     => "teste"
    ruby-1.9.2-p136 :023 > objeto.class
     => String

    A não ser que você queira saber a hierarquia de um objeto, você pode navegar pelas superclasses, assim:

    1
    2
    3
    4
    5
    6
    
    ruby-1.9.2-p136 :024 > o.class.superclass
     => Object
    ruby-1.9.2-p136 :025 > o.class.superclass.superclass
     => BasicObject
    ruby-1.9.2-p136 :026 > o.class.superclass.superclass.superclass
     => nil
    ruby-1.9.2-p136 :024 > o.class.superclass
     => Object
    ruby-1.9.2-p136 :025 > o.class.superclass.superclass
     => BasicObject
    ruby-1.9.2-p136 :026 > o.class.superclass.superclass.superclass
     => nil

    Obs: No 1.9, a classe Object não é a classe raiz dos objetos, mas sim a BasicObject (Veja mais na documentação).

    Há várias maneiras de saber se tal objeto pertence a uma determinada classe, desde comparativos diretos (objeto.class == String) até o mais elegante de todos, o objeto.instance_of?String.

    Geralmente, quando testamos uma classe de um objeto, também desejamos saber se o objeto é uma instância de alguma subclasse. Para fazer essa verificação, usa-se o is_a? ou kind_of?. Ex:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    
    ruby-1.9.2-p136 :027 > object = 1
     => 1
    ruby-1.9.2-p136 :028 > object.instance_of?Fixnum
     => true
    ruby-1.9.2-p136 :029 > object.instance_of?Numeric
     => false
    ruby-1.9.2-p136 :030 > object.is_a?Fixnum
     => true
    ruby-1.9.2-p136 :031 > object.is_a?Integer
     => true
    ruby-1.9.2-p136 :032 > object.is_a?Numeric
     => true
    ruby-1.9.2-p136 :033 > object.is_a?Comparable
     => true
    ruby-1.9.2-p136 :034 > object.is_a?Object
     => true
    ruby-1.9.2-p136 :027 > object = 1
     => 1
    ruby-1.9.2-p136 :028 > object.instance_of?Fixnum
     => true
    ruby-1.9.2-p136 :029 > object.instance_of?Numeric
     => false
    ruby-1.9.2-p136 :030 > object.is_a?Fixnum
     => true
    ruby-1.9.2-p136 :031 > object.is_a?Integer
     => true
    ruby-1.9.2-p136 :032 > object.is_a?Numeric
     => true
    ruby-1.9.2-p136 :033 > object.is_a?Comparable
     => true
    ruby-1.9.2-p136 :034 > object.is_a?Object
     => true

    Perceba que na situação em que object.instance_of?Numeric retorna falso, ele não chega a herança. Porém, se você faz o comparativo com object.is_a?Numeric, ele retorna true.

    Cada objeto tem uma classe bem definida em Ruby, tal classe nunca muda durante o ciclo de vida de um objeto. Porém, um tipo de objeto é mais flexível, pois está relacionado a sua classe, mas a classe é apenas uma parte de um tipo de objeto. Quando falo sobre tipos de objetos, estou me referenciando a um conjunto de comportamentos que caracterizam o objeto.

    Algo importante para lembrar ao programar ruby é o fato de que não se dá tanta importância as classes de um objeto, queremos apenas saber se podemos chamar um método dela. Considere,por exemplo, o operador “<<”. Arrays, strings, arquivos e outras classes responsáveis por entrada/saída definem genericamente esse operador como um anexador. Para esclarecer, não damos importância aos argumentos passados para a classe, sabemos que pode ser anexado usando o operador <<. Até podemos testar se a classe responde a esse operador utilizando o respond_to?

    1
    2
    3
    
    ruby-1.9.2-p136 :004 > object = "Teste"
     => "Teste"
    ruby-1.9.2-p136 :005 > object.respond_to? :"< true
    ruby-1.9.2-p136 :004 > object = "Teste"
     => "Teste"
    ruby-1.9.2-p136 :005 > object.respond_to? :"< true

    Aí sim, estamos testando apenas se o operador pode ser chamado na classe String, não os parâmetros para o método.

    Semelhanças entre os objetos
    O ruby fornece várias maneiras de comparar objetos pela sua semelhança e é importante saber como alguns métodos funcionam.

    O método equal?

    O método equal? (Fornecido pela classe Object) é responsável por verificar se dois valores referem-se exatamente ao mesmo objeto.

    1
    2
    3
    4
    5
    6
    7
    8
    
    ruby-1.9.2-p136 :006 > a = "Ruby"
     => "Ruby"
    ruby-1.9.2-p136 :007 > b = c = "Ruby"
     => "Ruby"
    ruby-1.9.2-p136 :008 > a.equal?(b)
     => false
    ruby-1.9.2-p136 :009 > b.equal?(c)
     => true
    ruby-1.9.2-p136 :006 > a = "Ruby"
     => "Ruby"
    ruby-1.9.2-p136 :007 > b = c = "Ruby"
     => "Ruby"
    ruby-1.9.2-p136 :008 > a.equal?(b)
     => false
    ruby-1.9.2-p136 :009 > b.equal?(c)
     => true

    a e b são objetos diferentes, mas b e c possuem referências para o mesmo objeto.

    Outra maneira para realizar a mesma operação é verificar se o object_id é igual.

    1
    2
    3
    4
    
    ruby-1.9.2-p136 :014 > a.object_id == b.object_id
     => false
    ruby-1.9.2-p136 :015 > b.object_id == c.object_id
     => true
    ruby-1.9.2-p136 :014 > a.object_id == b.object_id
     => false
    ruby-1.9.2-p136 :015 > b.object_id == c.object_id
     => true

    Conversão de Objetos
    Várias classes no ruby definem métodos que retornam uma representação do objeto como um valor de uma classe distinta. O método to_s, por exemplo, é utilizado para obter uma representação em String de um objeto.

    Algumas conversões são explícitas: to_s (String), to_i (Integer), to_f (Float), to_a (Array). Outras são implícitas, em alguns casos quando a classe possui características marcantes de outra classe.

    Copiando Objetos
    A classe Object possui dois métodos bastante parecidos para lidar com cópias de objetos. Tanto o clone ou dup retorna uma cópia superficial do objeto sobre o qual eles são chamados. Se o objeto copiado possuir um estado interno que se referencie a outros objetos, apenas as referências do objeto serão copiadas, não os próprios objetos referenciados.

    Se o objeto que está sendo copiado em questão define um método initialize_copy, clone e dup alocam uma instância nova e vazia da classe e chamam o initialize_copy nessa instância vazia. O objeto em questão a ser copiado é passado como um argumento e essa “cópia do construtor” pode inicializar a cópia como ela desejar.. Por exemplo, o método initialize_copy poderia copiar recursivamente os dados internos de um objeto de modo a que o objeto resultante não seja uma simples cópia superficial do original.

    As classes também podem sobrescrever diretamente o método clone e dup para resultarem qualquer cópia que desejarem.

    Existem duas diferenças importantes entre os métodos clone e dup que são definidos pela classe Object. Em primeiro lugar, clone copia tanto o estado freeze e o tainted (definido em primeira instância) de um objeto, enquanto que dup apenas copia o estado tainted; chamando dup em um objeto freeze retorna uma cópia sem o estado freeze. Em segundo lugar, clone copia todos os métodos singleton do objeto, enquanto o dup não.

    Empacotando (serializando) objetos
    Você pode salvar um estado de um objeto ao passá-lo como parâmetro para um método de classe Marshal.dump. Caso você passe um objeto de Entrada/Saída como segundo argumento, Marshal.dump determina o estado do objeto (e recursivamente, qualquer objeto que esteja sendo referenciado), caso contrário retorna um estado codificado como String binária.

    Para recuperar um objeto serializado, passe uma string ou um fluxo de entrada/saída contendo o objeto para o método Marshal.load.

    Serializar um objeto é um jeito bacana de guardar o estado para um uso futuro, além do que esses métodos podem ser utilizados para fornecer um formato automático de arquivos para apps em Ruby.

    Congelando Objetos
    Qualquer objeto pode ser “congelado” ao chamar o método freeze. Um objeto “congelado” é considerádo imutável – isto é, nenhum de seus estados podem ser modificados e a tentativa de chamar qualquer método que seja capaz de modificar será falha.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    
    ruby-1.9.2-p136 :001 > s = "ice"
     => "ice"
    ruby-1.9.2-p136 :002 > s.freeze
     => "ice"
    ruby-1.9.2-p136 :003 > s.frozen?
     => true
    ruby-1.9.2-p136 :004 > s.upcase!
    RuntimeError: can't modify frozen string
        from (irb):4:in `upcase!'
        from (irb):4
        from /Users/urieljuliatti/.rvm/gems/ruby-1.9.2-p136@rails-3.0.1/gems/railties-3.0.1/lib/rails/commands/console.rb:44:in `start'
        from /Users/urieljuliatti/.rvm/gems/ruby-1.9.2-p136@rails-3.0.1/gems/railties-3.0.1/lib/rails/commands/console.rb:8:in `start'
        from /Users/urieljuliatti/.rvm/gems/ruby-1.9.2-p136@rails-3.0.1/gems/railties-3.0.1/lib/rails/commands.rb:23:in `'
        from script/rails:6:in `require'
        from script/rails:6:in `'
    ruby-1.9.2-p136 :005 > s[0] = "ni"
    RuntimeError: can't modify frozen string
        from (irb):5:in `[]='
        from (irb):5
        from /Users/urieljuliatti/.rvm/gems/ruby-1.9.2-p136@rails-3.0.1/gems/railties-3.0.1/lib/rails/commands/console.rb:44:in `start'
        from /Users/urieljuliatti/.rvm/gems/ruby-1.9.2-p136@rails-3.0.1/gems/railties-3.0.1/lib/rails/commands/console.rb:8:in `start'
        from /Users/urieljuliatti/.rvm/gems/ruby-1.9.2-p136@rails-3.0.1/gems/railties-3.0.1/lib/rails/commands.rb:23:in `'
        from script/rails:6:in `require'
        from script/rails:6:in `'
    ruby-1.9.2-p136 :006 >
    ruby-1.9.2-p136 :001 > s = "ice"
     => "ice"
    ruby-1.9.2-p136 :002 > s.freeze
     => "ice"
    ruby-1.9.2-p136 :003 > s.frozen?
     => true
    ruby-1.9.2-p136 :004 > s.upcase!
    RuntimeError: can't modify frozen string
    	from (irb):4:in `upcase!'
    	from (irb):4
    	from /Users/urieljuliatti/.rvm/gems/ruby-1.9.2-p136@rails-3.0.1/gems/railties-3.0.1/lib/rails/commands/console.rb:44:in `start'
    	from /Users/urieljuliatti/.rvm/gems/ruby-1.9.2-p136@rails-3.0.1/gems/railties-3.0.1/lib/rails/commands/console.rb:8:in `start'
    	from /Users/urieljuliatti/.rvm/gems/ruby-1.9.2-p136@rails-3.0.1/gems/railties-3.0.1/lib/rails/commands.rb:23:in `'
    	from script/rails:6:in `require'
    	from script/rails:6:in `'
    ruby-1.9.2-p136 :005 > s[0] = "ni"
    RuntimeError: can't modify frozen string
    	from (irb):5:in `[]='
    	from (irb):5
    	from /Users/urieljuliatti/.rvm/gems/ruby-1.9.2-p136@rails-3.0.1/gems/railties-3.0.1/lib/rails/commands/console.rb:44:in `start'
    	from /Users/urieljuliatti/.rvm/gems/ruby-1.9.2-p136@rails-3.0.1/gems/railties-3.0.1/lib/rails/commands/console.rb:8:in `start'
    	from /Users/urieljuliatti/.rvm/gems/ruby-1.9.2-p136@rails-3.0.1/gems/railties-3.0.1/lib/rails/commands.rb:23:in `'
    	from script/rails:6:in `require'
    	from script/rails:6:in `'
    ruby-1.9.2-p136 :006 >

    Objetos Estranhos ou Duvidosos.

    *Tentei encontrar alguma tradução eficiente para Tainted Objects, sem sucesso.

    Geralmente, as aplicações web devem manter o controle de dados derivados da entrada de um usuário não confiável para evitar ataques de injeção SQL e tasks de segurança semelhantes.

    O Ruby fornece uma solução simples para esse problema: Qualquer objeto pode ser marcado como “duvidoso”, chamando-o pelo método taint. E isso gera uma reação em cadeia, pois a partir do momento que um objeto é setado como taint, qualquer objeto derivado será taint também.

    Segue o exemplo para analisarmos o que acontece quando setamos um objeto como taint:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    ruby-1.9.2-p136 :001 > s = "untrusted"
    => "untrusted"
    ruby-1.9.2-p136 :002 > s.taint
    => "untrusted"
    ruby-1.9.2-p136 :003 > s.tainted?
    => true
    ruby-1.9.2-p136 :004 > s.upcase.tainted?
    => true
    ruby-1.9.2-p136 :005 > s[3,4].tainted?
    => true
    ruby-1.9.2-p136 :001 > s = "untrusted"
    => "untrusted"
    ruby-1.9.2-p136 :002 > s.taint
    => "untrusted"
    ruby-1.9.2-p136 :003 > s.tainted?
    => true
    ruby-1.9.2-p136 :004 > s.upcase.tainted?
    => true
    ruby-1.9.2-p136 :005 > s[3,4].tainted?
    => true

    É uma abordagem que será interessante ter uma cobertura específica, pois envolve questões de segurança e de como o Ruby lida com isso. Portanto, resumi apenas demonstrá-los do poder que a linguagem possui, pois infelizmente não terá como cobrir todo o tema. Futuramente pretendo estudar alguns critérios específicos sobre essa abordagem do Ruby :)

    Por fim, gostaria de informar que a próxima abordagem será sobre Classes e Módulos.

    Bons estudos a todos!

    Referências:

    http://www.devarticles.com/c/a/Ruby-on-Rails/Ruby-Classes-and-Objects/1/

    http://rubylearning.com/blog/2010/11/03/do-you-understand-rubys-objects-messages-and-blocks/

    http://www.hokstad.com/ruby-object-model.html

    http://www.linuxtopia.org/online_books/programming_books/ruby_tutorial/Locking_Ruby_in_the_Safe_Tainted_Objects.html


  4. Tipo de Dados e Objetos em Ruby – Symbols

    August 23, 2011 by urieljuliatti

    Fala pessoa, beleza?!

    Hoje o assunto é Symbol e pelo o que andei lendo na internet, somado ao livro que estou acompanhando, ele é um enorme enigma para vários programadores. Se você experimentar procurar na internet sobre o assunto, vai encontrar diversas discussões e diversas opiniões sobre a relevância do uso de Symbol.

    Funcionamento: Em uma implementação comum , o interpretador do Ruby mantém uma tabela da classe Symbol que reserva os nomes de todas as classes, métodos e variáveis que se conhece. Isto permite que o interpretador evite comparações exageradas na cadeia de Strings, ele tenta sempre referir a nomes de métodos por sua posição nesta tabela de símbolos.

    O engraçado do Symbol é a forma de inicialização ou instanciamento da própria classe:

    1
    
     :o la_symbol
     :o la_symbol

    Normalmente, para inicializar uma classe usa-se a chamada “new” procedida pelo método ‘initialize’ definido dentro da classe.

    Lendo um artigo do Akita, além de ter uma cobertura mais abrangente do tópico que estou lendo no livro do Matz, descobri que o método initialize da classe Symbol é privado, isto é, ele força todo símbolo a ser instanciado com a notação de dois-pontos.

    Um dos motivos dos símbolos existirem é que se toda hora instanciarmos uma String, estaremos criando vários objetos para uma mesma causa onde o problema poderia ser resolvido por constantes. Vamos visualizar como isso fica?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    <pre>ruby-1.9.2-p136 :002 > "string".object_id
    => 2154639100
    ruby-1.9.2-p136 :003 > "string".object_id
    => 2154627240
    ruby-1.9.2-p136 :004 > "string".object_id
    => 2154611460 # veja quantos ids diferentes foram criados..
    ruby-1.9.2-p136 :005 > :string.object_id
    => 108168
    ruby-1.9.2-p136 :006 > :string.object_id
    => 108168 # percebam o mesmo id para os simbolos
    <pre>ruby-1.9.2-p136 :002 > "string".object_id
    => 2154639100
    ruby-1.9.2-p136 :003 > "string".object_id
    => 2154627240
    ruby-1.9.2-p136 :004 > "string".object_id
    => 2154611460 # veja quantos ids diferentes foram criados..
    ruby-1.9.2-p136 :005 > :string.object_id
    => 108168
    ruby-1.9.2-p136 :006 > :string.object_id
    => 108168 # percebam o mesmo id para os simbolos

    Essa solução já existe em outras linguagens, porém no Ruby, ao invés de declarar uma constante

    1
    
     CATEGORY = "category"
     CATEGORY = "category"

    e depois usá-la

    1
    
     belongs_to CATEGORY 
     belongs_to CATEGORY 

    o Ruby encontrou uma maneira mais elegante de tratar esse caso, especificamente sobre a sua sintaxe.

    Para concluir: O principal objetivo dos símbolos é “ser tão eficiente em consumo de memória quanto constantes mas tão agradáveis aos olhos como strings” (via @akitaonrails).

    Existem mais coisas sobre Symbols por aí na web, o que encontrei foi meio confuso

    Por fim, nosso próximo post será sobre Objetos, que será bem abrangente!


  5. [ Quick Post ] – Configurando ambiente para RSpec2 no Rails 3

    August 18, 2011 by urieljuliatti

    Fala pessoal, beleza?!

    Hoje tive que lidar com uma configuração de ambiente de testes com RSpec2, pois estou começando no mundo dos testes e queria aplicar alguns conceitos no meu blog que está sendo feito do zero em Rails. O objetivo desse quick post é apenas configurar o ambiente, não vou falar dos testes em si.

    Uma vez com a sua aplicação já criada, no seu Gemfile, adicione as linhas:

    1
    2
    3
    
    group :development, :test do
      gem 'rspec-rails'
    end
    group :development, :test do
      gem 'rspec-rails'
    end

    Agora rode o bundle no terminal para instalar a gem que acabamos de associar ao Gemfile:

    1
    
    bundle install
    bundle install

    E para finalizar, precisamos rodar o generator do RSpec. Ele será responsável por criar alguns arquivos que falarei em seguida. Digite no terminal:

    1
    
    rails generate rspec:install
    rails generate rspec:install

    Como havia dito, esse comando vai gerar alguns arquivos, tais como:

    - .rspec – Um arquivo de configuração onde podemos guardar algumas linhas de comando extras para se comunicar com a ferramenta rspec.

    - spec – Um diretório que irá conter todos os arquivos de models, controllers, views, aceitação e outros tipos de arquivos spec para a sua aplicação.

    - spec/spec_helper.rb – Um helper que será carregado a cada chamada do spec. Ele prepara todo o ambiente de teste, contendo a maioria das configurações do spec, arquivos de ajuda e etc.

    Agora toda vez que você criar um Model ou um Controller via rails generator ou scaffolding, ele vai gerar também um arquivo para o spec.

    1
    2
    3
    4
    5
    6
    
    $ rails g model teste
          invoke  active_record
          create    db/migrate/20110817125934_create_testes.rb
          create    app/models/teste.rb
          invoke    rspec
          create      spec/models/teste_spec.rb
    $ rails g model teste
          invoke  active_record
          create    db/migrate/20110817125934_create_testes.rb
          create    app/models/teste.rb
          invoke    rspec
          create      spec/models/teste_spec.rb

    Após compor o teste, para rodar junto à sua aplicação faça um rake spec:models (no nosso do teste), rake spec para integração, rake spec:views para views e assim vai :)

    É isso aí!

    Abraços.