Skip to content

Latest commit

 

History

History
1242 lines (958 loc) · 39 KB

README-ptBR.md

File metadata and controls

1242 lines (958 loc) · 39 KB

Prelúdio

Modelos são importantes.
-- Oficial Alex J. Murphy / RoboCop

O objetivo deste guia é apresentar um conjunto das melhores prescrições de práticas e estilo para desenvolvimento Ruby on Rails 4. Esse é um guia complementar para o já existente liderado pela comunidade Ruby coding style guide.

Alguns dos conselhos aqui são aplicáveis somente no Rails 4.0+.

Você pode gerar um PDF ou uma cópia HTML deste guia usando Pandoc.

Traduções deste guia estão disponíveis nas seguintes linguagens:

O Guia de Estilo Rails

Este guia de estilo Rails recomenda boas práticas para que os programadores reais de Rails possam escrever códigos que possam ser mantidos por outros programadores reais de Rails. Um guia de estilos que reflete o uso que o mundo real está acostumado e um guia de estilo que se prende a um ideal que foi rejeitado pelo povo supõe-se que o melhor é não usá-lo para nada - não importa quão bom seja.

O guia é separado em várias seções de regras relacionadas. Eu tentei adicionar a lógica por trás das regras (se estiver omitido, eu assumi que é bastante óbvio).

Eu não vim com todas as regras do nada - são na maioria baseadas na minhas extensa carreira como profissional de engenharia de software, comentários e sugestões de membros da comunidade Rails e vários recursos de programação Rails altamente recomendados.

Tabela de conteúdos

Configuração

  • Coloque código de inicialização customizada em config/initializers. O código nessa pasta são executados quando a aplicação inicia. [link]

  • Mantenha os códigos de inicialização de cada gem em um arquivo separado com o mesmo nome da gem, por exemplo carrierwave.rb, active_admin.rb, etc. [link]

  • Ajuste de acordo com as definições dos ambientes de desenvolvimento, teste e produção (nos arquivos correspondentes dentro de config/environments/) [link]

    • Marcar assets adicionais para pré-compilação (se houver):

      # config/environments/production.rb
      # Pré-compila assets adicionais (application.js, application.css,
      # e todo non-JS/CSS já são adicionados)
      config.assets.precompile += %w( rails_admin/rails_admin.css rails_admin/rails_admin.js )
  • Mantenha a configuração que é aplicável à todos ambientes no config/application.rb file. [link]

  • Crie um ambiente staging adicional que se assemelha ao produção. [link]

  • Mantenha qualquer configuração adicional em arquivos YAML dentro do diretório config/. [link]

    A partir do Rails 4.2, arquivos de configuração YAML podem ser facilmente carregados com o novo método config_for:

    Rails::Application.config_for(:arquivo_yaml)

Rotas

  • Quando você precisar adicionar mais actions à um resource RESTful (você realmente precisa delas?) use rotas member e collection. [link]

    # ruim
    get 'subscriptions/:id/unsubscribe'
    resources :subscriptions
    
    # bom
    resources :subscriptions do
      get 'unsubscribe', on: :member
    end
    
    # ruim
    get 'photos/search'
    resources :photos
    
    # bom
    resources :photos do
      get 'search', on: :collection
    end
  • Se você precisa definir múltiplas rotas member/collection use a alternativa de sintaxe em bloco. [link]

    resources :subscriptions do
      member do
        get 'unsubscribe'
        # mais rotas
      end
    end
    
    resources :photos do
      collection do
        get 'search'
        # mais rotas
      end
    end
  • Use rotas aninhadas para expressar melhor o relacionamento entre os modelos do ActiveRecord. [link]

    class Post < ActiveRecord::Base
      has_many :comments
    end
    
    class Comments < ActiveRecord::Base
      belongs_to :post
    end
    
    # routes.rb
    resources :posts do
      resources :comments
    end
  • Se você precisa de rotas aninhadas com mais de 1 nível de profundidade, use a opção shallow: true. Isto vai livrar o usuário de longas urls como posts/1/comments/5/versions/7/edit e você de longos helpers de url como edit_post_comment_version.

    resources :posts, shallow: true do
      resources :comments do
        resources :versions
      end
    end
  • Use namespace em rotas para agrupar actions relacionadas. [link]

    namespace :admin do
      # Direciona /admin/products/* ao Admin::ProductsController
      # (app/controllers/admin/products_controller.rb)
      resources :products
    end
  • Nunca use o legado de controlador de rota. Esta rota fará todas actions em todos os controladores serem acessíveis via requisições GET. [link]

    # muito ruim
    match ':controller(/:action(/:id(.:format)))'
  • Não use match para definir qualquer rota a não ser que haja necessidade de mapear múltiplos tipos de requisições dentre [:get, :post, :patch, :put, :delete] para uma única action usando a opção :via. [link]

