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



127
128
129
130
131
# File 'lib/db_view_cti/model/cti/associations.rb', line 127

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



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

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

#cti_associationsObject



157
158
159
160
# File 'lib/db_view_cti/model/cti/associations.rb', line 157

def cti_associations
  cti_initialize_cti_associations
  @cti_associations
end

#cti_create_association_proxiesObject



62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/db_view_cti/model/cti/associations.rb', line 62

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)


162
163
164
165
166
167
168
169
170
# File 'lib/db_view_cti/model/cti/associations.rb', line 162

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



172
173
174
175
176
177
178
179
180
# File 'lib/db_view_cti/model/cti/associations.rb', line 172

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



109
110
111
112
113
114
# File 'lib/db_view_cti/model/cti/associations.rb', line 109

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)


120
121
122
# File 'lib/db_view_cti/model/cti/associations.rb', line 120

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



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

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



133
134
135
136
137
138
139
# File 'lib/db_view_cti/model/cti/associations.rb', line 133

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

#cti_redefine_remote_to_many_association(remote_class, remote_association) ⇒ Object



141
142
143
144
145
146
147
148
149
150
151
# File 'lib/db_view_cti/model/cti/associations.rb', line 141

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