Rails polymorphic association (outdated database)

I am using an outdated database, so I have no control over the datamodel. They use many polymorphic links / join tables, for example this

create table person(per_ident, name, ...) create table person_links(per_ident, obj_name, obj_r_ident) create table report(rep_ident, name, ...) 

where obj_name is the name of the table and obj_r_ident is the identifier. Therefore, related reports will be inserted as follows:

 insert into person(1, ...) insert into report(1, ...) insert into report(2, ...) insert into person_links(1, 'REPORT', 1) insert into person_links(1, 'REPORT', 2) 

And then person 1 would have 2 related reports, 1 and 2.

I can understand the possible advantages having such a date, but basically I see one big drawback: the use of restrictions is impossible to ensure data integrity. But alas, I can’t change this anymore.

But to use this in Rails, I looked at polymorphic associations, but did not find a good way to solve this problem (since I cannot change the column names and I did not find a way to do this).

However, I came up with a solution. Please provide suggestions.

 class Person < ActiveRecord::Base set_primary_key "per_ident" set_table_name "person" has_and_belongs_to_many :reports, :join_table => "person_links", :foreign_key => "per_ident", :association_foreign_key => "obj_r_ident", :conditions => "OBJ_NAME='REPORT'" end class Report < ActiveRecord::Base set_primary_key "rep_ident" set_table_name "report" has_and_belongs_to_many :persons, :join_table => "person_links", :foreign_key => "obj_r_ident", :association_foreign_key => "per_ident", :conditions => "OBJ_NAME='REPORT'" end 

This works, but I wonder if there would be a better solution using polymorphic associations.

+4
source share
2 answers

You can redefine the column names, of course, but a quick scan of the Rails API did not show me anywhere to redefine a polymorphic column. Thus, you cannot set this to "obj_name".

This is ugly, but I think you'll need a HABTM for every type of object in your table.

You can do something like this:

 {:report => 'REPORT'}.each do |sym, text| has_and_belongs_to_many sym, :join_table => "person_links", :foreign_key => "obj_r_ident", :association_foreign_key => "per_ident", :conditions => "OBJ_NAME='#{text}'" end 

At least all the usual things remain DRY , and you can easily add more relationships.

+1
source

At a minimum, from Rails 4.2.1 you can pass foreign_type to the foreign_type declaration to specify the name of the column that will be used for the "type" polymorphic association

http://apidock.com/rails/v4.2.1/ActiveRecord/Associations/ClassMethods/belongs_to

+7
source

All Articles