Permalink
Browse files

Add ActiveRecord option to store the full class name on STI's type co…

…lumn, allowing one to have STI subclasses in different namespaces [#114]

Signed-off-by: rick <technoweenie@gmail.com>
  • Loading branch information...
divoxx authored and technoweenie committed Apr 11, 2008
1 parent 2d372d7 commit bca8751e40a5594c4de2ca58e089b8d98e44632b
@@ -439,6 +439,10 @@ def self.reset_subclasses #:nodoc:
cattr_accessor :schema_format , :instance_writer => false
@@schema_format = :ruby
+ # Determine whether to store the full constant name including namespace when using STI
+ superclass_delegating_accessor :store_full_sti_class
+ self.store_full_sti_class = false
+
class << self # Class methods
# Find operates with four different retrieval approaches:
#
@@ -1557,8 +1561,8 @@ def add_conditions!(sql, conditions, scope = :auto)
def type_condition
quoted_inheritance_column = connection.quote_column_name(inheritance_column)
- type_condition = subclasses.inject("#{quoted_table_name}.#{quoted_inheritance_column} = '#{name.demodulize}' ") do |condition, subclass|
- condition << "OR #{quoted_table_name}.#{quoted_inheritance_column} = '#{subclass.name.demodulize}' "
+ type_condition = subclasses.inject("#{quoted_table_name}.#{quoted_inheritance_column} = '#{store_full_sti_class ? name : name.demodulize}' ") do |condition, subclass|
+ condition << "OR #{quoted_table_name}.#{quoted_inheritance_column} = '#{store_full_sti_class ? subclass.name : subclass.name.demodulize}' "
end
" (#{type_condition}) "
@@ -2492,7 +2496,7 @@ def create
# Message class in that example.
def ensure_proper_type
unless self.class.descends_from_active_record?
- write_attribute(self.class.inheritance_column, Inflector.demodulize(self.class.name))
+ write_attribute(self.class.inheritance_column, store_full_sti_class ? self.class.name : Inflector.demodulize(self.class.name))
end
end
@@ -5,6 +5,34 @@
class InheritanceTest < ActiveRecord::TestCase
fixtures :companies, :projects, :subscribers, :accounts
+
+ def test_should_store_demodulized_class_name_with_store_full_sti_class_option_disabled
+ old = ActiveRecord::Base.store_full_sti_class
+ ActiveRecord::Base.store_full_sti_class = false
+ item = Namespaced::Company.new
+ assert_equal 'Company', item[:type]
+ ensure
+ ActiveRecord::Base.store_full_sti_class = old
+ end
+
+ def test_should_store_full_class_name_with_store_full_sti_class_option_enabled
+ old = ActiveRecord::Base.store_full_sti_class
+ ActiveRecord::Base.store_full_sti_class = true
+ item = Namespaced::Company.new
+ assert_equal 'Namespaced::Company', item[:type]
+ ensure
+ ActiveRecord::Base.store_full_sti_class = old
+ end
+
+ def test_different_namespace_subclass_should_load_correctly_with_store_full_sti_class_option
+ old = ActiveRecord::Base.store_full_sti_class
+ ActiveRecord::Base.store_full_sti_class = true
+ item = Namespaced::Company.create :name => "Wolverine 2"
+ assert_not_nil Company.find(item.id)
+ assert_not_nil Namespaced::Company.find(item.id)
+ ensure
+ ActiveRecord::Base.store_full_sti_class = old
+ end
def test_company_descends_from_active_record
assert_raise(NoMethodError) { ActiveRecord::Base.descends_from_active_record? }
@@ -15,6 +15,10 @@ def arbitrary_method
end
end
+module Namespaced
+ class Company < ::Company
+ end
+end
class Firm < Company
has_many :clients, :order => "id", :dependent => :destroy, :counter_sql =>
@@ -7,6 +7,9 @@
# Include ActiveRecord class name as root for JSON serialized output.
ActiveRecord::Base.include_root_in_json = true
+# Store the full class name (including module namespace) in STI type column
+ActiveRecord::Base.store_full_sti_class = true
+
# Use ISO 8601 format for JSON serialized times and dates
ActiveSupport.use_standard_json_time_format = true

2 comments on commit bca8751

@duncanbeevers

This comment has been minimized.

Show comment Hide comment
@duncanbeevers

duncanbeevers May 14, 2008

Contributor

What about the common technique of future-proofing migrations by defining the class being migrated within the namespace of the migration itself?

The solution could be as simple as adding a sti_class_name method on ActiveRecord::Base, cleaning up the repetition of all the store_full_sti_class ? self.class.name :

Contributor

duncanbeevers replied May 14, 2008

What about the common technique of future-proofing migrations by defining the class being migrated within the namespace of the migration itself?

The solution could be as simple as adding a sti_class_name method on ActiveRecord::Base, cleaning up the repetition of all the store_full_sti_class ? self.class.name :

@divoxx

This comment has been minimized.

Show comment Hide comment
@divoxx

divoxx May 14, 2008

Contributor

@duncanbeevers

I’m planning to address this issue and some others asap.
I’ll try to solve every issue listed in the ticket1, so if there is anything else please post there.

1 http://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/114-namespaced-models-and-sti

Contributor

divoxx replied May 14, 2008

@duncanbeevers

I’m planning to address this issue and some others asap.
I’ll try to solve every issue listed in the ticket1, so if there is anything else please post there.

1 http://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/114-namespaced-models-and-sti

Please sign in to comment.