Controladores

  • Mantenha o controlador pequeno - eles devem apenas receber informações da camada de view e não deveria conter qualquer regra de negócio (toda regra de negócio deveria naturalmente ficar dentro do modelo). [link]

  • Cada action do controlador deveria (idealmente) invocar somente um outro método além do inicial find ou new. [link]

  • Compartilhar não mais que duas variáveis de instância entre controlador e view. [link]

Renderizando

  • Prefira usar render em um template a um inline. [link]
# muito ruim
class ProductsController < ApplicationController
  def index
    render inline: "<% products.each do |p| %><p><%= p.name %></p><% end %>", type: :erb
  end
end

# bom
## app/views/products/index.html.erb
<%= render partial: 'product', collection: products %>

## app/views/products/_product.html.erb
<p><%= product.name %></p>
<p><%= product.price %></p>

## app/controllers/foo_controller.rb
class ProductsController < ApplicationController
  def index
    render :index
  end
end
  • Prefira render plain: ao render text:. [link]
# ruim - atribui tipo MIME a um `text/html`
...
render text: 'Ruby!'
...

# ruim - requer declaração explícita do tipo MIME
...
render text: 'Ruby!', content_type: 'text/plain'
...

# bom - curto e preciso
...
render plain: 'Ruby!'
...
  • Prefira símbolos correspondentes a um código numérico de status HTTP. Eles são significativos e não parecem números “mágicos” para códigos de status HTTP menos conhecidos. [link]
# ruim
...
render status: 500
...

# bom
...
render status: :forbidden
...

Modelos

  • Introduza livremente classes de modelos que não usem ActiveRecord. [link]

  • Nomeie modelos com significantes (porém pequenos) nomes sem abreviações. [link]

  • Se você precisa de objetos de modelos que possuam comportamento do ActiveRecord (como validações) sem a funcionalidade do database do ActiveRecord use a gem ActiveAttr. [link]

    class Message
      include ActiveAttr::Model
    
      attribute :name
      attribute :email
      attribute :content
      attribute :priority
    
      attr_accessible :name, :email, :content
    
      validates :name, presence: true
      validates :email, format: { with: /\A[-a-z0-9_+\.]+\@([-a-z0-9]+\.)+[a-z0-9]{2,4}\z/i }
      validates :content, length: { maximum: 500 }
    end

    Para um exemplo mais completo vejo o RailsCast sobre o assunto.

  • A não ser que tenham alguma importância para o regra de negócio, não ponha métodos no seu modelo que somente formata seus dados (como código gerando HTML). Estes métodos provavelmente só serão chamados na camada de view, então o lugar deles é nos helpers. Mantenhas seus modelos somente para regras de negócios e persistência de dados. [link]

