Ruby Série #7 – Classes Simples

Posted in Ruby/Rails on May 20th, 2010 by Edipo L Federle – Be the first to comment

Olá pessoas, finlamente estamos devolta para falar novamente de Ruby, dessa vez iremos dar uma olhada básica na criação de classes em Ruby.

Iremos fazer nossos exemplo em cima de uam classe chamada Matemática.

Definição de uma Classe

Simples como só o Ruby poderia ser :D , usamos a palavra chave do Ruby class para criar uma nova constante para fazer referência a nossa classe, nome de classe e constante ambas são as mesma, é por isso que devemos declarar classes com letra Maiúscula.

A palavra chave self

Podemos usar a palavra self para nos referir a própria classe, essa palavra vem dentro da definição da classe, por exemplo.

Criando uma Instância de Matematica

Até o momento ainda não colocamos nada de atributos ou métodos em nossa classe, mas isso não impede que agente crie uma instância dessa classe, para isso usamos a palavra-chave new.

Todo e qualquer objeto de classe tem um método new.

O que temos de importante para fazer com um objeto que não tem nenhum método ? Bem podemos pedir para ele qual é seu tipo, para tal operação:

Inicializar a Nossa Classe

Construtores é a palavra se você vem ou é do mundo Java, queremos inicializar nossa classe com dois argumentos x e y. Mas como você não está no Java aqui isso se chama initialize.

Simples heim, mas o que aconteceu nessas três novas linhas? Primeiramente usamos a palavra-chave def para definir nossa método initialize, vale dizer aqui que esse def define um método de instância da classe, quando vamos chamar um método de instância da classe o valor de self é uma instância da classe na qual o método foi declarado.

Bom, quando definimos uma initialize para uma classe, temos que saber que quando usamos o método new para criar um nova instância da nossa classe, ele chama automaticamente o método initialize para aquela instância, então todo e qualquer argumento que você passar para new irão ser passados para o initialize, então como nosso initialize está esperando dois argumentos devemos agora passar esses argumentos no momento em que criamos nosso objeto Matematica.

Pronto agora sim. Algo bacana que acontece internamente no Ruby é que o método intialize é PRIVATIZADO automaticamente. Ou seja um objeto por ele mesmo pode chamar esse método para fazer a inicialização de seus argumentos, mas você não pode fazer uma chamada explicita para por exemplo mudar os valores de inicialização.

O que temos dentro do método initialize é dois valores que passamos nas variáveis @x, e @y, em Ruby o que começar com @ é uma variável de instância, então podemos ter n instância de Matematica que cada um delas terá seus próprios valores para x e y.

Uma consideração sobre variáveis de instância é que elas somente podem ser acessadas pelos métodos de instância do Objeto. Ou seja se houver algum código que não esteja dentro de um método de instância não poderá ler ou modificar seu valor. Na verdade existe uma maneira de fazer isso usando algumas técnicas de reflexão(reflections)

Certamente se você esta pensando em Java ou outras linguagens estáticas ficou pensando em fazer a declaração das variáveis, se você fizesse isso podia até pensar estar fazendo a coisa certa mas não está, no Ruby as variáveis de instância são resolvidas todas em contexto self, no momento em que é invocado o método initialize o self mentém uma instânia de nossa classe(Matematica), ou seja, o código fora do initialize faz referência à definição da classe e não a INSTÂNCIA da classe, então quando a leitura das variáveis que você declara fora(como no Java, por exemplo) são totalmente diferentes daquelas dentro do initialize.

O quase sempre presente método to_s.

Isso é praticamente default em todas as classes que você fizer, isso para poder retornar uma representação da sequência do objeto.

Bem melhor que antes não:

Saídas

com to_s: (3,4)

sem to_s: #

Bom essa foi a primeira parte, logo logo eu posto mais, obrigado por ler :D

Criado_em, Atualizado_em – Timestamp com Hibernate

Posted in Hibernate, Java on April 25th, 2010 by Edipo L Federle – 1 Comment

Antes de ler: http://en.wikipedia.org/wiki/Timestamp

