summaryrefslogtreecommitdiffstats
path: root/app/models/enumeration.rb
diff options
context:
space:
mode:
authorEric Davis <edavis@littlestreamsoftware.com>2009-05-30 23:30:36 +0000
committerEric Davis <edavis@littlestreamsoftware.com>2009-05-30 23:30:36 +0000
commit62e58f26b0c6905fc0b2d79ed278ac0e4f55d793 (patch)
tree6989cbc655e9ffee0db9b7558985cd77d28b0edb /app/models/enumeration.rb
parentfbfb34949677c41734531a552547fb216537999f (diff)
downloadredmine-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.rb90
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'