rails_model.rb | 
      |
|---|---|
| 
        
         This guide applies to a Ruby on Rails ActiveRecord Model class. It is part of Jo Hund’s Software Engineering Guide. This convention puts the most important information about a model at the top.  | 
      
         | 
    
        class Project < ActiveRecord::Base
   | 
    |
| 
        
         Include other modules: They add new behavior to the model. We want to know about this right away.  | 
      
          include Canable::Permissions
   | 
    
| 
        
         Rails macros: They, too add implicit behavior to our model.  | 
      
          acts_as_list
  default_scope order("name ASC")
     | 
    
| 
        
         ActiveRecord callbacks: They add important behavior to our model. It’s also important to specify callbacks before associations in order for inheritance to work for the callback queues. Otherwise, you might trigger the loading of a child before the parent has registered the callbacks and they won’t be inherited. (From Rails' ActiveRecord::Callbacks documentation) 
  | 
      
          before_create :set_start_date # no dependencies, do this first
  before_save :update_duration # after set_start_date so we can use start date for calculation
   | 
    
| 
        
         ActiveRecord associations: They tell us how this model interacts with other models. 
  | 
      
          belongs_to :client, :inverse_of => :projects
  has_many :collaborators, :dependent => :nullify, :inverse_of => :project
  has_many :todos, :order => "position ASC", :dependent => :destroy, :inverse_of => :project
  has_many :persons_responsible,
    :through => :collaborators,
    :uniq => true,
    :source => :person,
    :order => "persons.email ASC" | 
    
| 
        
         Validations  | 
      
          validates_presence_of :name
   | 
    
| 
        
         Scopes (formerly known as named_scopes) 
  | 
      
          scope :active, where(:state => "active")
  scope :sorted_by lambda { |sort_key|
    case sort_key
    when "date_asc"; "projects.created_at ASC"
    ...
    end
  }
  scope :complicated,
    where("other_table.some_value = ?", value).
    order("position ASC").
    joins("other_table").
    limit(10)
     | 
    
| 
        
         Miscellaneous Declarations: 
  | 
      
          attr_protected :client_id
  alias_method ... | 
    
| 
        
         I prefer the demeter ruby extension over Rails' delegate for delegation.  | 
      
          demeter :client_name, :to => :client, :using => :name
   | 
    
| 
        
         Class Methods  I prefer the   | 
      
          def self.class_method_1
  end
  
  def self.class_method_2
  end
   | 
    
| 
        
         Instance Methods  | 
      
          def instance_method_1(arg1)
  end
  
  def instance_method_2(arg1)
  end
   | 
    
| 
        
         Permissions Permissions are all grouped together (both class and instance methods)  | 
      
          def self.listable_by?(actor)
    actor.is_admin?
  end
  
  def updatable_by?(actor)
    owned_by?(actor)
  end
  
  def owned_by?(actor)
    actor == person
  end
   | 
    
| 
        
          Protected Methods: The   | 
      
        protected
  def protected_method
  end
   | 
    
| 
        
          Private Methods: The   | 
      
        private
  def set_start_date
    self.started_at = Time.zone.now
  end
end | 
    
| 
        
         This document was generated with rocco.rb © Jo Hund  | 
      
         |