Uma das coisas que eu sempre achei muito bacana no Rails é a parte do ActiveRecord,(active record pattern) uma característica que particularmente gosto é a criação automatica dos timestemp das tabelas no banco de dados, no Rails quando tempo um modelo(model) quase sempre temos um tabela relacionada a esse modelo no banco de dados, para título de curiosidade do pessoal do Java vou apresentar abaixo uma classe(model) que representa um produto.

OBS: essa linhda validates_presence_of: eu coloquei somente para não deixar a classe vazia, ela faz a validação do campo nome e descrição.

Simples não? Claro temos a migration para isso.

Explicando para quem não conhece Ruby/Rails. Uma classe que herda de ActiveRecord::Migration e tem dois métodos um que irá criar nossa tabela e suas colunas, e um método caso quizermos apagar nossa tabela.(Essa classe irá ser executada quando você rodar o comando rake db:migrate), sem muitas explicações para não sair muito da linha, mas sendo um pouco xiita, muito elegante esse código não?
Como podemos ver nessa classe temos uma linha que diz t.timestamp, é essa linha que irá criar os created_at e updated_at na nossa tabela, essa linha vem junto com qualquer migração(model) padrão que você criar, bom isso não ?

Ultimamente eu estou tendo um contado maior com Java e Hibernate, não vamos falar sobre Java vs Ruby aqui(ainda), então eu estava mapeando classes para o banco e me vi sem os timestamps, pensei, o hibernate é algo bacana provavelmente tenha algo parecido, uma olhada no google e na documentação e achei uma forma bem bacana e de certa forma elegante(não quanto o Ruby, xiita :D ) de se fazer tal funcionalidade.

Abaixo apresento uma classe Java Product que faz o uso do timestamp através de anotações do Hibernate.

Bom um tanto elegante também, mas … bom, tirei os gets e sets para deixar mais pequena, com essas anotações(@prePersist, @PreUpdate) iremos ter esses campos no banco igualmente temos no Rails, agora quando você persistir seu objeto ele ira gravar a data e a hora, e toda as vezes que você atualizar esse objeto no banco de dados ele irá atualizar a data e hora do campo updated, como na imagem a abaixo:

Bom pessoal esse post foi rápido e espero que tenha sido bom. :D

Até Logo. :)

Minha Primeira RubyGem – Gploy: automatizando deployment rails usando git push

Posted in Programação, Ruby/Rails on March 31st, 2010 by Edipo L Federle – 1 Comment

Olá pessoas, ja fazia um tempão que não postava nada aqui, mas a coisa anda corrida por esses lados, mas vamos ao post.

Recetemente lancei para o público a primeira gem que me arrisquei a fazer, essa gem está longe de ser perfeita e também esta bem longe de ter um bom código, mas como é a primeira me perdoem :D .

O que essa gem faz é simplesmente configurar seu projeto rails para usar o git para automatizar seu deploys, essa gem usas as configurações citadas pelo Fábio Akita neste post, ou seja configura seu projeto localmente e o seu servidor para isso. Como sstou com um pouco de preguiça :D irei colocar aqui somente por enquanto o link para o github e la tem a documentação(em inglês) de como usar(é fácil).

Github Projet Page

RubyGem Page

Valeu pessoas e comentem.

Ruby Série #6 – Exceções e Manipulação de Exceções – Parte 1

Posted in Programação, Ruby/Rails on February 16th, 2010 by Edipo L Federle – Be the first to comment

Warning: Missing argument 1 for GeSHi::GeSHi(), called in /home/storage/f/73/ab/bitside1/public_html/edipo_blog/blog/wp-content/plugins/codecolorer/codecolorer-core.php on line 137 and defined in /home/storage/f/73/ab/bitside1/public_html/edipo_blog/blog/wp-content/plugins/deans_code_highlighter/geshi.php on line 432

Warning: Missing argument 2 for GeSHi::GeSHi(), called in /home/storage/f/73/ab/bitside1/public_html/edipo_blog/blog/wp-content/plugins/codecolorer/codecolorer-core.php on line 137 and defined in /home/storage/f/73/ab/bitside1/public_html/edipo_blog/blog/wp-content/plugins/deans_code_highlighter/geshi.php on line 432

