module RequiresApproval::ClassMethods

Public Instance Methods

prepare_tables_for_requires_approval() click to toggle source

adds the correct tables and columns for requires_approval

# File lib/requires_approval.rb, line 197
def prepare_tables_for_requires_approval
  self.reset_column_information

  # adds is_active to the parent table
  self.add_requires_approval_fields
  self.reset_column_information

  # adds our versions table
  self.drop_versions_table
  self.create_versions_table
  
end
requires_approval_for(*attrs) click to toggle source
# File lib/requires_approval.rb, line 210
def requires_approval_for(*attrs)
  self.set_options(attrs.extract_options!)

  # set up our attributes that require approval
  self.class_attribute :fields_requiring_approval
  self.fields_requiring_approval = attrs.collect(&:to_s)

  # set up delegates
  self.set_up_version_delegates

  # create a blank version before create to handle if no
  # attributes were ever set
  self.before_validation_on_create(
    :latest_unapproved_version_with_nil_check
  )
  
  # create the versions class
  self.create_versions_class
  self.has_many :versions, 
    :class_name => self.versions_class.name,
    :foreign_key => self.versions_foreign_key

  self.has_one :latest_unapproved_version,
    :autosave => true,
    :class_name => self.versions_class.name,
    :foreign_key => self.versions_foreign_key,
    :conditions => [
      "#{self.versions_table_name}.is_approved = ?", false
    ]

  self.set_up_scopes


end
versions_class() click to toggle source

the class which our versions are

# File lib/requires_approval.rb, line 246
def versions_class
  "#{self.name}::#{self.versions_class_name}".constantize
end

Protected Instance Methods

add_requires_approval_fields() click to toggle source
# File lib/requires_approval.rb, line 252
def add_requires_approval_fields
  # add is_frozen
  unless self.column_names.include?("is_frozen")
    self.connection.add_column(
      self.table_name, :is_frozen, :boolean, :default => true
    )
  end
  # add is_deleted
  unless self.column_names.include?("is_deleted")
    self.connection.add_column(
      self.table_name, :is_deleted, :boolean, :default => false
    )
  end
  true
end
create_versions_class() click to toggle source

create a class

# File lib/requires_approval.rb, line 269
def create_versions_class
  versions_table_name = self.versions_table_name
  
  self.const_set self.versions_class_name, Class.new(ActiveRecord::Base)
  
  self.versions_class.class_eval do
    self.table_name = versions_table_name
  end
end
create_versions_table() click to toggle source
# File lib/requires_approval.rb, line 279
def create_versions_table
  self.connection.create_table(self.versions_table_name) do |t|
    self.columns.each do |column|
      t.send(column.type, column.name, {
        :default => column.default,
        :limit => column.limit,
        :null => column.null,
        :precision => column.precision,
        :scale => column.scale
      })
    end
    t.integer self.versions_foreign_key
    t.boolean :is_approved, :default => false
  end
  self.connection.add_index(
    self.versions_table_name,
    [self.versions_foreign_key, :is_approved]
  )
end
drop_versions_table() click to toggle source

drop the versions table if it exists

# File lib/requires_approval.rb, line 300
def drop_versions_table
  if self.connection.tables.include?(self.versions_table_name)
    self.connection.drop_table(self.versions_table_name)
  end
end
set_options(opts = {}) click to toggle source
# File lib/requires_approval.rb, line 306
def set_options(opts = {})
  @versions_class_name = opts.delete(:versions_class_name)
  @version_foreign_key = opts.delete(:versions_foreign_key)
  @versions_table_name = opts.delete(:versions_table_name)
end
set_up_scopes() click to toggle source
# File lib/requires_approval.rb, line 312
def set_up_scopes
  self.named_scope(:unapproved, {
    :include => [:latest_unapproved_version],
    :conditions => [
      "#{self.versions_table_name}.id IS NOT NULL"
    ]
  })
end
set_up_version_delegates() click to toggle source
# File lib/requires_approval.rb, line 321
def set_up_version_delegates
  self.fields_requiring_approval.each do |f|
    define_method("#{f}=") do |val|
      # type cast our val so "0" changes to 'false'
      type_casted_val = self.column_for_attribute(f).type_cast(val)
      
      # if we have a latest_unapproved version already, let it handle
      # updates - if not, only create one if the type casted value is
      # not the same as what is in the parent value
      if self.latest_unapproved_version.present? || 
        type_casted_val != self.send(f)
        
        self.send("#{f}_will_change!")
        self.latest_unapproved_version_with_nil_check.send("#{f}=", val)
      end
    end
  end
end
versions_class_name() click to toggle source

class name for our versions

# File lib/requires_approval.rb, line 341
def versions_class_name
  @versions_class_name ||= "Version"
end
versions_foreign_key() click to toggle source

foreign key for our class on the version table

# File lib/requires_approval.rb, line 346
def versions_foreign_key
  @version_foreign_key ||= "#{self.base_class.name.underscore}_id"
end
versions_table_name() click to toggle source

table name for our versions

# File lib/requires_approval.rb, line 351
def versions_table_name
  @versions_table_name ||= "#{self.base_class.name.underscore}_versions"
end