Module: MagicMultiConnection::Connected

Defined in:
lib/magic_multi_connections/connected.rb

Defined Under Namespace

Modules: ClassMethods

Class Method Summary collapse

Class Method Details

.included(base) ⇒ Object



2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/magic_multi_connections/connected.rb', line 2

def self.included(base)
  base.instance_eval do
    alias :pre_connected_const_missing :const_missing
    
    def namespace_reflections_mirror_db
      @namespace_reflections_mirror_db
    end

    def namespace_reflections_mirror_db=(value)
      if value
        warn "DEPRACATION WARNING: Automatic namespace associations will be removed in the next major release of this gem. Please use explicit association statments."
      end
      @namespace_reflections_mirror_db = value
    end

    def const_missing(const_id)
      # return pre_connected_const_missing(const_id) rescue nil
      target_class = "#{self.parent_module}::#{const_id}".constantize rescue nil
      raise NameError.new("uninitialized constant \{const_id}") unless target_class
      
      # The code below is used to solve an issue with the acts_as_versioned
      # plugin.  Because the acts_as_versioned plugin creates a 'Version' model
      # in the namespace of the class itself, the mmc method const_missing() will
      # never get called.  To get around this issue I have modified the acts_as_versioned
      # plugin so that it uses the inherited() method and forces a new ActiveRecord object
      # to be created.  That inheritance method relies on mmc_owner function created below.
      mmc_owner = self
      klass = create_class const_id, target_class do
        @@mmc_owner = mmc_owner
        def self.mmc_owner
          @@mmc_owner
        end
      end        
      klass.establish_connection self.connection_spec
      klass
    end

    def create_class(class_name, superclass = Object, &block)
      klass = Class.new superclass, &block
      result = self.const_set(class_name, klass)
      
      # Cycle through all reflections, and redefine those reflections
      # for all relationships where the ActiveRecord Object follows one
      # of the two following conditions: 
      # 1. The module is set to mirror relationships for the namespace, the reflection object is in
      #    the reflection owner's namespace and the mirror_db_connection object is not explicitly set
      # 2. The reflections mirror_db_connection is explicitly set to true.
      parent_mod = self.parent_module
      superclass.reflections.each do |reflection_name, reflection|
        
        # First do a check to see if code is using a depracated method
        # of associations:
        reflection_mirrors_db = false
        if reflection.mirror_db_connection == true
          reflection_mirrors_db = true
        elsif (reflection.mirror_db_connection == :default && 
               namespace_reflections_mirror_db &&
               Regexp.new("(::|^)#{parent_mod.to_s}(::|$)") =~ reflection.klass.to_s)
          warn "DEPRACATION WARNING: Automatic namespace associations will be removed in the next major release of this gem. Please use explicit association statments."
          reflection_mirrors_db = true
        end
        
        if reflection_mirrors_db
          # redefine the reflection
          new_class_name = reflection.class_name.sub(parent_mod.to_s, "::#{self.name}").gsub("::::", "::")
          new_options = reflection.options.dup
          new_options[:class_name] = new_class_name
          case reflection.macro
          when :has_one, :has_many, :belongs_to
            new_options[:foreign_key] ||= reflection.primary_key_name
          when :has_and_belongs_to_many
            
          end
          
          klass.send reflection.macro, reflection_name, new_options
        end         
      end
      result      
    end
  end
  base.extend(ClassMethods)
end