Need help understanding self.abstract_class = true in AR

All,

I submitted the following bug to Rails Traq:
http://dev.rubyonrails.org/ticket/6010

I was basing my bug report on my understanding that setting
self.abstract_class = true meant that your model did not have a table
backing it. This has been my experience when using the odbc adapter for
AR against SQL Server, where I have created several abstract models and
instantiated them successfully without having backing tables for them.

However, the traq report says that self.abstract_class = true “means you
can inherit from it (the model) without using STI.”

The RoR API says: “Returns whether this class is a base AR class. If A
is a base class and B descends from A, then B.base_class will return B.”

Q1) Can someone please summarize what the purpose of setting
self.abstract_class is?

Q2) If self.abstract_class = true is NOT meant to create an ActiveRecord
model that is not backed by a table, then what is the correct way to
accomplish that?

Neither of those statements above addresses whether or not the
abstract_class is expected to have a backing table or not. To me, it’s
implied that there is not a backing table (I don’t see how you could
even take advantage of one if there were a backing table).

It makes sense that perhaps it is not expected that an abstract AR class
would even be instantiated so handling issues with around the existence
of a backing table wouldn’t be addressed.

Thanks,
Wes

Wes G. wrote:

Q2) If self.abstract_class = true is NOT meant to create an ActiveRecord
model that is not backed by a table, then what is the correct way to
accomplish that?

I’m a bit flummoxed by why you’d want an ActiveRecord object that
didn’t have a database table behind it. What would it do? The whole
point of ActiveRecord is to map the object to the database.

If you just want a class that isn’t saved to the database, you can
create a normal Ruby class like

class Person
end

and put it in your /app/models directory and use it.

Chris

I want to take advantage of AR validation methods for such a model.

I use an abstract class in my FlexImage plugin
http://beautifulpixel.com/articles/2006/08/21/fleximage

Wes G. wrote:

Q1) Can someone please summarize what the purpose of setting
self.abstract_class is?

Basically, I wanted to provide a class that one of your models could
inherit from with all the functionality. The problem was that Rails was
assuming I wanted to do STI when I just wanted basic ruby inheritance.
Setting abstract class in this case meant there was no table and it only
exists as a class to inherit from and provides no functionality in and
of itself.

This is a longer version of what the reply in that ticket says. It’s
absolutely right. Abstract AR classes aren’t used idrectly, just
inherited from.

Q2) If self.abstract_class = true is NOT meant to create an ActiveRecord
model that is not backed by a table, then what is the correct way to
accomplish that?

If you want an ActiveRecord object without a DB table, then you don’t
want an ActiveRecord object. The entire core functionality of AR is
built around providing an interface to a database table.

If you want a class to validate other AR objects, abstract class will
work for you.

class Foo < ActiveRecord::Base
self.abstract_class = true
validates_presence_of :bar
end

class Zing < Foo

already inherits validates_presence_of :bar

end

class Groucho < Foo

already inherits validates_presence_of :bar

end

Alex,

Thanks for the response.

So if I can actually create an instance of an AR object that has
self.abstract_class set to true, then that should be a bug, correct?

I am able to create instances of abstract AR classes when using the ODBC
driver against SQL Server. Should I log that as a bug?

I still would like to be able to get the AR::Validations functionality
for an arbitrary class - I’ll play with seeing if I can just include it
into a regular class.

Thanks,
Wes

On 9/1/06, Wes G. [email protected] wrote:

instantiated them successfully without having backing tables for them.
Q2) If self.abstract_class = true is NOT meant to create an ActiveRecord
model that is not backed by a table, then what is the correct way to
accomplish that?

  1. read my response to the ticket:

An abstract model means you can inherit from it without using STI.

class SuperModel < AR::Base
self.abstract_class = true
end

class Foo < SuperModel
end

Foo.table_name

=> ‘foos’

It’s used in the CachedModel plugin. I’m not sure why it’s a class
and not a mixin though, but ok.

  1. Two ideas, one is really hackish.

The hackish way:

http://rails.techno-weenie.net/tip/2005/11/19/validate_your_forms_with_a_table_less_model

The second is directly including ActiveRecord::Validations into your
class. You may have to implement some of the ActiveRecord API for
this though. I’m pretty sure the wiki has some info on this.


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

On 02/09/06, Wes G. [email protected] wrote:

Which now makes me realize that the original behavior I see against SQL
Server is the bug. Do you think that’s a bug?

As Rick said, setting self.abstract_class = true means you can extend
a class without STI kicking in. The class isn’t really abstract in
the strict sense; it can still be instantiated (whichever database
adapter is used). Perhaps base_class or some other signifier
(acts_as_base_class?) would have been less confusing.

Tom

Rick,

I get it now. However, my original issue has to do with what I now
believe to be a bug in the AR ODBC module.

Using AR w/ODBC against SQL Server, I can successfully instantiate a
class with self.abstract_class set to true with no problems. I
convinced myself that part of the intended functionality of
self.abstract_class was to allow the user to take advantage of AR
validations without requiring them to persist the data.

Now I see that that was an incorrect understanding.

Which now makes me realize that the original behavior I see against SQL
Server is the bug. Do you think that’s a bug?

Wes

Rick O. wrote:

The second is directly including ActiveRecord::Validations into your
class. You may have to implement some of the ActiveRecord API for
this though. I’m pretty sure the wiki has some info on this.

Here’s a nice article about a plugin that looks like it should do the
trick:
http://www.realityforge.org/articles/2005/12/02/validations-for-non-activerecord-model-objects

Wes

So I think there’s a bug in the ODBC mode of the SQL Server driver then.

This plugin seems to work quite well.