ActiveRecord

  • Evite alterar os padrões do ActiveRecord (nomes de tabela, chave primária, etc) a não ser que você tenha uma razão muito boa pra isso (como uma base de dados que não está sob seu controle). [link]

    # ruim - não faça isso se você pode modificar o schema
    class Transaction < ActiveRecord::Base
      self.table_name = 'order'
      ...
    end
  • Agrupe métodos estilo macro (has_many, validates, etc) no início da definição da classe. [link]

    class User < ActiveRecord::Base
      # mantenha o escopo padrão primeiro (se houver)
      default_scope { where(active: true) }
    
      # contantes entram depois
      COLORS = %w(red green blue)
    
      # logo após, colocamos macros attr relacionados
      attr_accessor :formatted_date_of_birth
    
      attr_accessible :login, :first_name, :last_name, :email, :password
    
      # Rails4+ enums depois dos macros attr, prefira sintaxe de hash
      enum gender: { female: 0, male: 1 }
    
      # seguido de associações macros
      belongs_to :country
    
      has_many :authentications, dependent: :destroy
    
      # e validações macros
      validates :email, presence: true
      validates :username, presence: true
      validates :username, uniqueness: { case_sensitive: false }
      validates :username, format: { with: /\A[A-Za-z][A-Za-z0-9._-]{2,19}\z/ }
      validates :password, format: { with: /\A\S{8,128}\z/, allow_nil: true }
    
      # depois nós temos os callbacks
      before_save :cook
      before_save :update_username_lower
    
      # outras macros (como as do devise) devem ser colocadas depois dos callbacks
    
      ...
    end
  • Prefira has_many :through ao has_and_belongs_to_many. Usar has_many :through permite atributos e validações adicionais no modelo. [link]

    # não tão bom - usando has_and_belongs_to_many
    class User < ActiveRecord::Base
      has_and_belongs_to_many :groups
    end
    
    class Group < ActiveRecord::Base
      has_and_belongs_to_many :users
    end
    
    # forma preferida - usando has_many :through
    class User < ActiveRecord::Base
      has_many :memberships
      has_many :groups, through: :memberships
    end
    
    class Membership < ActiveRecord::Base
      belongs_to :user
      belongs_to :group
    end
    
    class Group < ActiveRecord::Base
      has_many :memberships
      has_many :users, through: :memberships
    end
  • Prefira self[:attribute] ao read_attribute(:attribute). [link]

    # ruim
    def amount
      read_attribute(:amount) * 100
    end
    
    # bom
    def amount
      self[:amount] * 100
    end
  • Prefira self[:attribute] = value ao write_attribute(:attribute, value). [link]

    # ruim
    def amount
      write_attribute(:amount, 100)
    end
    
    # bom
    def amount
      self[:amount] = 100
    end
  • Sempre use as novas validações “sexy”. [link]

    # ruim
    validates_presence_of :email
    validates_length_of :email, maximum: 100
    
    # bom
    validates :email, presence: true, length: { maximum: 100 }
  • Quando uma validação customizada é usada mais de uma vez ou a validação é o mapeamento de alguma expressão regular, crie um arquivo de validação customizado. [link]

    # ruim
    class Person
      validates :email, format: { with: /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i }
    end
    
    # bom
    class EmailValidator < ActiveModel::EachValidator
      def validate_each(record, attribute, value)
        record.errors[attribute] << (options[:message] || 'is not a valid email') unless value =~ /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i
      end
    end
    
    class Person
      validates :email, email: true
    end
  • Mantenha validações customizadas dentro de app/validators. [link]

  • Considere extrair validações customizadas para uma gem compartilhada se você está mantendo várias aplicações relacionadas ou se a validação customizada é genérica o suficiente. [link]

  • Use escopos nomeados livremente. [link]

    class User < ActiveRecord::Base
      scope :active, -> { where(active: true) }
      scope :inactive, -> { where(active: false) }
    
      scope :with_orders, -> { joins(:orders).select('distinct(users.id)') }
    end
  • Quando um escopo nomeado é definido com um lambda e os parâmetros ficam muito complicados, é preferível fazer um método de classe que sirva ao mesmo propósito do escopo nomeado e retorne um objeto do tipo ActiveRecord::Relation. Sem dúvida você pode definir escopos ainda mais simples como este. [link]

    class User < ActiveRecord::Base
      def self.with_orders
        joins(:orders).select('distinct(users.id)')
      end
    end
  • Cuidado com o comportamento do método update_attribute. Ele não executa as validações de modelo (diferente do update_attributes) e poderia corromper facilmente o estado do modelo. [link]

  • Use URLs amigáveis. Mostre algum atributo descritivo do modelo na URL diferente do seu id. Existe mais de uma maneira de conseguir isso: [link]

    • Sobrescreva o método to_param do modelo. Esse método é usado pelo Rails para construir uma URL para o objeto. A implementação padrão retorna o id do objeto como uma String. Ele pode ser sobrescrito para incluir algum atributo humano-legível.

      class Person
        def to_param
          "#{id} #{name}".parameterize
        end
      end

    A fim de converter isto para um valor de URL amigável, parameterize deve ser chamado na string. O id do objeto precisa estar no início para que ele possa ser achado pelo método find do ActiveRecord.

    • Use a gem friendly_id. Ela permite a criação de URLs humano-legíveis através do uso de algum atributo descritivo do modelo ao invés do seu id.

      class Person
        extend FriendlyId
        friendly_id :name, use: :slugged
      end

    Veja a documentação da gem para mais informações sobre como usar.

  • Use find_each para iterar sobre uma coleção de objetos do AR. Fazer um looping através de uma coleção de registros da base de dados (usando o método all, por exemplo) é muito ineficiente já que ele irá tentar instanciar todos os objetos de uma só vez. Nesse caso, métodos de processamento batch te permitem trabalhar com registros em batches, reduzindo significativamente o consumo de memória. [link]

    # ruim
    Person.all.each do |person|
      person.do_awesome_stuff
    end
    
    Person.where('age > 21').each do |person|
      person.party_all_night!
    end
    
    # bom
    Person.find_each do |person|
      person.do_awesome_stuff
    end
    
    Person.where('age > 21').find_each do |person|
      person.party_all_night!
    end
  • Desde que o Rails criou callbacks para associações dependentes, sempre chame callbacks before_destroy que façam validação com prepend: true. [link]

    # ruim (roles sempre serão deletados mesmo que super_admin? seja true)
    has_many :roles, dependent: :destroy
    
    before_destroy :ensure_deletable
    
    def ensure_deletable
      fail "Cannot delete super admin." if super_admin?
    end
    
    # bom
    has_many :roles, dependent: :destroy
    
    before_destroy :ensure_deletable, prepend: true
    
    def ensure_deletable
      fail "Cannot delete super admin." if super_admin?
    end
  • Defina a opção dependent para as associações has_many e has_one. [link]

    # ruim
    class Post < ActiveRecord::Base
      has_many :comments
    end
    
    # bom
    class Post < ActiveRecord::Base
      has_many :comments, dependent: :destroy
    end
  • Quando persistir objetos AR sempre use o método com o ponto de exclamação ou manipule o valor retornado pelo método. Isso se aplica ao create, save, update, destroy, first_or_create e find_or_create_by. [link]

    # ruim
    user.create(name: 'Bruce')
    
    # ruim
    user.save
    
    # bom
    user.create!(name: 'Bruce')
    # ou
    bruce = user.create(name: 'Bruce')
    if bruce.persisted?
      ...
    else
      ...
    end
    
    # bom
    user.save!
    # ou
    if user.save
      ...
    else
      ...
    end

