Ruby 3.0. Ruby e métodos de controlo da privacidade menos conhecidos
Tomasz Szkaradek
Arquiteto de desenvolvimento
Uma das caraterísticas mais adoradas do Ruby é a sua sintaxe muito flexível. Pessoalmente, adoro Ruby pela quantidade de possibilidades que temos para definir classes e as suas propriedades, e é isto que vou discutir neste artigo.
Soluções de base
Vamos supor que estamos a utilizar a classe Foo que tem um método público e um método privado:
classe Foo
def bar
:awesome
fim
privado
def baz
:algo_privado
fim
fim
Tudo é ótimo, vemos uma solução deste tipo em praticamente todos os projeto. Em curso Foo.new.baz provocará o erro NoMethodError (método privado "baz" chamado para # ) e era isso que pretendíamos fazer. O que acontece se tentarmos alterar o formato de gravação e adicionarmos private como prefixo na definição da classe?
classe Foo
def bar
:awesome
fim
private def baz
:algo_privado
fim
fim
Como se pode ver, depois de executar o código, funciona de facto! Porque é que podemos introduzir a visibilidade do método antes de o fazer? Porque ao definir um método, def devolve o nome do método como um símbolo. Esta expressão não é apenas uma parte da sintaxe, mas de facto um método derivado da classe Module e que trata este símbolo como um argumento. Para mais informações, consulte a documentação nesta ligação. Uma vez que começou tão facilmente com private, vamos tentar alterar a visibilidade do método private.
classe Foo
def bar
:awesome
fim
private def baz
:algo_privado
fim
public :baz
fim
O que é que acontece depois de executar o código?
irb(main):012:0> Foo.new.baz
=> :algo_privado
Sucesso! O nosso método de bases tornou-se público porque o tornámos visível duas vezes. Naturalmente, a mesma operação aplica-se aos módulos. Ótimo, mas onde é que se obtém nós? Esta funcionalidade dá-nos muitas vantagens, porque podemos alterar livremente a visibilidade de um método enquanto o definimos, ou mesmo alterar a visibilidade dos métodos quando os herdamos.
Agora, vamos ver o que Rubi 2.7 pode fazer em termos de alteração da visibilidade dos pseudónimos e dos acessores.
classe Foo
private attr_accessor :awesome_variable
final
Infelizmente, recebemos um erro porque o método privado espera símbolos e attr_accessor. O código devolve nil e, portanto, este método não é compatível com a utilização privada em Ruby 2.7. Então, quais são as nossas opções?
Podemos utilizar attr_accessor sob a palavra-chave private para o fazer funcionar, ou seja, obteremos um erro quando quisermos fazer referência ao variável_fantástica variável_fantástica método.
classe Foo
privado
attr_accessor :variável_fantástica
final
A segunda opção é executar o método privado em métodos gerados por atributo_atributoNeste caso, também temos de nos lembrar de introduzir o setter.
classe Foo
attr_accessor :variável_impressionante
private :awesome_variable, :awesome_variable=
fim
Problemas com o attr_ * não são os únicos obstáculos. Podemos encontrar a mesma dificuldade quando queremos criar um alias privado.
classe Foo
private alias :bar, :awesome_bar
fim
Ruby 3.0 e a nossa atividade
Felizmente, o Ruby 3.0 introduz uma grande mudança, uma vez que os métodos de visibilidade podem receber uma matriz como argumento e o alias de métodos, attr_ *, pode repor a matriz com os nomes dos métodos que foram definidos. Pode ler mais em aqui.
Agora, vamos ver alguns exemplos na última euba e verificar se as alterações foram realmente efectuadas e como podemos utilizá-las. No primeiro exemplo, vamos utilizar private antes do acessório attr:
classe Foo
private attr_accessor :awesome_variable
final
Essa chamada não causará erros na análise da sintaxe e, o que é importante, o variável_incrível evariável_fantástica =tornam-se privados. O método alias fará o mesmo, mas agora também devolve um símbolo como o nome do novo método e torna-o visível.
classe Foo
private alias :bar, :awesome_bar
fim
Um facto interessante é que também podemos aprofundar outros métodos, por exemplo, o fantásticoo módulo de impressão pode ser chamado entre private e attré importante que esse método devolva uma matriz com os nomes dos métodos que estão do lado direito da expressão.
classe Módulo
def awesome_print(nomes)
coloca nomes
nomes
fim
fim
classe Foo
private awesome_print attr_reader :awesome_bar
end
Resumo
Espero que este artigo vos seja útil! Em caso de mais notícias sobre Ruby 3.0. leia mais aqui.