Ruby Forum Rails-core > STI Patch to store full class name

Posted by Rodrigo Kochenburger (Guest)
on 03.05.2008 19:06
(Received via mailing list)
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. :)

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
Posted by Rodrigo Kochenburger (Guest)
on 03.05.2008 19:10
(Received via mailing list)
Ops, forgot the patch url :)

http://dev.rubyonrails.org/ticket/11575
Posted by Andriy Tyurnikov (Guest)
on 03.05.2008 19:28
(Received via mailing list)
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 ;)

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. :)
>


God bless Core team ;)

Regards,
Andriy Tyurnikov
Posted by Rodrigo Kochenburger (Guest)
on 03.05.2008 19:39
(Received via mailing list)
I believe you can set the observers using the classes itself:

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

I'm not 100% sure though ;)

On May 3, 2:27 pm, Andriy Tyurnikov <andriy.tyurni...@gmail.com>
Posted by Andriy Tyurnikov (Guest)
on 03.05.2008 19:56
(Received via mailing list)
On 3 May 2008, at 20:38, Rodrigo Kochenburger wrote:

>
> I believe you can set the observers using the classes itself:
>
> config.active_record.observers = [SomeNamespace::SomeObserver]
>
> I'm not 100% sure though ;)


nope, not able :(

... *5 minutes in shell*

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

will patch the docs, your +1 expected ;)

Regards,
Andriy.Tyurnikov
Posted by Rodrigo Kochenburger (Guest)
on 03.05.2008 20:14
(Received via mailing list)
Yeah, definitely.
Can i count with your +1 for this patch? :)

On May 3, 2:55 pm, Andriy Tyurnikov <andriy.tyurni...@gmail.com>
Posted by Michael Koziarski (Guest)
on 04.05.2008 03:57
(Received via mailing list)
>  Yeah, definitely.
>  Can i count with your +1 for this patch? :)

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.



--
Cheers

Koz
Posted by EAW (Guest)
on 05.05.2008 04:55
(Received via mailing list)
You might also want to reference  http://dev.rubyonrails.org/ticket/
6792 and the namespaced_model plugin.

e.
Posted by Rodrigo Kochenburger (Guest)
on 05.05.2008 16:44
(Received via mailing list)
@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
Posted by Duncan Beevers (Guest)
on 05.05.2008 23:27
(Received via mailing list)
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
Posted by Michael Koziarski (Guest)
on 09.05.2008 04:35
(Received via mailing list)
On Tue, May 6, 2008 at 9:24 AM, Duncan Beevers <duncanbeevers@gmail.com> 
wrote:
>  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?


>>  Cheers
>>  > I see the option to turn this behaviour off, is that only needed for
>>  >
>>
>
> >
>



--
Cheers

Koz
Posted by Rick Olson (Guest)
on 14.05.2008 00:26
(Received via mailing list)
> 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

--
Rick Olson
http://lighthouseapp.com
http://weblog.techno-weenie.net
http://mephistoblog.com