RSS Feed
  1. Tipo de Dados e Objetos em Ruby – Ranges

    August 17, 2011 by urieljuliatti

    Um objeto do tipo Range representa valores entre um valor inicial e um valor final, retornando uma faixa/intervalo de valores. São escritos geralmente com dois ou três pontos entre esses valores. Se optarmos por usar dois pontos, o intervalo é inclusivo, isto é, o valor final faz parte da faixa retornada. E , por fim, se desejar utilizar dois pontos, a faixa será exclusiva e o valor final não fará parte da faixa retornada.

    Para exemplicar o que acabei de escrever, nada mais do que a prática:

    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
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    
    ruby-1.9.2-p136 :015 > my_age = 1985..2011
    => 1985..2011
    ruby-1.9.2-p136 :016 > my_age.each do |year|
    ruby-1.9.2-p136 :017 >     puts year
    ruby-1.9.2-p136 :018?>   end
    1985
    1986
    1987
    1988
    1989
    1990
    1991
    1992
    1993
    1994
    1995
    1996
    1997
    1998
    1999
    2000
    2001
    2002
    2003
    2004
    2005
    2006
    2007
    2008
    2009
    2010
    2011
    => 1985..2011
    ruby-1.9.2-p136 :019 > my_age = 1985...2011
    => 1985...2011
    ruby-1.9.2-p136 :020 > my_age.each do |year|
    ruby-1.9.2-p136 :021 >     puts year
    ruby-1.9.2-p136 :022?>   end
    1985
    1986
    1987
    1988
    1989
    1990
    1991
    1992
    1993
    1994
    1995
    1996
    1997
    1998
    1999
    2000
    2001
    2002
    2003
    2004
    2005
    2006
    2007
    2008
    2009
    2010
    => 1985...2011
    ruby-1.9.2-p136 :015 > my_age = 1985..2011
    => 1985..2011
    ruby-1.9.2-p136 :016 > my_age.each do |year|
    ruby-1.9.2-p136 :017 >     puts year
    ruby-1.9.2-p136 :018?>   end
    1985
    1986
    1987
    1988
    1989
    1990
    1991
    1992
    1993
    1994
    1995
    1996
    1997
    1998
    1999
    2000
    2001
    2002
    2003
    2004
    2005
    2006
    2007
    2008
    2009
    2010
    2011
    => 1985..2011
    ruby-1.9.2-p136 :019 > my_age = 1985...2011
    => 1985...2011
    ruby-1.9.2-p136 :020 > my_age.each do |year|
    ruby-1.9.2-p136 :021 >     puts year
    ruby-1.9.2-p136 :022?>   end
    1985
    1986
    1987
    1988
    1989
    1990
    1991
    1992
    1993
    1994
    1995
    1996
    1997
    1998
    1999
    2000
    2001
    2002
    2003
    2004
    2005
    2006
    2007
    2008
    2009
    2010
    => 1985...2011

    -> Explico o que aconteceu.

    É importante observar que a principal proposta de uma Range é a comparação, sendo capaz de identificar se um valor está dentro ou fora da faixa.

    1
    2
    3
    4
    5
    6
    7
    8
    
    ruby-1.9.2-p136 :014 > (1..10) === 10
    => true
    ruby-1.9.2-p136 :016 > (1...10) === 10
    => false
    ruby-1.9.2-p136 :024 > (1...10).include?(5)
    => true
    ruby-1.9.2-p136 :025 > (1...10).include?(10)
    => false
    ruby-1.9.2-p136 :014 > (1..10) === 10
    => true
    ruby-1.9.2-p136 :016 > (1...10) === 10
    => false
    ruby-1.9.2-p136 :024 > (1...10).include?(5)
    => true
    ruby-1.9.2-p136 :025 > (1...10).include?(10)
    => false

    Assume-se que na primeira linha, 10 está dentro da faixa de valores. Importante destacar que na segunda comparação
    o 10 não se encontra mais nessa faixa de valores, pois a range foi declarada de forma exclusiva.

    Uma outra grande observação é a iteração, como no exemplo abaixo, a classe dos desfechos de uma série define um método succ (para o sucessor), você verá um conjunto discreto de intervalos que podem ser iterados com each, step e alguns métodos da classe Enumerable.

    1
    2
    3
    4
    5
    6
    7
    8
    
    ruby-1.9.2-p136 :001 > r = 'a'..'c'
    => "a".."c"
    ruby-1.9.2-p136 :004 > r.each {|l| print "[#{l}]"}
    [a][b][c] => "a".."c"
    ruby-1.9.2-p136 :005 > r.step(2) { |l| print "[#{l}]"}
    [a][c] => "a".."c"
    ruby-1.9.2-p136 :006 > r.to_a
    => ["a", "b", "c"]
    ruby-1.9.2-p136 :001 > r = 'a'..'c'
    => "a".."c"
    ruby-1.9.2-p136 :004 > r.each {|l| print "[#{l}]"}
    [a][b][c] => "a".."c"
    ruby-1.9.2-p136 :005 > r.step(2) { |l| print "[#{l}]"}
    [a][c] => "a".."c"
    ruby-1.9.2-p136 :006 > r.to_a
    => ["a", "b", "c"]

    A razão por esse código funcionar dessa maneira é que a classe String possui um método succ onde ‘a’.succ é igual ‘b’ e
    ‘b’.succ é igual a ‘c’.

    Testando se existem membros em uma Range.

    A classe Range possui métodos para determinar se um valor arbitrário é um membro de uma faixa (range). Existem duas formas de definir uma afiliação para as ranges, contínua ou discreta. A contínua seria algo equivalente a:

    1
    2
    3
    
    begin <= x <= end
     
    begin <= x < end # O que seria 1..3, por exemplo, com três pontos.
    begin <= x <= end
    
    begin <= x < end # O que seria 1..3, por exemplo, com três pontos.

    Onde todos os valores finais dos intervalos devem implementar o operador <=>, portanto essa definição de filiação funciona para qualquer objeto Range e não necessita de valores finais para implementar o método succ .

    A segunda forma de filiação, a discreta, necessita do succ. Ela lida com a classe Range como um conjunto que inclui o begin, begin.succ, begin.succ.succ e assim por diante. Por definição, uma range afiliada é um conjunto, onde o valor x é incluído em uma range apenas e somente se um valor é retornado por alguma das chamadas do método succ. Essa metodologia é muito mais custosa do que a contínua.

    O exemplo abaixo exemplifica um teste com a forma discreta:

    1
    2
    3
    4
    5
    6
    7
    8
    
    ruby-1.9.2-p136 :006 > r = 0...100
    => 0...100
    ruby-1.9.2-p136 :007 > r.member?50
    => true
    ruby-1.9.2-p136 :008 > r.include?100
    => false
    ruby-1.9.2-p136 :009 > r.include?99.9
    => true
    ruby-1.9.2-p136 :006 > r = 0...100
    => 0...100
    ruby-1.9.2-p136 :007 > r.member?50
    => true
    ruby-1.9.2-p136 :008 > r.include?100
    => false
    ruby-1.9.2-p136 :009 > r.include?99.9
    => true

    Acredito que o artigo foi bem resumido, com a finalidade de que vocês, assim como eu, que estão estudando o Ruby possam encontrar mais informações a partir deste ou até mesmo trazer mais informações para este artigo a partir de outros!

    A próxima cobertura será feita sobre os Symbols.

    Portanto, nos vemos até o próximo post!

    Abraços a todos!


  2. Tipo de Dados e Objetos em Ruby – Hashes

    August 2, 2011 by urieljuliatti

    Hashes

    Hash é uma estrutura de dados que possui um conjunto de objetos conhecidos como “keys”, onde existe um valor associado para cada dessas keys. Uma outra definição para as hashes, é que elas também são conhecidas como mapas, pois mapeiam cada key para um determinado valor. É comum serem chamadas de arrays associativas, pois como elas associam valores para cada uma das chaves, pode ser pensado como matrizes em que o índice da matriz pode ser qualquer objeto ao invés de um inteiro:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
    ruby-1.9.2-p136 :080 > numbers = Hash.new
    => {}
     
    ruby-1.9.2-p136 :082 > numbers["one"] = 1
    => 1
    ruby-1.9.2-p136 :083 > numbers["two"] = 2
    => 2
    ruby-1.9.2-p136 :084 > numbers["three"] = 3
    => 3
    ruby-1.9.2-p136 :085 > sum = numbers["one"] + numbers["two"] + numbers["three"]
    => 6
    ruby-1.9.2-p136 :086 > numbers
    => {"one"=>1, "two"=>2, "three"=>3}
    ruby-1.9.2-p136 :080 > numbers = Hash.new
    => {}
    
    ruby-1.9.2-p136 :082 > numbers["one"] = 1
    => 1
    ruby-1.9.2-p136 :083 > numbers["two"] = 2
    => 2
    ruby-1.9.2-p136 :084 > numbers["three"] = 3
    => 3
    ruby-1.9.2-p136 :085 > sum = numbers["one"] + numbers["two"] + numbers["three"]
    => 6
    ruby-1.9.2-p136 :086 > numbers
    => {"one"=>1, "two"=>2, "three"=>3}

    Com esse exemplo muito simples, fica prático e interessante observar a flexibilidade das Hashes.

    Hash Literais

    A representação de uma hash literal pode ser feita através de um ou mais pares de keys/valores associados e separados por vírgulas dentro de chaves, onde cada par (keys e valores) é separado por uma seta. Nós já fizemos essa representação acima, que foi justamente essa:

    1
    2
    
    ruby-1.9.2-p136 :086 > numbers
    => {"one"=>1, "two"=>2, "three"=>3}
    ruby-1.9.2-p136 :086 > numbers
    => {"one"=>1, "two"=>2, "three"=>3}

    Geralmente, os objetos do tipo Symbol são mais eficientes com as hashes do que as strings:

    1
    
    numbers = { : one => 1, : two => 2, : three => 3}
    numbers = { : one => 1, : two => 2, : three => 3}

    E no Ruby 1.9 existe uma maneira de simplificar a sintaxe escrevendo-a da seguinte forma:

    1
    2
    
    ruby-1.9.2-p136 :089 > numbers = { one: 1, two: 2, three: 3}
    => { :o ne=>1, :two=>2, :three=>3}
    ruby-1.9.2-p136 :089 > numbers = { one: 1, two: 2, three: 3}
    => {:one=>1, :two=>2, :three=>3}

    No próximo post falarei sobre Ranges :)

    Abraços e até a próxima!


  3. Tipos de dados e Objetos em Ruby – Arrays

    July 27, 2011 by urieljuliatti

    Fala pessoal, tranquilo?

    Antes de tudo, gostaria de reforçar que a minha série de estudos sobre o Ruby cobre bastante o conceito básico da linguagem, tendo a premissa básica que o conteúdo é voltado para iniciantes, assim como eu. Em segundo lugar, quero agredecer a todo apoio recebido pelos meus colegas de trabalho e por outros amigos programadores . Agora vamos ao assunto técnico, né? :)

    Arrays

    No Ruby, o primeiro índice de uma array é zero, contendo métodos para retornar o tamanho da array (size e lenght). O último elemento de uma array em Ruby é -1. Os  índices negativos de uma array são contados de a partir do final da array, portanto o último elemento , como já dito anteriormente, pode ser acessado no indice de -1. Sendo assim, o segundo índice é -2 e assim por conseguinte.  Se você tiver uma  array com 5 índices, o -1 devolve o quinto e ultimo, -2 retorna o quarto item, etc.

    Por padrão, se acontecer um acesso a um elemento que esteja além do final da array ou antes do primeiro indíce o Ruby vai retornar nil sem gerar uma exceção.

    As arrays em Ruby se diferenciam por não serem tipadas, mas sim mutáveis. Os elementos da Array não precisam ser da mesma classe e eles podem ser modificados a qualquer momento. Além do mais, o tamanho das arrays é flexível, você pode adicionar elementos ao array a medida que obtiver necessidade.

    Alguns exemplos de arrays implementados:

    1
    2
    3
    
    [1, 2, 3] #  Uma array com 3 objetos da classe Fixnum
     
    [] # Uma array vazia que retorna 0
    [1, 2, 3] #  Uma array com 3 objetos da classe Fixnum
    
    [] # Uma array vazia que retorna 0

    Para criar uma array você pode utilizar Array.new , que também permite passagem de parâmetros em seu constructor.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    arrayVazia = Array.new # retorna um array vazio
     
    nils = Array.new(3) # [nil, nil, nil] -> Uma array nova com três elementos nil
     
    zeros = Array.new(4, 0) # [0,0,0,0] -> Uma array nova com quatros elementos zero
     
    arrayCopia = Array.new(nils) # faz uma copia do array “nils”
     
    arrayCounted = Array.new(3) { |i| i+1 } # [1,2,3] : 3 elementos vindos de um indice 1.
    arrayVazia = Array.new # retorna um array vazio
    
    nils = Array.new(3) # [nil, nil, nil] -> Uma array nova com três elementos nil
    
    zeros = Array.new(4, 0) # [0,0,0,0] -> Uma array nova com quatros elementos zero
    
    arrayCopia = Array.new(nils) # faz uma copia do array “nils”
    
    arrayCounted = Array.new(3) { |i| i+1 } # [1,2,3] : 3 elementos vindos de um indice 1.

    Para obter um valor de um element da array, use qualquer numero inteiro dentro dos []:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    
    a = [0, 1, 4, 9, 16]
     
    a[0] # Retorna zero
     
    a[-1] # retorna 16, que é o ultimo elemento
     
    a[-2] # retorna 9
     
    a[a.size-1] # uma outra abordagem para obter o ultimo
     
    a[-a.size] # outra forma de obter o primeiro element
     
    a[8] # retorna nil, pois nao existe tal indice
     
    a[-8] # retorna nil assim como o acima
    a = [0, 1, 4, 9, 16]
    
    a[0] # Retorna zero
    
    a[-1] # retorna 16, que é o ultimo elemento
    
    a[-2] # retorna 9
    
    a[a.size-1] # uma outra abordagem para obter o ultimo
    
    a[-a.size] # outra forma de obter o primeiro element
    
    a[8] # retorna nil, pois nao existe tal indice
    
    a[-8] # retorna nil assim como o acima

    Exceção: Nunca adicione algo antes do primeiro indice do array. Você obterá um erro:

    1
    2
    3
    
    => ruby-1.9.2-p136 :002 > a[-10] = 100
     
    => IndexError: index -10 too small for array; minimum: 0
    => ruby-1.9.2-p136 :002 > a[-10] = 100
    
    => IndexError: index -10 too small for array; minimum: 0

    Assim como as strings, as arrays também podem ser indexadas com dois inteiros (índice e o número de elementos). Em ambos os casos, a expressão retorna a subarray especificada:

    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
    26
    27
    
    ruby-1.9.2-p136 :004 > a = ('a'..'e').to_a
     
    -> ["a", "b", "c", "d", "e"]
     
    ruby-1.9.2-p136 :005 > a[0,0]
     
    -> []  # zero
     
    ruby-1.9.2-p136 :006 > a[1,1]
     
    => ["b"] # uma array de um elemento
     
    ruby-1.9.2-p136 :007 > a[-2,2]
     
    => ["d", "e"]  # os dois ultimos elementos da array
     
    ruby-1.9.2-p136 :008 > a[0..2]
     
    => ["a", "b", "c"] # os tres primeiros elementos
     
    ruby-1.9.2-p136 :009 > a[-2..-1]
     
    => ["d", "e"] # outra forma de acessar os dois ultimos elementos da array
     
    ruby-1.9.2-p136 :010 > a[0...-1]
     
    => ["a", "b", "c", "d"]  # todos menos o último
    ruby-1.9.2-p136 :004 > a = ('a'..'e').to_a
    
    -> ["a", "b", "c", "d", "e"]
    
    ruby-1.9.2-p136 :005 > a[0,0]
    
    -> []  # zero
    
    ruby-1.9.2-p136 :006 > a[1,1]
    
    => ["b"] # uma array de um elemento
    
    ruby-1.9.2-p136 :007 > a[-2,2]
    
    => ["d", "e"]  # os dois ultimos elementos da array
    
    ruby-1.9.2-p136 :008 > a[0..2]
    
    => ["a", "b", "c"] # os tres primeiros elementos
    
    ruby-1.9.2-p136 :009 > a[-2..-1]
    
    => ["d", "e"] # outra forma de acessar os dois ultimos elementos da array
    
    ruby-1.9.2-p136 :010 > a[0...-1]
    
    => ["a", "b", "c", "d"]  # todos menos o último

    Quando usadas a esquerda de uma atribuição, uma subarray pode ser substituída por elementos da array.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
    ruby-1.9.2-p136 :005 > a = ('a'..'e').to_a
     
    => ["a", "b", "c", "d", "e"]
     
    ruby-1.9.2-p136 :006 > a[0,2] = ['A', 'B']
     
    => ["A", "B"]
     
    ruby-1.9.2-p136 :006 > a[0..2] = []
     
    # deletar os elementos
     
    ruby-1.9.2-p136 :006 > a[-1,1] = [‘Z’] # Substitui o ultimo element por Z<strong></strong>
    ruby-1.9.2-p136 :005 > a = ('a'..'e').to_a
    
    => ["a", "b", "c", "d", "e"]
    
    ruby-1.9.2-p136 :006 > a[0,2] = ['A', 'B']
    
    => ["A", "B"]
    
    ruby-1.9.2-p136 :006 > a[0..2] = []
    
    # deletar os elementos
    
    ruby-1.9.2-p136 :006 > a[-1,1] = [‘Z’] # Substitui o ultimo element por Z<strong></strong>

    A classe Array também nos permite concatenar arrays:

    1
    2
    3
    4
    5
    
    a = [1,2,3] + [4,5] # [1,2,3,4,5]
     
    a = a + [[6,7,8]] # [1,2,3,4,5, [6,7,8]]
     
    a = a + 9 # Deve ser uma array!
    a = [1,2,3] + [4,5] # [1,2,3,4,5]
    
    a = a + [[6,7,8]] # [1,2,3,4,5, [6,7,8]]
    
    a = a + 9 # Deve ser uma array!

    Com a operação de soma, a classe fica responsável por criar uma nova array que contenha os novos operandos juntos. Para anexar elementos ao final de uma array, use o concat.

    1
    2
    3
    4
    5
    6
    7
    
    a = []
     
    a << 1 # [1]
     
    a << 2 << 3 #[1,2,3]
     
    a << [4,5,6] # [1,2,3,[4,5,6]]
    a = []
    
    a << 1 # [1]
    
    a << 2 << 3 #[1,2,3]
    
    a << [4,5,6] # [1,2,3,[4,5,6]]

    E da mesma forma que você soma, você pode subtrair, multiplicar.

    1
    
    a = [0] * 8 # [0,0,0,0,0,0,0,0]
    a = [0] * 8 # [0,0,0,0,0,0,0,0]

    A classe Array consegue utilizar os operadores | e & para união e interseção. O | concatena os elementos e então remove todos aqueles que estejam duplicados retornando uma array unificada:

    1
    2
    3
    4
    5
    6
    7
    8
    
    ruby-1.9.2-p136 :059 > a
     => [0, 1, 2, 3]
    ruby-1.9.2-p136 :060 > b = Array.new
     => []
    ruby-1.9.2-p136 :061 > b << 0 << 1 << 5 << 6 << 7
     => [0, 1, 5, 6, 7]
    ruby-1.9.2-p136 :062 > a | b
     => [0, 1, 2, 3, 5, 6, 7]
    ruby-1.9.2-p136 :059 > a
     => [0, 1, 2, 3]
    ruby-1.9.2-p136 :060 > b = Array.new
     => []
    ruby-1.9.2-p136 :061 > b << 0 << 1 << 5 << 6 << 7
     => [0, 1, 5, 6, 7]
    ruby-1.9.2-p136 :062 > a | b
     => [0, 1, 2, 3, 5, 6, 7]

    E o & retorna um array que mostra o que tem de comum entre as duas (interseção), exemplo:

    1
    2
    
    ruby-1.9.2-p136 :063 > a & b
     => [0, 1]
    ruby-1.9.2-p136 :063 > a & b
     => [0, 1]

    Para fechar, a classe Array oferece outros métodos muito úteis como o join, pop, push, reverse, reverse_each, sort, sort!, uniq!, unshif, tclear, compact!, delete_if, each_index, empty?, fill, flatten!, include?, index e entre outros que você pode encontrar na documentação do Ruby.
    Bons estudos à todos e até o próximo post que será sobre Hashes :)


  4. [ Quick Post ] – accepts_nested_attributes_for

    July 26, 2011 by urieljuliatti

    Hoje tive que me deparar com uma situação onde necessitava de fazer um cadastro de um artigo com a seguinte situação: Como construir os artigos e as tags em um só form e de uma só vez?

    A solução foi formidável: Apliquei o accepts_nested_attributes :tags, :allow_destroy => true no meu model Article.

    Tendo em vista que você já fez suas associações nos modelos, essa propriedade permite que você crie outros objetos (Tag, por exemplo) associados à aquele objeto Pai (Article) em seu atual tempo de criação, ao invés de criar um primeiro e depois o outro, que fugiria completamente a lógica do sistema.

    Quando você define um accepts_nested_attributes no seu modelo, você está dizendo ao rails que aquele objeto possui um writer (setter) com métodos de outro(s) objeto(s). Feito isso, agora sim você vai permitir que as Tags sejam escritas dentro do mesmo form de criação de um Article.

    Na view que você criará o artigo, basta iterar com o fields_for :

    1
    2
    3
    4
    5
    6
    
    <pre><%= form_for @articles do |article_form| %>
      ...
      <%= article_form.fields_for :tags do |tag_fields| %>
        Titulo  : <%= tag_fields.text_field :title %>
      <% end %>
    <% end %></pre>
    <pre><%= form_for @articles do |article_form| %>
      ...
      <%= article_form.fields_for :tags do |tag_fields| %>
        Titulo  : <%= tag_fields.text_field :title %>
      <% end %>
    <% end %></pre>

    A cobertura foi meio básica, pois eu utilizei um helper junto à view, utilizando Jquery para adicionar ou remover quantas tags eu quiser.

    Mesmo assim, espero que façam um bom proveito :)

    Abraços.


  5. [ Quick Post ] – Callbacks no Rails 3 – before_save

    July 13, 2011 by urieljuliatti

    Os callbacks são conhecidos por funcionarem como um “gancho” para o ciclo de vida de um objeto Active Record. Eles permitem acionar lógica antes ou depois de uma alteração do estado de um objeto. Basicamente, você lida com acionamento de triggers que podem alterar o objeto para um determinado estado, como se fosse uma chave de “liga e desliga”. Imagine uma lâmpada apagada em um quarto em que o interruptor fique do lado de fora. Para entrar no quarto e ter o estado lâmpada como “acesa” você precisa apertar o interruptor antes de entrar e, caso queira mudar o estado para “apagada” , você precisa sair do quarto e acionar o interruptor novamente. Repararam? Para os dois diferentes estados (apagada e acesa) do objeto Lâmpada, precisei executar uma tarefa antes (before) e outra depois (after).

    Para ilustrar a aplicação dessa funcionalidade, ontem tive que encriptar uma senha antes dela ser salva como um registro, mudando o estado para salvo. Logo abaixo, o método encrypt_new_password é executado e aplica a todas as operações (create e update)  antes de mudar o estado do objeto através do callback save.

    Em suma, toda vez que um objeto for criado ou atualizado, ele acionará esse método de encriptação antes mudar seu estado para salvo e gravar o registro.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
    before_save :encrypt_new_password
     
    protected
     
    def encrypt_new_password
    return if password.blank?
    self.hashed_password = encrypt(password)
    end
       def encrypt(string)
    Digest::SHA1.hexdigest(string)
    end
     
    end
    before_save :encrypt_new_password
    
    protected
    
    def encrypt_new_password
    return if password.blank?
    self.hashed_password = encrypt(password)
    end
       def encrypt(string)
    Digest::SHA1.hexdigest(string)
    end
    
    end

    Existem outros callbacks que o Rails oferece por padrão, você pode estudá-los através da própria API .

    Abraços e até o próximo quick post!

    Créditos ao amigo @m3nd3s pelas correções :)