Active record multiple table inheritance with abstract parent

I have four tables: jp_properties, cn_properties, jp_dictionaries and
cn_dictioanries.

And every jp_property belongs to a jp_dictionary with foreign key
“dictionary_id” in table.

Similarly, every cn_property belongs to a cn_dictionary with foreign
key “dictionary_id” in table too.

Since there are a lot of same functions in both property model and
both dictionary model, I’d like to group all these functions in
abstract_class.

The Models are like this:

class Property < AR::Base
self.abstract_class = true
belongs_to :dictionry,
:foreign_key=>‘dictionary_id’,
:class=> —ModelDomainName— + “Dictionary”

functions shared by JpProperty and CnProperty

end

class Dictionary < AR::Base
self.abstract_class = true
has_many :properties,
:foreign_key=>‘dictionary_id’,
:class=> —ModelDomainName— + “Dictionary”

functions shared by JpDictionary and CnDictionary

end

class JpProperty < Property
:set_table_name :jp_properties
end

class CnProperty < Property
:set_table_name :cn_properties
end

class JpDictionary < Dictionary
:set_table_name :jp_dictionaries
end

class CnDictionary < Dictionary
:set_table_name :cn_dictionaries
end

As you can see from the above code, the —ModelDomainName— part is
either ‘Jp’ or ‘Cn’. And I want to get these string dynamically from
the instances of JpProperty, JpDictionary, CnProperty or CnDictionary.

For example:

tempJpProperty = JpProperty.first
tempJpProperty.dictionary #=> will get ‘Jp’ from tempJpProperty’s
class name and then apply it to the “belongs_to” declaration.

So the problem is I don’t know how to specify the —
ModelDomainName— part.

More specifically, I have no idea how to get subclass’s instance
object’s class name within the parent class’s body.

Can you please help me with this problem?

boblu wrote:

I have four tables: jp_properties, cn_properties, jp_dictionaries and
cn_dictioanries.

And every jp_property belongs to a jp_dictionary with foreign key
“dictionary_id” in table.

Similarly, every cn_property belongs to a cn_dictionary with foreign
key “dictionary_id” in table too.

Since there are a lot of same functions in both property model and
both dictionary model, I’d like to group all these functions in
abstract_class.

The Models are like this:

class Property < AR::Base
self.abstract_class = true
belongs_to :dictionry,
:foreign_key=>‘dictionary_id’,
:class=> —ModelDomainName— + “Dictionary”

functions shared by JpProperty and CnProperty

end

class Dictionary < AR::Base
self.abstract_class = true
has_many :properties,
:foreign_key=>‘dictionary_id’,
:class=> —ModelDomainName— + “Dictionary”

functions shared by JpDictionary and CnDictionary

end

class JpProperty < Property
:set_table_name :jp_properties
end

class CnProperty < Property
:set_table_name :cn_properties
end

class JpDictionary < Dictionary
:set_table_name :jp_dictionaries
end

class CnDictionary < Dictionary
:set_table_name :cn_dictionaries
end

As you can see from the above code, the —ModelDomainName— part is
either ‘Jp’ or ‘Cn’. And I want to get these string dynamically from
the instances of JpProperty, JpDictionary, CnProperty or CnDictionary.

For example:

tempJpProperty = JpProperty.first
tempJpProperty.dictionary #=> will get ‘Jp’ from tempJpProperty’s
class name and then apply it to the “belongs_to” declaration.

So the problem is I don’t know how to specify the —
ModelDomainName— part.

More specifically, I have no idea how to get subclass’s instance
object’s class name within the parent class’s body.

Can you please help me with this problem?

This is untested but worth a try.

class Property < AR::Base
self.abstract_class = true
def self.inherited(klass)
klass.to_s =~ /(\w+)[A-Z].*/
language = $1
klass.belongs_to :dictionary, :foreign_key => ‘dictionary_id’,
:class => “#{language}Dictionary”
end
end

class Dictionary < AR::Base
self.abstract_class = true
def self.inherited(klass)
klass.to_s =~ /(\w+)[A-Z].*/
language = $1
klass.has_many :properties, :foreign_key => ‘dictionary_id’,
:class => “#{language}Property”
end
end

Basically you have to delay the creation of the association until the
subclass is created.

Best,
Michael G.

Thanks a lot for your reply.

I just tried your suggestion, but I did not get luck.

This is the console output:

Jp::Property.first
TypeError: can’t dup NilClass
from /rails/activerecord/lib/active_record/base.rb:2189:in dup' from /rails/activerecord/lib/active_record/base.rb:2189:in scoped_methods’
from /rails/activerecord/lib/active_record/base.rb:2193:in
current_scoped_methods' from /rails/activerecord/lib/active_record/base.rb:2183:in scope’
from /rails/activerecord/lib/active_record/base.rb:2414:in
set_readonly_option!' from /rails/activerecord/lib/active_record/base.rb:610:in find’
from /rails/activerecord/lib/active_record/base.rb:623:in `first’
from (irb):2

Is there any other way to 'delay the creation of the association until
the subclass is created. '?

Thank you

On 8月10æ—¥, 午前5:30, Michael G. [email protected]

anyboby any ideas?

To IIan

Can you tell me what do you mean?

If you mean whether I tried the following

class Property < AR::Base
self.abstract_class = true
belongs_to :dictionary, :foreign_key => ‘dictionary_id’, :class => “#
{self.class.name.to_s[0…1]}Dictionary”
end

I can tell you it does not work, because the ‘belongs_to’ declaration
will be evaluated in the abstract class and the sub class will only
inherit the methods generated by ‘belongs_to’.

On 8月10æ—¥, 午後10:27, Ilan B. [email protected]

boblu wrote:

anyboby any ideas?

self.class.name() doesn’t work in the super?