Consultas com ActiveRecord

  • Evite interpolação de strings em consultas, isso fará seu código suscetível à ataques de SQL injection. [link]

    # ruim - parâmetros serão interpolados sem escape
    Client.where("orders_count = #{params[:orders]}")
    
    # bom - parâmetros serão propriamente escapados
    Client.where('orders_count = ?', params[:orders])
  • Considere usar espaços reservados nomeados ao invés de espaços reservados posicionais quando tiver mais de um espaço reservado na sua consulta. [link]

    # até vai..
    Client.where(
      'created_at >= ? AND created_at <= ?',
      params[:start_date], params[:end_date]
    )
    
    # bom 
    Client.where(
      'created_at >= :start_date AND created_at <= :end_date',
      start_date: params[:start_date], end_date: params[:end_date]
    )
  • Favoreça o uso de find ao where quando precisar recuperar um único registro pelo id. [link]

    # ruim
    User.where(id: id).take
    
    # bom
    User.find(id)
  • Favoreça o uso de find_by ao where e find_by_attribute quando você precisar recuperar um único registro por alguns atributos. [link]

    # ruim
    User.where(first_name: 'Bruce', last_name: 'Wayne').first
    
    # ruim
    User.find_by_first_name_and_last_name('Bruce', 'Wayne')
    
    # bom
    User.find_by(first_name: 'Bruce', last_name: 'Wayne')
  • Favoreça o uso de where.not ao SQL. [link]

    # ruim
    User.where("id != ?", id)
    
    # bom
    User.where.not(id: id)
  • Quando especificar uma consulta explícita em um método tal como find_by_sql, use heredocs com squish. Isso permite formatar legivelmente o SQL com quebra de linhas e indentações, enquanto suporta destaque de sintaxe em muitas ferramentas (incluindo o GitHub, Atom e RubyMine). [link]

    User.find_by_sql(<<-SQL.squish)
      SELECT
        users.id, accounts.plan
      FROM
        users
      INNER JOIN
        accounts
      ON
        accounts.user_id = users.id
      # further complexities...
    SQL

    String#squish remove os caracteres de indentação e de nova linha para que o log do servidor mostra uma string de SQL fluida em ve de algo como isso:

    SELECT\n    users.id, accounts.plan\n  FROM\n    users\n  INNER JOIN\n    acounts\n  ON\n    accounts.user_id = users.id
    