Em linhas gerais uma exceção é um objeto que indica um tipo de condição excepcional, ela indica que algo muito errado aconteceu, um clássico exemplo de exceção é a divisão por zero, aposto que todos já passaram por algum caso de divisão por zero, chamar métodos que não existem, passar argumentos errados para métodos e assim por diante, esses exemplos citados são todos erros de programação, mas uma exceção não é somente levantada por conta disso, também podemos ter outros tipos de exceções como tentar fazer o uso da rede quando a mesama estiver off.

Não irei falar mais sobre o que são exceções mas recomendo fortemente a leitura na wikipedia sobre isso.

Quando algum erro acontece, por exemplo à passagem de um argumento inválido para um método qualquer dizemos que uma exceção é levantada, por padrão o Ruby finaliza o programa quando algo do tipo acontece, mas como iremos ver é possível fazer à declaração de manipuladores de exceções, isto é um bloco de código que é sempre executado se uma exceção acontecer na execução de um bloco de código, quando uma exceção é levantada o que acontece é a transferência do fluxo de controle para um código que irá tratar essa exceção. Possivelmente você pode tentar fazer uma comparação com a delaração break para sair de um laço por exemplo, mas como iremos ver mais adiante as exceções são bem diferentes, poderosas e flexíveis ao ponto de nos premitir transmitir o fluxo para n blocos.

No Ruby podemos fazer o uso do método raise para levantar exceções e fazer o uso da cláusula rescue para tratar as exceções.
Todas exceções que são levantadas por raise são uma instância de classe Exception ou de alguma de suas subclasses.

Segue abaixo a hierarquia da classe Exception:

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
Exception
 NoMemoryError
 ScriptError
   LoadError
   NotImplementedError
   SyntaxError
 SignalException
   Interrupt
 StandardError
   ArgumentError
   IOError
     EOFError
   IndexError
   LocalJumpError
   NameError
     NoMethodError
   RangeError
     FloatDomainError
   RegexpError
   RuntimeError
   SecurityError
   SystemCallError
   SystemStackError
   ThreadError
   TypeError
   ZeroDivisionError
 SystemExit
 fatal

Logicamente voçê não tem que saber cada uma delas(seus nomes não bem óbvios) o que você deve ter em mente é que algumas dessas classes extendem uma classe conhecida como StandardError, ou seja, exceções, digamos assim que acontecem com mais frequência, algumas outra expressões representam níveis bem mais baixos, coisas que com menos possibilidade de recuperação logo os programas Ruby(normalmente) não tentam fazer a sua manipulação.

Objetos dos métodos de excecção.

Temos dois métodos que podem retornar alguns detalhes sobre uma dada exeção, esses métos são da classe Exception, message irá retornar uma sequência que permite obter alguns detalhes que podem ser entendidos por seres humanos, facilitando o entendimento de erros.
Também temos outro método bastante importante que é o backtrace, backtrace irá retornar um array de sequências representando uma pilha no ponto em que a exceção foi levantada.

A[0] = posição no qual a exceção foi levantada.
A[1] = posição no qual o método que levantou a exceção foi chamado.
A[2] = posição no qual esse método foi chmado.

E por ai vai, para poder ver um rastreamento da pilha o Ruby fornece um Método Kernel caller.

Objetos de Exceção.

Objetos de exceção são criados pelo método raise, também temos a opção de fazer a criação de nossos próprios objetos, normalmente usando o new ou com outra classe de métodos exception.

Lançando Exceções com Raise.

Quando um método do Kernel é sobreescreito uma exceção é levantada, fail é usado certas vezes quando há certa expectativa que seu programa deva ser finalizado pela exceção.
Existem n formas de se invocar o método raise, veremos abaixo algumas dessas formas:

Raise sem Argumentos

Se o método raise for chamado sem nenhum argumento, o mesmo irá criar um objeto do tipo RunTimeError que não irá ter nenhuma mensagem e então o levanta, por hora se raise for usado também sem argumento mas dentro de um rescue(iremos ver logo ele) o que irá acontencer é que a exceção(que estava sem manipulada) irá ser re-levantada.

