We have a certain problem with polymorphic relation in rails/activerecord. As mentioned in an other question . The reason we need this kind of polymorphic relation with a integer foreign_type column is the number of records in table, we have about 40 million record in that table an the number is raising. We try to save storage at the database server an memory consumption concerning the index handling at the database.
The question mentioned earlier is related to Rails 2 and if already tried to uses this with Rails 3 but it doesn't work. The method of the module was never called and i can't see why.
I would like to have a mapping like this with column types see in the migration class
class Notification < ActiveRecord::Base
belongs_to :notifiable, :polymorphic => true
end
class User < ActiveRecord::Base
attr_accessible :name
has_many :notifications, :as => :notifiable
end
class Comment < ActiveRecord::Base
attr_accessible :text
has_many :notifications, :as => :notifiable
end
class Message < ActiveRecord::Base
attr_accessible :title, :text
has_many :notifications, :as => :notifiable
end
class Activity < ActiveRecord::Base
attr_accessible :title, :description
has_many :notifications, :as => :notifiable
end
class CreateNotification < ActiveRecord::Migration
def change
create_table :notifications do |t|
t.integer :notifiable_id
t.integer :notifiable_type # should be a tinyint at the database
t.timestamps
end
end
end
I would like to map Comment and User with a numeric value and save the numeric value instead of the class name as type information.
To make the polymorphic belongs_to working, you can do that:
In config/initializers
directory, create a file and put theses lines:
module ActiveRecord
# = Active Record Belongs To Polymorphic Association
module Associations
class BelongsToPolymorphicAssociation < BelongsToAssociation #:nodoc:
def klass
type = owner.send(reflection.foreign_type)
type.presence && type.constantize
end
end
end
end
then in each model, override notifiable_type
(define the hash as a constant and put it anywhere you like):
def notifiable_type
{ 0: 'User', 1: 'Comment', 3: 'Message' }[read_attribute(:notifiable_type)]
end
and for has_many
, try this (set INT_CLASS_TYPE for each model):
has_many :notifications, :conditions => ["`notifiable_type` = ?", INT_CLASS_TYPE], :foreign_key => 'notifiable_id'