Каков правильный порядок ассоциаций, областей, валидаций и т.д. В моделях Rails

Отредактировал этот старый вопрос, чтобы включить ответ снизу: он есть у Rubocop https://github.com/rubocop-hq/rails-style-guide#macro-style-methods

Rails - это "Соглашение о конфигурации". Однако я еще не встречал "стандарта" для порядка ассоциаций, областей действия, включений, проверок... в моделях Rails. Возьмем, к примеру, следующую упрощенную модель продукта:

class Product < ActiveRecord::Base
  mount_uploader :logo, AssetUploader
  acts_as_taggable
  paginates_per 50

  include ActionView::Helpers::NumberHelper

  belongs_to :company

  validates_presence_of [:title, :price, :plu]

  scope :on_website, where(display: true)

  def display_price
    ...
  end
end

Это правильный порядок? Может быть, это не так важно для многих людей, но я лично думаю, что было бы замечательно, если бы было соглашение по этому вопросу.

Ответ 1

У Рубокопа есть https://github.com/rubocop-hq/rails-style-guide#macro-style-methods

class User < ActiveRecord::Base
  # keep the default scope first (if any)
  default_scope { where(active: true) }

  # constants come up next
  COLORS = %w(red green blue)

  # afterwards we put attr related macros
  attr_accessor :formatted_date_of_birth

  attr_accessible :login, :first_name, :last_name, :email, :password

  # Rails 4+ enums after attr macros
  enum gender: { female: 0, male: 1 }

  # followed by association macros
  belongs_to :country

  has_many :authentications, dependent: :destroy

  # and validation 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 }

  # next we have callbacks
  before_save :cook
  before_save :update_username_lower

  # other macros (like devise's) should be placed after the callbacks

  ...
end

Ответ 2

Такого соглашения нет. Но вы можете создать его для своего проекта и быть совместимым с ним во всех моделях. Это то, что я следую.

class Model < ActiveRecord::Base
   #all mixins
   include Something
   extend Something

   #other stuff
   acts_as_taggable
   paginates

   #associations
   has_many :something
   belongs_to :something_else

   #validations
   validate_presence_of :something

   #scopes
   scope :something

   #instance methods
   def instance_method
   end

   #class methods
   def self.method
   end

   #private methods
   private
   def method2
   end
end