Raise com um único argumento

Caso o raise for chamdo com um único argumento (objeto exception) ele irá levantar essa exceção.( Não é um forma muito comun se fazer o uso do raise)

Raise com uma sequencia de argumentos.

Neste caso será criado um objeto novo de exceção( RunTimeError), é uma forma comun de fazer o uso do raise.

Raise com objeto que possua uma exceção

Neste caso raise invoca tal método e levanta o objeto Exception que o mesmo retona.
OBS: A classe Exception possue um método exception, isso quer dizer que você pode especificar a classe do objeto para qualquer tipo de exceçao para ser o primeiro argumento do raise.

Raise com sequencia no terceiro argumento

Neste caso um array de sequências é especificado e então serão usados como o backtrace do objeto(exceção).
OBS: Caso este terceiro argumentos não esteja especificado raise ira usar Kernel caller no backtrace.

Exemplo 1:

Até agora falamos muito, mas não colocamos nada em código ainda, vamos fazer um exemplo bem simples para começar, meio batido mas vou usar o exemplo fatorial novamente.

1
2
3
4
5
6
7
8
9
10
def fatorial(n)
  raise "Argumento invalido" if n < 1
  return 1 if n == 1
  n * fatorial(n-1)
end

puts fatorial(5)
puts fatorial(4)
puts fatorial(10)
puts fatorial(-4)

ruby ex.rb
120
24
3628800
ex.rb:2:in `fatorial’: Argumento invalido (RuntimeError)
from ex.rb:10

Este caso se encaixa no tipo de uso do raise um um único argumento, como dito antes temos outras formas de fazer a mesma coisa, por exemplo:

raise “Argumento invalido” if n < 1
pode ser perfeitamente substituido por:
raise RuntimeError "Argumento invalido" if n < 1
raise RuntimeError.new "Argumento invalido" if n < 1 ou
raise RuntimeError.exception "Argumento invalido" if n < 1

Claramente uma exceção RuntimeError não parece o mais apropriada para o caso do fatorial acima seria mais adequado usar um ArgumentError, ficando assim:

1
2
3
4
5
6
7
8
9
10
def fatorial(n)
  raise ArgumentError if n < 1
  return 1 if n == 1
  n * fatorial(n-1)
end

puts fatorial(5)
puts fatorial(4)
puts fatorial(10)
puts fatorial(-4)

ruby ex.rb
120
24
3628800
ex.rb:2:in `fatorial’: ArgumentError (ArgumentError)
from ex.rb:10

ou até mesmo você pode personalizar um pouco essa mensagem, por exemplo fazendo o seguinte:

1
2
3
4
5
6
7
def fatorial(n)
  raise ArgumentError, "Esperava um argumento >= 1. Mas retornou #{n}", caller if n < 1
  return 1 if n == 1
  n * fatorial(n-1)
end

puts fatorial(-4)

ruby ex.rb
ex.rb:7: Esperava um argumento >= 1. Mas retornou -4 (ArgumentError)

Bom, bem melhor a mensagem assim ? O exemplo do fatorial é um código simples, você não irá querer escrever testes unitários para ele(devia), pois podemos pensar facilmente nos casos em que ele irá falhar, se o código fose algo mais complexo e com n casos seria muito útil termos testes para eles, mas será que esse código de fatorial está ok ? claramente vemos que ele simplesmente checa se o número é positivo, mas não chega o tipo, isso pode ser facilmente resolvido adicionando um outro raise, assim:

1
2
3
4
5
6
def fatorial(n)
  raise TypeError, "Valor invalido, somente inteiros positivos" unless n.is_a? Integer
  raise ArgumentError, "Esperava um argumento >= 1. Mas retornou #{n}", caller if n < 1
  return 1 if n == 1
  n * fatorial(n-1)
end

E por curiosidade aqui vai um simples teste unitário para o código acima:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
require "test/unit"
require "fatorial.rb"

