PullMonkey Blog

13 Aug

Modularized Models and Associations in ActiveRecord


Have you ever encountered this error?

wrong constant name X::YAssociationExtension

I found this error when dealing with acts_as_versioned for one my models. I would have found it eventually with any association I would have setup in this case, so it is not acts_as_versioned's fault.

I have an application with various parts so I create some of my models like this:

1
2
./script/generate model module_name::model_name



So the fix is pretty simple, instead of winding up with ModuleName::ModelAssociationExtension or whatever, you want your extention module name to be ModelAssociationExtension.

Here is the method where the code breaks for me:

1
2
3
4
5
6
7
8
9
10
11
12
13
def create_extension_modules(association_id, block_extension, extensions)
  if block_extension
    extension_module_name = "#{self.to_s}#{association_id.to_s.camelize}AssociationExtension"

    silence_warnings do
      Object.const_set(extension_module_name, Module.new(&block_extension))
    end
    Array(extensions).push(extension_module_name.constantize)
  else
    Array(extensions)
  end
end

Here is the fix, on line 3, you will note the demodulize addition:

1
2
3
4
5
6
7
8
9
10
11
12
13
def create_extension_modules(association_id, block_extension, extensions)
  if block_extension
    extension_module_name = "#{self.to_s.demodulize}#{association_id.to_s.camelize}AssociationExtension"

    silence_warnings do
      Object.const_set(extension_module_name, Module.new(&block_extension))
    end
    Array(extensions).push(extension_module_name.constantize)
  else
    Array(extensions)
  end
end

I threw the corrected code into a library - RAILS_ROOT/lib/fix_active_record_create_extension_for_modules.rb. Make sure to open up the necessary modules to overwrite the method itself, I.e., like this:

1
2
3
4
5
6
7
8
module ActiveRecord
  module Associations
    module ClassMethods
      # the code above fits right here
    end
  end
end

Short and sweet, let me know if you have a better method for handling this.





Sorry, comments for this entry are closed at this time.