Migrações

  • Mantenha o schema.rb (ou structure.sql) sob controle de versão. [link]

  • Use rake db:schema:load em vez de rake db:migrate para inicializar um banco de dados vazio. [link]

  • Imponha valores padrões nas próprias migrações em vez de colocar na camada de aplicação. [link]

    # ruim - aplicação impõe valor padrão
    def amount
      self[:amount] or 0
    end

    Mesmo a imposição de padrões só no Rails sendo defendida por muitos desenvolvedores Rails, essa é uma abordagem extremamente frágil que deixa seus dados vulneráveis a muitos erros de aplicação. E você terá que considerar o fato de que aplicações não triviais compartilham um banco de dados com outras aplicações, logo impor integridade de dados na aplicação Rails é impossível.

  • Imponha restrições de chave estrangeira. Como do Rails 4.2, ActiveRecord suporta restrições de chave estrangeira nativamente. [link]

  • Ao escrever migrações construtivas (adicionar tabelas ou colunas) use o método change ao invés dos métodos up e down. [link]

    # jeito antigo
    class AddNameToPeople < ActiveRecord::Migration
      def up
        add_column :people, :name, :string
      end
    
      def down
        remove_column :people, :name
      end
    end
    
    # o jeito novo
    class AddNameToPeople < ActiveRecord::Migration
      def change
        add_column :people, :name, :string
      end
    end
  • Não use classes modelo em migrações. As classes modelos estão constantemente evoluindo e, em algum ponto no futuro, as migrações que costumavam funcionar podem parar por causa das mudanças no modelo usado. [link]

  • Nomeie sua chave estrangeira explicitamente em vez de confiar nos nomes de chave estrangeira automaticamente gerados pelo Rails. (http://edgeguides.rubyonrails.org/active_record_migrations.html#foreign-keys)

    # ruim
    class AddFkArticlesToAuthors < ActiveRecord::Migration
      def change
        add_foreign_key :articles, :authors
      end
    end
    
    # bom
    class AddFkArticlesToAuthors < ActiveRecord::Migration
      def change
        add_foreign_key :articles, :authors, name: :articles_author_id_fk
      end
    end

[link]

Views

  • Nunca chame a camada de modelo diretamente da view. [link]

  • Nunca faça formatação complexa em views, exporte a formatação para um método no helper ou no modelo. [link]

  • Reduza a duplicação de código através do uso de partials e layouts. [link]

Internacionalização

  • Nenhuma string ou outra configuração local específica deveria ser usada nas views, modelos e controladores. Esses textos deveriam ser movidos para os arquivos de localidade no diretório config/locales. [link]

  • Quando as labels de um modelo do ActiveRecord precisarem ser traduzidas, use o escopo activerecord: [link]

    en:
      activerecord:
        models:
          user: Member
        attributes:
          user:
            name: 'Full name'
    

    Logo User.model_name.human irá retornar "Member" e User.human_attribute_name("name") irá retornar "Full name". Essas traduções de atributos serão usadas como labels nas views.

  • Separe os textos usados nas views das traduções de atributos do ActiveRecord. Coloque os arquivos de localidade para modelos na pasta locales/models e os textos usados nas views na pasta locales/views. [link]

    • Quando a organização dos arquivos de localidade estiverem prontos com os diretórios adicionais, estes diretórios devem ser descritos no arquivo application.rb em ordem de carregamento.

      # config/application.rb
      config.i18n.load_path += Dir[Rails.root.join('config', 'locales', '**', '*.{rb,yml}')]
  • Coloque as opções de localização compartilhada, tal como datas e formatos de moedas, em arquivos sob a raiz do diretório locales. [link]

  • Use o formato curto dos métodos do I18n: I18n.t em vez de I18n.translate e I18n.l em vez de I18n.localize. [link]

  • Use pesquisa ”preguiçosa” para os textos nas views. Digamos que temos a seguinte estrutura: [link]

    en:
      users:
        show:
          title: 'User details page'
    

    O valor de users.show.title pode ser pesquisado no template app/views/users/show.html.haml dessa forma:

    = t '.title'
  • Use as chaves separadas por ponto nos controladores e nos modelos ao invés de especificar a opção :scope. As chamadas separadas por ponto são mais fáceis de ler e traçar sua hierarquia. [link]

    # ruim
    I18n.t :record_invalid, scope: [:activerecord, :errors, :messages]
    
    # bom
    I18n.t 'activerecord.errors.messages.record_invalid'
  • Informações mais detalhadas sobre o Rails I18n podem ser encontradas no Rails Guides [link]

Assets

Use o assets pipeline para aumentar a organização dentro da sua aplicação.

Mailers

  • Nomeie os mailers como AlgumaCoisaMailer. Sem o sufixo Mailer não fica claro qual é o Mailer e a quais views ele está relacionado. [link]

  • Providencie ambos templates de view em HTML texto plano. [link]

  • Habilite elevação de erros ao tentar enviar email no ambiente de desenvolvimento. Os erros são desabilitados por padrão. [link]

    # config/environments/development.rb
    
    config.action_mailer.raise_delivery_errors = true
  • Use um servidor SMTP local como o Mailcatcher no ambiente de desenvolvimento. [link]

    # config/environments/development.rb
    
    config.action_mailer.smtp_settings = {
      address: 'localhost',
      port: 1025,
      # mais configurações
    }
  • Providencie configurações padrões para o nome do host. [link]

    # config/environments/development.rb
    config.action_mailer.default_url_options = { host: "#{local_ip}:3000" }
    
    # config/environments/production.rb
    config.action_mailer.default_url_options = { host: 'seu_site.com' }
    
    # na sua classe mailer
    default_url_options[:host] = 'seu_site.com'
  • Se você precisa usar um link para o seu site no email, sempre use o _url, e não métodos _path. Os métodos _url incluem o nome do host e os métodos _path não. [link]

    # ruim
    Você pode encontrar mais informações sobre esse curso 
    <%= link_to 'aqui', curso_path(@curso) %>
    
    # bom
    ocê pode encontrar mais informações sobre esse curso 
    <%= link_to 'aqui', curso_url(@curso) %>
  • Formate os endereços de from e to devidamente. Use o seguinte formato: [link]

    # na sua classe mailer
    default from: 'Seu nome <info@seu_site.com>'
  • Tenha certeza que o método de envio de email para seu ambiente de teste está configurado para test: [link]

    # config/environments/test.rb
    
    config.action_mailer.delivery_method = :test
  • O método de envio para desenvolvimento e produção devem ser smtp: [link]

    # config/environments/development.rb, config/environments/production.rb
    
    config.action_mailer.delivery_method = :smtp
  • Quando enviar emails html todos os estilos devem estar em linha, já que alguns clientes de email têm problemas com estilos externos. Entretanto, isso os faz mais difíceis de manter e leva a uma duplicação de código. Existem duas gems similares que transformam os estilos em os põe em correspondentes tags html: premailer-rails e roadie. [link]

  • Enviar emails enquanto gera resposta para página deveria ser evitado. Isso causa atrasos no carregamento da página e pode dar timeout na requisição se múltiplos emails são enviados. Para superar isso, emails podem ser enviados em um processo em background com a ajuda da gem sidekiq. [link]

Extensões de núcleo do Active Support

  • Prefira o operador de navegação seguro do Ruby 2.3's &. em vez de ActiveSupport#try!. [link]
# ruim
obj.try! :fly

# bom
obj&.fly
  • Prefira métodos da Biblioteca Padrão do Ruby ao invés de alias do ActiveSupport. [link]
# ruim
'the day'.starts_with? 'th'
'the day'.ends_with? 'ay'

# bom
'the day'.start_with? 'th'
'the day'.end_with? 'ay'
  • Prefira a Biblioteca Padrão do Ruby ao invés de extensões incomuns do ActiveSupport. [link]
# ruim
(1..50).to_a.forty_two
1.in? [1, 2]
'day'.in? 'the day'

# bom
(1..50).to_a[41]
[1, 2].include? 1
'the day'.include? 'day'
  • Prefira os operadores de comparação do Ruby ao invés dos Array#inquiry, Numeric#inquiry e String#inquiry do ActiveSupport. [link]
# ruim - String#inquiry
ruby = 'two'.inquiry
ruby.two?

# bom
ruby = 'two'
ruby == 'two'

# ruim - Array#inquiry
pets = %w(cat dog).inquiry
pets.gopher?

# bom
pets = %w(cat dog)
pets.include? 'cat'

# ruim - Numeric#inquiry
0.positive?
0.negative?

# bom
0 > 0
0 < 0

Time

  • Configure seu timezone devidamente no application.rb. [link]

    config.time_zone = 'Eastern European Time'
    # opcional - note que ele só pode ser :utc ou :local (o padrão é :utc)
    config.active_record.default_timezone = :local
  • Não use Time.parse. [link]

    # ruim
    Time.parse('2015-03-02 19:05:37') # => Irá assumir que a string com a hora que foi passada está no timezone do sistema.
    
    # bom
    Time.zone.parse('2015-03-02 19:05:37') # => Mon, 02 Mar 2015 19:05:37 EET +02:00
  • Não use Time.now. [link]

    # ruim
    Time.now # => Retorna hora do sistema e ignora sua configuração de timezone.
    
    # bom
    Time.zone.now # => Fri, 12 Mar 2014 22:04:47 EET +02:00
    Time.current # mesma coisa só que menor.

Bundler

  • Ponha as gems que são usadas só em desenvolvimento e teste dentro de um grupo apropriado no Gemfile. [link]

  • Use somente gems estáveis nos seus projetos. Se você está pensando em usar uma gem pouco conhecida, você deveria dar uma revisada cuidadosa no código fonte dela primeiro. [link]

  • Gems específicas de sistemas operacionais irão, por padrão, resultar em constantes mudanças no Gemfile.lock para projetos com muitos desenvolvedores usando diferentes sistemas operacionais. Adicione todas a gems específicas do OS X ao grupo darwin no Gemfile, e todas as gems específicas do Linux ao grupo linux: [link]

    # Gemfile
    group :darwin do
      gem 'rb-fsevent'
      gem 'growl'
    end
    
    group :linux do
      gem 'rb-inotify'
    end

    Para incluir as gems apropriadas nos ambientes corretos, adicione o seguinte ao config/application.rb:

    platform = RUBY_PLATFORM.match(/(linux|darwin)/)[0].to_sym
    Bundler.require(platform)
  • Não remova o Gemfile.lock do controle de versão. Ele não é um tipo de arquivo gerado randomicamente - ele te dá certeza de que todos os membros da sua equipe tenham as mesmas versões de gems quando executarem o bundle install. [link]

Gerenciamento de processos

  • Se seu projeto depende de vários processos externos use o foreman para gerenciá-los. [link]

Leitura Adicional

Existem alguns recursos excelentes no estilo Rails que você deveria considerar, se você tiver tempo sobrando:

Contribuindo

Nada escrito neste manual está escrito em pedra. O meu desejo é trabalhar em conjunto com todos interessados no estilo de programação Rails, para que por fim assim nós possamos criar um recurso que irá beneficiar a comunidade de Ruby inteira. Sinta-se livre para abrir tickets ou enviar pull requests com melhorias. Desde já agradeço pela sua ajuda!

Você pode também pode ajudar o projeto (e o RuboCop) com contribuições financeiras via gittip.

Ajuda via Gittip

Como contribuir?

Isso é fácil! É só seguir as orientações de contribuição.

Licensa

Creative Commons License Esse trabalho está licenciado sob Creative Commons Attribution 3.0 Unported License

Avise a todos

Um guia de estilo voltado para a comunidade é de pouca utilidade se a comunidade não sabe sobre sua existência. Tweet sobre o guia, compartilhe com seus amigos e colegas. Todo comentário, sugestão e opinião que tivermos fará o guia só um pouco melhor. E nós queremos ter o melhor guia possível, não é mesmo?

Até mais,
Bozhidar