Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails 3 polymorphic association with foreign_type column as integer

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.

like image 910
motionless Avatar asked Aug 09 '26 05:08

motionless


1 Answers

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'
like image 160
gtournie Avatar answered Aug 10 '26 20:08

gtournie



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!