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