STI Patch to store full class name

While working on a big project (>100 models) it was necessary to use namespace to store the models and surprisingly it wasn't hard at all. Looks like Rails is (almost) supporting full model namespaces out-of- the-box. :slight_smile:

The one and only problem was with STI. If you have subclasses in a different namespace than the baseclass then things will blow. Reason being ActiveRecord doesn't store the full class name, it store the "demodulized" version of it.

For example:

class CollectionItem < ActiveRecord::Base; end class ComicCollection::Item < CollectionItem; end

item = ComicCollection::Item.new item.type # => 'Item'

item2 = CollectionItem.find(item.id) # <- this would raise an error because it would not find class Item

I wrote a patch that add a configuration option ActiveRecord::Base.store_full_sti_class (in order to keep back- compatibility) that when enabled will store the full class name.

I believe storing the demodulized name was a bad assumption made in the early days of Rails. Applying this patch will not only allow people to namespace their models but probably prevent some other errors and bugs in the future.

If you think this should be applied, please go ahead and add +1 in there.

Cheers

Ops, forgot the patch url :slight_smile:

http://dev.rubyonrails.org/ticket/11575

I am sorry, that I am not yet able to commit to framework, but while you interested in improvement of namespace support in rails - here some notes, that you may find useful:

1) Invoking to_xml on namespaced model will produce bad XML, bcoz '/' symbol will used as namespace separator, and as you know this symbol is very special for XML :wink:

2) It looks like observers can not be namespaced, when defined by symbols config.active_record.observers = :somenamespace_someclass_observer # this will fail perhaps there are another ways to set namespaced observers, not by symbols, but those ways are not documented well.

While working on a big project (>100 models) it was necessary to use namespace to store the models and surprisingly it wasn't hard at all. Looks like Rails is (almost) supporting full model namespaces out-of- the-box. :slight_smile:

God bless Core team :wink:

Regards, Andriy Tyurnikov

I believe you can set the observers using the classes itself:

config.active_record.observers = [SomeNamespace::SomeObserver]

I'm not 100% sure though :wink:

nope, not able :frowning:

... *5 minutes in shell*

oops - It can be done by config.active_record.observers = "SomeNamespace/SomeObserver"

will patch the docs, your +1 expected :wink:

Regards, Andriy.Tyurnikov

Yeah, definitely. Can i count with your +1 for this patch? :slight_smile:

Yeah, definitely. Can i count with your +1 for this patch? :slight_smile:

My only concern with this kind of change is what happens to existing data that's stored in the database.

I see the option to turn this behaviour off, is that only needed for backwards compatibility reasons? Are there any other downsides to the change?

Finally, if you could move this to lighthouse it'd make the reviewing a little easier.

You might also want to reference http://dev.rubyonrails.org/ticket/ 6792 and the namespaced_model plugin.

e.

@Koz

Yeah, i've added the configuration option in order to allow back compatibility.

Also, i've moved the ticket to lighthouse http://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/114-namespaced-models-and-sti

Cheers

There's also the issue of models referenced from within migrations where you might want to explicitly specify a module hierarchy that does not match the model's actual namespace.

Perhaps we can include a method that allows you explicitly set the sti class name?

class SomeMigration < ActiveRecord::Migration   class User < ActiveRecord::Base   end

  class Administrator < User     sti_class_name 'CustomNamespace::Administrator'   end end

There's also the issue of models referenced from within migrations where you might want to explicitly specify a module hierarchy that does not match the model's actual namespace.

Perhaps we can include a method that allows you explicitly set the sti class name?

class SomeMigration < ActiveRecord::Migration class User < ActiveRecord::Base end

class Administrator < User    sti_class_name 'CustomNamespace::Administrator' end end

I'm not sure how feasible this would be to implement, if the file with that directive in it hadn't been required yet AR wouldn't know how to map 'Some::Crazy::Stuff' to 'Administrator'.

Any thought rodrigo?

I'm not sure how feasible this would be to implement, if the file with that directive in it hadn't been required yet AR wouldn't know how to map 'Some::Crazy::Stuff' to 'Administrator'.

Any thought rodrigo?

I think the point of #sti_class_name is so that SomeMigration::User writes "User" to the type field. AR::Base#compute_type shouldn't need to create some custom name => class hash map or anything like that.

FWIW I've committed the original patch. See also: http://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/114