class TestLibraryFileName < Test::Unit::TestCase
  def test_simples_cases
    assert_equal(120, fatorial(5))
    assert_equal(6, fatorial(3))
  end
 
  def test_negative_numbers
    assert_raise(ArgumentError) {fatorial(-1)}
  end
 
  def test_invalid_argument_type
    assert_raise(TypeError) {fatorial("a")}
  end

end

Uma coisa que deve ser entendida aqui, é que muitas vezes exceçõe irão acontecer mesmo sem agente levanta-lás, ou seja, exceções no próprio código Ruby, então uma lição importante é saber manipula-lás mesmo sem agente nunca lenvantar sequer uma delas.

O manipulador de Execções rescue

O rescue é um declaração que deve ser usada em conjunto com a declaração begin, begin é um delimitador de bloco de código dentro das exceções sendo manipuladas(Vimos um pouco disso no post anterior), a declaração begin parece bom isso:

1
2
3
4
5
begin
  #algum código
rescue Exception => e
  #código da manipualação da exceção vem aqui, qualquer exceção levantada pelo código acima, cai aqui.
end

OBS: o Exception => e é opcional, mas logo vermos que ele é útil.e

Dando um nome para um Objeto de Exceção

Podemos usar váriaveis para atribui-las um objeto de exceção(Exception), por exemplo:

1
2
3
4
5
6
7
8
9
def simple(n)
  raise ArgumentError, "Argumento Invalido" if n < 0
end

begin
  simple(-4)
rescue Exception => e
  puts "#{e.class}: #{e.message}"
end

=>ArgumentError: Argumento Invalido

Agora temos um váriavel global que faz referência ao objecto de exceção ( Exception ), essa váriavel é a $!, temos outras n variáveis globais, outra interessante é a $@ que retorna o local do último erro.

Uma coisa a ser notada aqui é que a váriavel e ficará disponível após o rescue ser finalizado, veja esse exemplo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
def simple(n)
  raise ArgumentError, "Argumento Invalido" if n < 0
end

begin
  simple(-4)
rescue Exception => e
  puts "Dentro do Rescue"
  puts "#{e.class}: #{e.message}"
  puts $!
  puts "Erro em #{$@}"
end

puts ""
puts "Fora do Rescue"
puts $!
puts e

Exceções por Tipo

As execções mostras acima com o uso do rescue trata exceções StandardError, ou suas subclasses, outras exceções que não tiverem dentro dessa hierarquia sera ignorado, então como podem tratar qualquer tipo de exceções ? Simples, faça o seguinte:

Resuce Exception

Agora você deve saber que para manipular um ArgumentError e atribuir isso para e, é simples:

Rescue ArgumentError => ex

E para definir mais que um tipo? Simples, simplesmente separe por virgula(,) elas.
Então vemos um exemplo de como tratar duas exceções, ArgumentError, e TypeError, mas queremos tratas ambas de forma diferentes.

1
2
3
4
5
6
7
begin
  x = fatorial("f")
rescue ArgumentError => e
  puts "Numero >= que 1 eh preciso"
rescue TypeError => e
  puts "Tente com intiero"
end

Bom pessoal essa foi a primeira parte sobre como tratar exceções no Ruby, na segunda parte iremos ver sobre propagação de exceções, exceções que ocorrem dentro de exceções e outras coisas mais.

Espero que tenham gostado e comentem :D

Campanha #SouDev Twitter

Posted in Opinião, Programação on January 29th, 2010 by Edipo L Federle – 5 Comments

Ontem chegou até min no twitter via @felipedeveloper uma mensagem sobre uma campanha #souDev no twitter, realmente não sei quem começou isso(se o fundador ler esse post por favor comente), essa campanha tem como simples objetivo fazer com que os desenvolvedores se “achem” no twitter e com isso fazer com que nossa timeline se torne algo melhor, onde possamos conhecer pessoas que trabalham com tecnologia, trocar informações e tudo mais.

Esse post tem como objetivo que o pessoal que ta participando do #SouDev deixe seu comentário para que eu possa ir adicionando aqui no post e com isso poder compilar opiniões de todos sobre a campanha, e até discutir formas de ampliar ela, quem sabe até um blog :D

Então pessoas, o que vocês pensam do #SouDev ?