Module: DBViewCTI::Model::CTI::Associations::ClassMethods

Defined in:
lib/db_view_cti/model/cti/associations.rb

Instance Method Summary collapse

Instance Method Details

#cti_association_name_to_class_name(association_name, class_name = nil) ⇒ Object

converts e.g. :space_ships to SpaceShip Normally operates on associations of this class, but it is possible to pass in ‘class_name’ if ‘association_name’ is an association on a different classes



124
125
126
127
128
# File 'lib/db_view_cti/model/cti/associations.rb', line 124

def cti_association_name_to_class_name(association_name, class_name = nil)
  klass = self
  klass = class_name.constantize if class_name
  klass.reflect_on_all_associations.select { |a| a.name == association_name }.first.class_name
end

#cti_association_proxy_name(association) ⇒ Object



150
151
152
# File 'lib/db_view_cti/model/cti/associations.rb', line 150

def cti_association_proxy_name(association)
  "@cti_#{association}_association_proxy"
end

#cti_associationsObject



154
155
156
157
# File 'lib/db_view_cti/model/cti/associations.rb', line 154

def cti_associations
  cti_initialize_cti_associations
  @cti_associations
end

#cti_create_association_proxiesObject



59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/db_view_cti/model/cti/associations.rb', line 59

def cti_create_association_proxies
  # create hash with proxy and class names. The proxies themselves will be created
  # by the 'association' instance method when the association is used for the first time.
  @cti_association_proxies ||= {}
  @cti_ascendants.each do |ascendant|
    [:has_many, :has_and_belongs_to_many, :has_one].each do |association_type|
      ascendant.constantize.cti_associations[association_type].each do |association|
        proxy_name = cti_association_proxy_name(association)
        @cti_association_proxies[proxy_name] = ascendant
      end
    end
  end
end

#cti_has_association?(association_name) ⇒ Boolean

Returns:

  • (Boolean)


159
160
161
162
163
164
165
166
167
# File 'lib/db_view_cti/model/cti/associations.rb', line 159

def cti_has_association?(association_name)
  if !@cti_all_associations
    @cti_all_associations = @cti_associations.keys.inject([]) do |result, key|
      result += @cti_associations[key]
      result 
    end
  end
  @cti_all_associations.include?(association_name.to_sym)
end

#cti_initialize_cti_associationsObject



169
170
171
172
173
174
175
176
177
# File 'lib/db_view_cti/model/cti/associations.rb', line 169

def cti_initialize_cti_associations
  @cti_associations ||= {}
  @cti_redefined_remote_associations ||= {}
  [:has_many, :has_and_belongs_to_many, :has_one].each do |name|
    @cti_associations[name] ||= []
    @cti_redefined_remote_associations[name] ||= []
  end
  @cti_association_proxies ||= {}
end

#cti_reciprocal_association_for(association, type, class_name = nil) ⇒ Object

Gets reciprocal association of type ‘type’ for the given association. (example: if a has_many association has a corresponding belongs_to in the remote class). Normally, the method checks if the remote association refers to this class, but it is possible to pass in ‘class_name’ to check different classes



106
107
108
109
110
111
# File 'lib/db_view_cti/model/cti/associations.rb', line 106

def cti_reciprocal_association_for(association, type, class_name = nil)
  class_name ||= self.name
  remote_class = cti_association_name_to_class_name( association, class_name ).constantize
  remote_associations = remote_class.reflect_on_all_associations( type ).select { |a| a.class_name == class_name }
  remote_associations.first
end

#cti_reciprocal_association_present_for?(association, type, class_name = nil) ⇒ Boolean

Check if a reciprocal association of type ‘type’ is present for the given association. (example: check if a has_many association has a corresponding belongs_to in the remote class). Normally, the method checks if the remote association refers to this class, but it is possible to pass in ‘class_name’ to check different classes

Returns:

  • (Boolean)


117
118
119
# File 'lib/db_view_cti/model/cti/associations.rb', line 117

def cti_reciprocal_association_present_for?(association, type, class_name = nil)
  !cti_reciprocal_association_for(association, type, class_name).nil?
end

#cti_redefine_remote_associationsObject

fix the ‘remote’ (i.e. belongs_to) part of any has_one of has_many association in this class



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/db_view_cti/model/cti/associations.rb', line 74

def cti_redefine_remote_associations
  cti_initialize_cti_associations
  # redefine remote belongs_to associations
  [:has_many, :has_one].each do |association_type|
    @cti_associations[association_type].each do |association|
      next if @cti_redefined_remote_associations[association_type].include?( association )
      if cti_reciprocal_association_present_for?( association, :belongs_to )
        remote_association = cti_reciprocal_association_for( association, :belongs_to )
        remote_class = cti_association_name_to_class_name( association ).constantize
        cti_redefine_remote_belongs_to_association(remote_class, remote_association.name.to_sym)
        @cti_redefined_remote_associations[association_type] << association
      end
    end
  end
  # redefine remote has_many and has_and_belongs_to_many associations
  [:has_many, :has_and_belongs_to_many].each do |association_type|
    @cti_associations[association_type].each do |association|
      next if @cti_redefined_remote_associations[association_type].include?( association )
      if cti_reciprocal_association_present_for?( association, association_type)
        remote_association = cti_reciprocal_association_for( association, association_type )
        remote_class = cti_association_name_to_class_name( association ).constantize
        cti_redefine_remote_to_many_association(remote_class, remote_association.name.to_sym)
        @cti_redefined_remote_associations[association_type] << association
      end
    end
  end
end

#cti_redefine_remote_belongs_to_association(remote_class, remote_association) ⇒ Object



130
131
132
133
134
135
136
# File 'lib/db_view_cti/model/cti/associations.rb', line 130

def cti_redefine_remote_belongs_to_association(remote_class, remote_association)
  remote_class.class_eval "    def \#{remote_association}=(object, *args, &block)\n      super( object.try(:convert_to, '\#{self.name}'), *args, &block )\n    end\n  eos\nend\n", __FILE__, __LINE__+1

#cti_redefine_remote_to_many_association(remote_class, remote_association) ⇒ Object



138
139
140
141
142
143
144
145
146
147
148
# File 'lib/db_view_cti/model/cti/associations.rb', line 138

def cti_redefine_remote_to_many_association(remote_class, remote_association)
  remote_class.class_eval "    def \#{remote_association}=(objects, *args, &block)\n      super( objects.map { |o| o.try(:convert_to, '\#{self.name}') }, *args, &block)\n    end\n    def \#{remote_association}(*args, &block)\n      collection = super\n      DBViewCTI::Model::CollectionDelegator.new(collection, '\#{self.name}')\n    end\n  eos\nend\n", __FILE__, __LINE__+1