Rails Way: Modelos gordos e controladores magros

30 de janeiro de 2009  |  Rails Way  | 

Existe um jargão na comunidade Ruby on Rails conhecido como o “Rails way”, ou em bom português o jeitão de fazer as coisas no Rails. Não existe uma regra escrita sobre como desenvolver código em Ruby usando o Rails, mas a comunidade tem apoiado algumas praticas que tem se mostrado úteis e inteligentes.

Um grande problema que tenho encontrado com alguns alunos e até mesmo com profissionais “experientes” é que muitos que hoje programam em Ruby vieram de linguagens como Java, C# e PHP, e trazem para o Ruby on Rails os mesmos vícios que possuíam ao desenvolver nestas plataformas.

Para facilitar a vida destes programadores vou tentar mostrar algumas das “boas práticas” que um bom desenvolvedor Rails costuma adotar. E a primeira delas é “modelos gordos e controladores magros”.

laurel-hardy-portrait

Modelo gordo e controlador magro

A idéia é que toda a lógica para a manipulação de um recurso fique concentrada dentro da sua classe especifica. Esta idéia parece um pouco confusa e difícil de ser adota no inicio, mas para simplificar um pouco tente fazer o seguinte: Cada action de seus controllers deve chamar apenas um método de um modelo além de um find ou new iniciais, mesmo que seja necessário criar métodos .new ou .update personalizados.

Por exemplo:

def update
  @account = Account.find(params[:id])

  respond_to do |format|
    if @account.update_attributes(params[:account])
      format.html { redirect_to client_accounts_url(@client) }
    else
      format.html { render :action => "edit" }
    end
  end
end

Veja que no código acima estou inicialmente chamando o método find da classe Account e logo em seguida o método update_attributes. Este é o mundo ideal, apenas um método além do find inicial, no caso o método update_attributes. Estou sendo repetitivo para fixar a ideia.

Existem casos um pouco mais complexos que exigirão a criação de métodos personalizados e não há mal algum de cria-los. Imagine que no exemplo acima eu somente pudesse alterar os dados da conta (Account) do usuário atual. Neste caso eu poderia cria um novo método dentro da classe Account chamado update_attributes_by_user que além de receber o hash com os dados do formulário, também deve receber o usuário registrado na sessão atual:

def update
  @account = Account.find(params[:id])

  respond_to do |format|
    if @account.update_attributes_by_user(params[:account], current_user)
      format.html { redirect_to client_accounts_url(@client) }
    else
      format.html { render :action => "edit" }
    end
  end
end

Não importa o código deste método, o que importa é que a lógica por traz dele está no lugar certo, dentro do modelo. Enfim, esta é a ideia.

Em breve escreverei sobre outras boas praticas ao desenvolver softwares com Ruby on Rails.


9 Comentários


  1. Maykon Luís Capellari

    Ótimo artigo Carlos, realmente este tipo de vício é dificil de perder no começo o que mais acontece é criar validações e atribuições direto no controller e normalmete o controller fica com muito código e a maioria das vezes códigos repetitivos, enquanto o model tem apenas os validates e as associaçoões. Mais uma vez parabéns. Aguardo novo post. ;)

  2. Muito bom o artigo, eu que estou me tornando um newbie em ruby on rails já poderia cortar o mal antes que ele vire vicio. Muito boas as dicas, tanto essa quantos as outras, todas muito úteis. Obrigado pelo bom trabalho.

  3. Gostei do artigo. É sempre bom ensinar as pessoas a desenvolverem com Rails usando o… Rails. Uma linguagem/framework não é só sintaxe, semântica e API. No fim, o mais importante é o “DNA” da linguagem/framework, ou seja, o modo como as coisas são feitas nela.

    Enfim, parabéns pela boa idéia, e que venha os próximos posts da série.

  4. Ótimo artigo! Tomara que a série continue, gosto pra caramba de artigos mostrando o Rails Way das coisas.

    Essa dica em particular é muito útil porque evita repetição de código. Sempre que você pensar em dar um ctrl+c ctrl+v num controller, sinal que o código tem que ir pro modelo. :D

  5. Carlos, o que você chamou de problema – “trazem para o Ruby on Rails os mesmos vícios que possuíam ao desenvolver nestas plataformas” – é uma coisa super comum de acontecer. Eu diria que é até normal. Você, por exemplo, se não me engano, chegou ao RoR vindo de C#, estou certo? Com certeza no começo você deve ter trazido um monte de coisas que tinha como verdade na antiga plataforma, e com o tempo, vendo os hackers Ruby e Rails fazerem as coisas, você foi aprendendo o jeitão Ruby e Rails.

    O problema está em que nem tudo que é verdade em um plataforma, também é em outra. (Na verdade, problema não, não vejo isso como problema. Hummm… “a particularidade”… Acho que assim fica melhor… rsrsrs)

    Tendo acesso a livros como The Ruby Way, The Rails Way, e posts como esses seus, os novatos vindos de outras plataformas (onde eram ou não experientes) vão pegando “o jeitão de como se fazer as coisas no RoR”.

    Agora, algumas coisas conceituais serão verdade em uma ampla gama de plataformas. Como é o caso de “modelos gordos e controladores magros”, que não é uma boa prática de bons programadores RoR, mas de qualquer bom programador que está trabalhando com uma abordagem MVC.

    Abraço!

  6. Um comentário superatrasado, mas pertinente para mim. Estou estudando RoR e o Google me apontou para cá. Uma questão. Não seria repetir o código o que você sugere fazer com o segundo método, quando a convenção diz para não repetir? Desculpe-me, realmente sei quase nada de RoR, talvez minha pergunta em função do jeito RoR de ser (e fazer) esteja bem equivocada.

  7. Eduardo,

    Não entendi onde está a repetição de código? Você pode explicar melhor?

    Talvez você tenha confundido, mas ambos são o mesmo método. Será que é isso?

  8. Oi Carlos. Pelo que entendi, o segundo método seria uma outra situação não atendida pelo prineiro método, ou seja, ambos poderiam existir na aplicação se ela os requeresse. Se ela requeresse ambos os tratamentos, não seriam escritos dois métodos praticamente iguais como esses? Isso não vai contra a convenção? Foi essa a questão que me passou pela cabeça. Ou eu, na minha ainda grande ignorância sobre o assunto, intrometi-me antes da hora, quando não devia? Hehe.. Parabéns ao blog. Grato.

  9. Eduardo,

    O segundo exemplo é só para mostrar uma modificação no primeiro exemplo. Em ambos o método update é o mesmo.

Trackbacks

  1. Rails Way #2: Variáveis de Instância, Controllers e Views | Nome do Jogo

Deixe um comentário