100 lines
2.8 KiB
Ruby
100 lines
2.8 KiB
Ruby
class Profile < ActiveRecord::Base
|
|
belongs_to :context, :polymorphic => true
|
|
belongs_to :root_account, :class_name => 'Account'
|
|
|
|
attr_accessible :context, :root_account, :title, :path, :description, :visibility, :position
|
|
|
|
serialize :data
|
|
|
|
validates_presence_of :root_account
|
|
validates_presence_of :context
|
|
validates_length_of :title, :within => 0..255
|
|
validates_length_of :path, :within => 0..255
|
|
validates_format_of :path, :with => /\A[a-z0-9-]+\z/
|
|
validates_uniqueness_of :path, :scope => :root_account_id
|
|
validates_uniqueness_of :context_id, :scope => :context_type
|
|
validates_inclusion_of :visibility, :in => %w{ public private }
|
|
|
|
self.abstract_class = true
|
|
|
|
def title=(title)
|
|
write_attribute(:title, title)
|
|
write_attribute(:path, infer_path) if path.nil?
|
|
title
|
|
end
|
|
|
|
def infer_path
|
|
return nil unless title
|
|
path = base_path = title.downcase.gsub(/[^a-z0-9]+/, '-').gsub(/\A\-+|\-+\z/, '')
|
|
count = 0
|
|
while profile = Profile.find_by_root_account_id_and_path(root_account_id, path)
|
|
break if profile.id == id
|
|
path = "#{base_path}-#{count += 1}"
|
|
end
|
|
path
|
|
end
|
|
|
|
def data
|
|
read_attribute(:data) || write_attribute(:data, {})
|
|
end
|
|
|
|
def self.data(field, options = {})
|
|
options[:type] = :string
|
|
define_method(field) {
|
|
data.has_key?(field) ? data[field] : data[field] = options[:default]
|
|
}
|
|
define_method("#{field}=") { |value|
|
|
data[field] = sanitize_data(value, options)
|
|
}
|
|
end
|
|
|
|
def sanitize_data(value, options)
|
|
case options[:type]
|
|
when :int; value.to_i
|
|
else value
|
|
end
|
|
end
|
|
|
|
# some tricks to make it behave like STI with a type column
|
|
def self.inherited(klass)
|
|
super
|
|
context_type = klass.name.sub(/Profile\z/, '')
|
|
klass.class_eval { alias_method context_type.downcase.underscore, :context }
|
|
klass.instance_eval { def table_name; "profiles"; end }
|
|
klass.default_scope :conditions => ["context_type = ?", context_type]
|
|
end
|
|
|
|
def self.columns_hash
|
|
not_set = @columns_hash.nil?
|
|
super
|
|
if not_set
|
|
def @columns_hash.include?(key)
|
|
key == "type" || super
|
|
end
|
|
end
|
|
@columns_hash
|
|
end
|
|
|
|
def self.instantiate(record)
|
|
record["type"] = "#{record["context_type"]}Profile"
|
|
super
|
|
end
|
|
|
|
module Association
|
|
def self.included(klass)
|
|
klass.has_one :profile, :as => :context
|
|
klass.class_eval <<-CODE, __FILE__, __LINE__ + 1
|
|
def profile_with_correct_class
|
|
profile_without_correct_class || begin
|
|
profile = #{klass.to_s}Profile.new(:context => self)
|
|
profile.root_account = root_account
|
|
profile.title = name
|
|
profile.visibility = "private"
|
|
profile
|
|
end
|
|
end
|
|
alias_method_chain :profile, :correct_class
|
|
CODE
|
|
end
|
|
end
|
|
end |