diff options
author | Eric Davis <edavis@littlestreamsoftware.com> | 2009-05-30 23:30:36 +0000 |
---|---|---|
committer | Eric Davis <edavis@littlestreamsoftware.com> | 2009-05-30 23:30:36 +0000 |
commit | 62e58f26b0c6905fc0b2d79ed278ac0e4f55d793 (patch) | |
tree | 6989cbc655e9ffee0db9b7558985cd77d28b0edb /app/models/enumeration.rb | |
parent | fbfb34949677c41734531a552547fb216537999f (diff) | |
download | redmine-62e58f26b0c6905fc0b2d79ed278ac0e4f55d793.tar.gz redmine-62e58f26b0c6905fc0b2d79ed278ac0e4f55d793.zip |
Changed Enumerations to use a Single Table Inheritance
* Added migrations to change Enumerations to an STI relationship
* Added TimeEntryActivity model (STI)
* Added DocumentCategory model (STI)
* Added IssuePriority model (STI)
* Added Enumeration#get_subclasses to get a list of the subclasses of Enumeration
* Changed Enumeration to use the STI type field instead of the opt field
* Changed Enumeration#opt to return the old opt values but with a deprecation warning.
* Removed Enumeration::OPTIONS
* Removed the dynamic named_scopes in favor of specific named_scopes. Kept for
compatibility reasons.
* Added Enumeration#default so each subclass can easily find it's default record.
* Fixed Enumeration#default to use the STI scoping with a fake default scope for finding Enumeration's default.
* Added a 'all' named scope for getting all records in order by position.
* Added Deprecation warnings to the old named_scopes in Enumerations.
* Moved various methods off of Enumeration and onto the concrete classes
* Changed the EnumerationsController to use types
* Updated the Enumeration list template
* Added has_many relationships to the Enumeration STI classes.
* Fixes for tests.
#3007
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@2777 e93f8b46-1217-0410-a6f0-8f06a7374b81
Diffstat (limited to 'app/models/enumeration.rb')
-rw-r--r-- | app/models/enumeration.rb | 90 |
1 files changed, 64 insertions, 26 deletions
diff --git a/app/models/enumeration.rb b/app/models/enumeration.rb index d466940b7..380a4d3d2 100644 --- a/app/models/enumeration.rb +++ b/app/models/enumeration.rb @@ -16,53 +16,77 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. class Enumeration < ActiveRecord::Base - acts_as_list :scope => 'opt = \'#{opt}\'' + acts_as_list :scope => 'type = \'#{type}\'' before_destroy :check_integrity - validates_presence_of :opt, :name - validates_uniqueness_of :name, :scope => [:opt] + validates_presence_of :name + validates_uniqueness_of :name, :scope => [:type] validates_length_of :name, :maximum => 30 - - # Single table inheritance would be an option - OPTIONS = { - "IPRI" => {:label => :enumeration_issue_priorities, :model => Issue, :foreign_key => :priority_id, :scope => :priorities}, - "DCAT" => {:label => :enumeration_doc_categories, :model => Document, :foreign_key => :category_id, :scope => :document_categories}, - "ACTI" => {:label => :enumeration_activities, :model => TimeEntry, :foreign_key => :activity_id, :scope => :activities} - }.freeze - # Creates a named scope for each type of value. The scope has a +default+ method - # that returns the default value, or nil if no value is set as default. - # Example: - # Enumeration.priorities - # Enumeration.priorities.default - OPTIONS.each do |k, v| - next unless v[:scope] - named_scope v[:scope], :conditions => { :opt => k }, :order => 'position' do - def default - find(:first, :conditions => { :is_default => true }) - end + # Backwards compatiblity named_scopes. + # Can be removed post-0.9 + named_scope :priorities, :conditions => { :type => "IssuePriority" }, :order => 'position' do + ActiveSupport::Deprecation.warn("Enumeration#priorities is deprecated, use the IssuePriority class. (#{Redmine::Info.issue(3007)})") + def default + find(:first, :conditions => { :is_default => true }) + end + end + + named_scope :document_categories, :conditions => { :type => "DocumentCategory" }, :order => 'position' do + ActiveSupport::Deprecation.warn("Enumeration#document_categories is deprecated, use the DocumentCategories class. (#{Redmine::Info.issue(3007)})") + def default + find(:first, :conditions => { :is_default => true }) + end + end + + named_scope :activities, :conditions => { :type => "TimeEntryActivity" }, :order => 'position' do + ActiveSupport::Deprecation.warn("Enumeration#activities is deprecated, use the TimeEntryActivity class. (#{Redmine::Info.issue(3007)})") + def default + find(:first, :conditions => { :is_default => true }) end end - named_scope :values, lambda {|opt| { :conditions => { :opt => opt }, :order => 'position' } } do + named_scope :values, lambda {|type| { :conditions => { :type => type }, :order => 'position' } } do def default find(:first, :conditions => { :is_default => true }) end end + named_scope :all, :order => 'position' + + def self.default + # Creates a fake default scope so Enumeration.default will check + # it's type. STI subclasses will automatically add their own + # types to the finder. + if self.descends_from_active_record? + find(:first, :conditions => { :is_default => true, :type => 'Enumeration' }) + else + # STI classes are + find(:first, :conditions => { :is_default => true }) + end + end + + # Overloaded on concrete classes def option_name - OPTIONS[self.opt][:label] + nil + end + + # Backwards compatiblity. Can be removed post-0.9 + def opt + ActiveSupport::Deprecation.warn("Enumeration#opt is deprecated, use the STI classes now. (#{Redmine::Info.issue(3007)})") + return OptName end def before_save if is_default? && is_default_changed? - Enumeration.update_all("is_default = #{connection.quoted_false}", {:opt => opt}) + Enumeration.update_all("is_default = #{connection.quoted_false}", {:type => type}) end end + # Overloaded on concrete classes def objects_count - OPTIONS[self.opt][:model].count(:conditions => "#{OPTIONS[self.opt][:foreign_key]} = #{id}") + 0 end def in_use? @@ -75,7 +99,7 @@ class Enumeration < ActiveRecord::Base # If a enumeration is specified, objects are reassigned def destroy(reassign_to = nil) if reassign_to && reassign_to.is_a?(Enumeration) - OPTIONS[self.opt][:model].update_all("#{OPTIONS[self.opt][:foreign_key]} = #{reassign_to.id}", "#{OPTIONS[self.opt][:foreign_key]} = #{id}") + self.transfer_relations(reassign_to) end destroy_without_reassign end @@ -85,9 +109,23 @@ class Enumeration < ActiveRecord::Base end def to_s; name end + + # Returns the Subclasses of Enumeration. Each Subclass needs to be + # required in development mode. + # + # Note: subclasses is protected in ActiveRecord + def self.get_subclasses + @@subclasses[Enumeration] + end private def check_integrity raise "Can't delete enumeration" if self.in_use? end + end + +# Force load the subclasses in development mode +require_dependency 'time_entry_activity' +require_dependency 'document_category' +require_dependency 'issue_priority' |