Como validar variáveis ao usar attr_accessor no Ruby

Boa dia.

Galera, começei a estudar Ruby e muitas dúvidas surgiram.

Uma delas é a seguinte… no Java eu declaro uma variável privada e defino get’s e set’s, neste caso eu poderia usar o método set para validar a informação, por exemplo:

class People{  
  
    private int age;  
  
    public int getAge(){  
        return age;  
    }  
  
    public void setAge(int age){  
        if(age < 0){  
           this.age = 0      
        }else{  
           this.age = age;  
        }  
    }  
  
}  

Em ruby eu vi que existe um atalho para a criação desses métodos de acesso, por exemplo:

class People  
  
     attr_accessor :age  
  
end  

Mas existe alguma forma de validar se a idade é menor que zero utilizando esse atalho, ou teria que implementar um método tipo esse:

view plaincopy to clipboardprint?
class People

    def age=(age)  
        @age = age  
    end   

end

Dese já obrigado, aguardo.

Não duplique seus tópicos:

http://www.guj.com.br/java/308995-como-validar-variaveis-ao-usar-attr_accessor-no-ruby

[quote=Daniel T.S]

def age=(age) @age = age end .[/quote]
a forma mais simples é essa mesmo, criando o método setter. não dá pra ser mais econômico :smiley:
qualquer tentativa de simplificar isso vai piorar e deixar o código ilegível com metaprogramming.

[quote=leandronsp][quote=Daniel T.S]

def age=(age) @age = age end .[/quote]
a forma mais simples é essa mesmo, criando o método setter. não dá pra ser mais econômico :smiley:
qualquer tentativa de simplificar isso vai piorar e deixar o código ilegível com metaprogramming.[/quote]

Poderia ter postado ao menos no post original e não neste que é o duplicado…

de qualquer forma, não consigo ver como usar as validações do Active Record tornam o código ilegível:

class Person < ActiveRecord::Base
  validates :age, numericality: { only_integer: true, greather_than: 0 }
end

postar lá no original, uma vez que ele já alterou o conteúdo, faz sentido pra você?

dê uma olhada: http://www.guj.com.br/java/308998-como-validar-variaveis-ao-usar-attr_accessor-no-ruby

[quote=Ataxexe]de qualquer forma, não consigo ver como usar as validações do Active Record tornam o código ilegível:

class Person < ActiveRecord::Base
  validates :age, numericality: { only_integer: true, greather_than: 0 }
end

[/quote]
o exemplo dele não usa AR. É uma Ruby class simples.
Mesmo que usasse AR, acho ele não quer validar: quer assegurar que ages menores que 0 chegem a 0 :smiley:

EDITED:
Havia ainda um terceiro post duplicado e eu não havia reparado. Olhei para aquele com a descrição vazia…sorry

meu ponto sobre ilegibilidade não é o produto final, mas sim o meta-código que dará trabalho pra entender 6 meses depois. Para o caso de economizar um mísero IF como no exemplo, não vejo necessidade de criar um helper method que vai adicionar mais linhas de código no fim das contas

Não é bem um mísero if porque você tem uma segunda instrução aí:

def age=(n) age = n.to_i raise Error if n &lt; 1 #ou a loucura de colocar o age como zero (mas aí pode ser com um if/else na atribuição @age = age end

O "to_i" serve para converter para inteiro (ou teremos 23.5 anos, o que só é válido em alguns casos isolados e mesmo assim seria calculado com base na data de nascimento). E não precisamos criar um helper, pode-se importar gems de validação para isso.

E se alguém não entender o helper 6 meses depois é porque não o escreveu direito e se não entender a utilização do helper é porque não sabe ler.

Ficou confuso mesmo porque ele se referiu a validação durante o post inteiro. Mas o exemplo dele não é bem uma validação.

Eu não seria tão defensivo assim…
Não dá pra simplesmente fazer isso?

def age=(n) @age = [n.to_i, 0].max # thanks Math! end

Sim, obviamente. Mas importar uma gem pra validar que o age não pode ser menor que 0???

De novo, metaprogramming pra isso? Quando existem N outras formas pragmáticas de resolver o problema? Várias literaturas e a comunidade como um todo tem percebido que metaprogramming tem que ser usado com moderação. É questão de avaliar custos: compensa fazer toda essa volta pra verificar apenas que o age não pode ser menor que 0? Esse que é meu ponto. Meta é a última coisa que eu vou fazer, quando não há nenhuma solução simples na stdlib para aquilo.

Acho que o autor do tópico colocou isso em questão, porque como no começo ouvimos aquela moda em falar que Ruby faz “magias”, ele suspeitou que poderia ter algo mágico já pronto. Só que tem que ver o custo desse “pronto”.
Claro que, se ele for usar AR (ou até memo o ActiveModel apenas), já ganha de lambuja essas validações. Mas no caso de um simples PORO sei lá, não vejo necessidade

[quote=leandronsp]Eu não seria tão defensivo assim…
Não dá pra simplesmente fazer isso?

def age=(n) @age = [n.to_i, 0].max # thanks Math! end
[/quote]

Dá sim, embora não seja o mesmo efeito por causa da Exceção. O seu exemplo se aproxima mais do código Java do autor, eu soquei um raise lá só pra ilustrar também outra forma.

Eu entendo seu ponto, e se avaliarmos somente o código do post realmente não seria necessário importar uma gem só pra esse caso, mas se tivermos outro e outro e por aí em diante pode ser uma boa usar esse recurso.

[quote]
Acho que o autor do tópico colocou isso em questão, porque como no começo ouvimos aquela moda em falar que Ruby faz “magias”, ele suspeitou que poderia ter algo mágico já pronto. Só que tem que ver o custo desse “pronto”.
Claro que, se ele for usar AR (ou até memo o ActiveModel apenas), já ganha de lambuja essas validações. Mas no caso de um simples PORO sei lá, não vejo necessidade[/quote]

Eu entendo, só postei o lado metaprogramming disso por causa da sua última frase da primeira mensagem:

[quote=Ataxexe]Eu entendo, só postei o lado metaprogramming disso por causa da sua última frase da primeira mensagem:

Verdade, acho que não conssegui me expressar bem. Não sou contra meta, aliás, já precisei fazer muito meta nessa vida :stuck_out_tongue:

Mas por experiência própria e também aprendendo com os outros, prefiro adotar metaprogramming (inicialmente) como um “anti-pattern” até que se prove o contrário e seu uso traga realmente valor.

Eu também não sou muito fã de abusar de metaprogramação, é mais ou menos o mesmo que abusar de reflexão no java. Uma vez eu fiz umas loucuras com essas magias negras do ruby que me deu até medo de continuar usando adoidado (o que mais me deu medo foi definir métodos dinamicamente cujos nomes também eram dinâmicos - foi quase uma “inception”). É legal pra impressionar, mas não dá pra abusar mesmo.

LOL pode crer