Module: GenericTableAssociation::ClassMethods

Included in:
ActiveRecord::Base, StreamMethodArgument
Defined in:
app/models/generic_table_association.rb

Instance Method Summary collapse

Instance Method Details

#associated_foreign_key_name(association_referenced_by_foreign_key) ⇒ Object

foreign_key_association_names


32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'app/models/generic_table_association.rb', line 32

def associated_foreign_key_name(association_referenced_by_foreign_key)
	if !is_association?(association_referenced_by_foreign_key.to_s.singularize) then
		raise "Association #{association_referenced_by_foreign_key.to_s.singularize} is not an association of #{self.name}."
	end #if
	many_to_one_foreign_keys=foreign_key_names
	matchingAssNames=many_to_one_foreign_keys.select do |fk|
		ass=fk[0..-4].to_sym
		ass==association_referenced_by_foreign_key.to_s.singularize.to_sym
	end #end
	if matchingAssNames.size==0 then
		raise "Association #{association_referenced_by_foreign_key} does not have a corresponding foreign key in association #{self.name}."
	end #if
	return matchingAssNames.first
end

#association_arity(association_name) ⇒ Object

returns :to_one, :to_many, or :not_an_association


198
199
200
201
202
203
204
205
206
# File 'app/models/generic_table_association.rb', line 198

def association_arity(association_name)
	if is_association_to_one?(association_name) then
		return :to_one
	elsif is_association_to_many?(association_name) then
		return :to_many
	else 
		return :not_an_association
	end #if
end

#association_class(association_name) ⇒ Object

return class when passed a symbol reference


175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
# File 'app/models/generic_table_association.rb', line 175

def association_class(association_name)
	 if !is_association?(association_method_symbol(association_name)) then
		raise "#{association_method_symbol(association_name)} is not an association of #{self.name}."
	elsif is_polymorphic_association?(association_name) then
		raise "Polymorphic associations #{association_method_symbol(association_name)} of #{self.name} do not have a single class.. Need instance not class method "
	else
		default_class_defined=association_default_class_name?(association_name)
		if default_class_defined then
			return Generic_Table.class_of_name(association_default_class_name?(association_name))
		else
			all_parents=all
			all_association_classes=all_parents.map do |bc|
				bc.association_class(association_name)
			end.flatten.uniq #map
			if all_association_classes.size==1 then
				return all_association_classes[0] # remove Array
			else
				return all_association_classes # polymorphic? impossible?
			end #if
		end #if
	end #if
end

#association_default_class_name?(association_name) ⇒ Boolean

return association's default_class name can be used as a boolean test

Returns:

  • (Boolean)

166
167
168
169
170
171
172
173
# File 'app/models/generic_table_association.rb', line 166

def association_default_class_name?(association_name)
	default_association_class_name=association_name.to_s.classify
	if eval("defined? #{default_association_class_name}") then
		return default_association_class_name
	else
		return nil # not default class name
	end #if
end

#association_method_plurality(association_table_name) ⇒ Object

checks whether association symbol exists or if a singular or plural name exists.


149
150
151
152
153
154
155
156
157
158
159
# File 'app/models/generic_table_association.rb', line 149

def association_method_plurality(association_table_name)
	if self.instance_respond_to?(association_table_name) then
		return association_table_name.to_sym
	elsif self.instance_respond_to?(association_table_name.to_s.singularize) then
		return association_table_name.to_s.singularize.to_sym
	elsif self.instance_respond_to?(association_table_name.to_s.pluralize) then
		return association_table_name.to_s.pluralize.to_sym
	else # don't know what to do; most likely cure
		return association_table_name.to_s.pluralize.to_sym
	end #if
end

#association_method_symbol(association_table_name) ⇒ Object

For convenience handles both type and plurality.


161
162
163
# File 'app/models/generic_table_association.rb', line 161

def association_method_symbol(association_table_name)
	return association_method_plurality(name_symbol(association_table_name))
end

#association_methods(association_name) ⇒ Object

return automagically created methods for an association.


66
67
68
# File 'app/models/generic_table_association.rb', line 66

def association_methods(association_name)
	return matching_instance_methods(association_name,false)
end

#association_namesObject

association_names_to_many


125
126
127
# File 'app/models/generic_table_association.rb', line 125

def association_names
	return instance_methods(false).select {|m| is_association_to_one?(m) or is_association_to_many?(m)}
end

#association_names_to_manyObject

association_names_to_one


122
123
124
# File 'app/models/generic_table_association.rb', line 122

def association_names_to_many
	return instance_methods(false).select {|m| is_association_to_many?(m)}
end

#association_names_to_oneObject

is_polymorphic_association


119
120
121
# File 'app/models/generic_table_association.rb', line 119

def association_names_to_one
	return instance_methods(false).select {|m| is_association_to_one?(m)}
end

#association_patterns(association_name) ⇒ Object

association_methods


69
70
71
72
73
74
75
# File 'app/models/generic_table_association.rb', line 69

def association_patterns(association_name)
	patterns=association_methods(association_name).map do |n| 
		matchData=Regexp.new(association_name.to_s).match(n)
		Regexp.new('^'+matchData.pre_match+'([a-z0-9_]+)'+matchData.post_match+'$')
	end #map
	return Set.new(patterns)
end

#foreign_key_association_namesObject

list names of the associations having foreign keys.


29
30
31
# File 'app/models/generic_table_association.rb', line 29

def foreign_key_association_names
	foreign_key_names.map {|fk| fk.sub(/_id$/,'')}
end

#foreign_key_namesObject

List names (as Strings) of all foreign keys.


14
15
16
17
18
19
# File 'app/models/generic_table_association.rb', line 14

def foreign_key_names
	content_column_names=content_columns.collect {|m| m.name}
	special_columns=column_names-content_column_names
	possible_foreign_keys=special_columns.select { |m| m =~ /_id$/ }
	return possible_foreign_keys
end

#foreign_key_to_association_name(foreign_key) ⇒ Object

translate foreign_key into asociation name Example: foreign_Key_to_association_name(:fk_id)=='fk' association


25
26
27
# File 'app/models/generic_table_association.rb', line 25

def foreign_key_to_association_name(foreign_key)
	foreign_key.to_s.sub(/_id$/,'')
end

#is_association?(association_name) ⇒ Boolean

is_association_patterns

Returns:

  • (Boolean)

87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'app/models/generic_table_association.rb', line 87

def is_association?(association_name)
	# Don’t create associations that have the same name as instance methods of ActiveRecord::Base.
	if ActiveRecord::Base.instance_methods_from_class.include?(association_name.to_s) then
#bad char		raise "# Don’t create associations that have the same name (#{association_name.to_s})as instance methods of ActiveRecord::Base (#{ActiveRecord.instance_methods_from_class})."
	end #if
	if association_name.to_s[-4,4]=='_ids' then # automatically generated
		return false
	elsif self.instance_respond_to?(association_name) and self.instance_respond_to?((association_name.to_s+'=').to_sym)  then
		return true
	else
		return false
	end
end

#is_association_patterns?(association_name, association_patterns) ⇒ Boolean

match_association_patterns

Returns:

  • (Boolean)

83
84
85
86
# File 'app/models/generic_table_association.rb', line 83

def is_association_patterns?(association_name,association_patterns)
	(association_patterns(association_name)-association_patterns.to_a).empty?&&
	(association_patterns-association_patterns(association_name).to_a).empty?
end

#is_association_to_many?(association_name) ⇒ Boolean

association_to_one

Returns:

  • (Boolean)

107
108
109
110
111
112
113
# File 'app/models/generic_table_association.rb', line 107

def is_association_to_many?(association_name)
	if is_association?(association_name)  and self.instance_respond_to?((association_name.to_s.singularize+'_ids').to_sym) and self.instance_respond_to?((association_name.to_s.singularize+'_ids=').to_sym) then
		return true
	else
		return false
	end
end

#is_association_to_one?(association_name) ⇒ Boolean

is_association

Returns:

  • (Boolean)

100
101
102
103
104
105
106
# File 'app/models/generic_table_association.rb', line 100

def is_association_to_one?(association_name)
	if is_association?(association_name)  and !self.instance_respond_to?((association_name.to_s.singularize+'_ids').to_sym) and !self.instance_respond_to?((association_name.to_s.singularize+'_ids=').to_sym) then
		return true
	else
		return false
	end
end

#is_foreign_key_name?(symbol) ⇒ Boolean

foreign_key_names

Returns:

  • (Boolean)

20
21
22
# File 'app/models/generic_table_association.rb', line 20

def is_foreign_key_name?(symbol)
	return foreign_key_names.include?(symbol.to_s) && is_association?(foreign_key_to_association_name(symbol))
end

#is_matching_association?(association_name) ⇒ Boolean

Does association have me as one of its associations?

Returns:

  • (Boolean)

47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'app/models/generic_table_association.rb', line 47

def is_matching_association?(association_name)
	 if is_association?(association_name) then
		association_class=association_class(association_name)
		 if association_class.nil? then
			 raise "Association #{association_name.classify} is not a defined constant."
		end #if
		table_symbol=association_class.association_method_symbol(self)
		 if association_class.is_association?(table_symbol) then
			 return true
		elsif association_class.is_association?(association_method_symbol(self.table_name.singularize.to_sym))  then
			return true
		else
			 return false
		end #if
	else
		return false
	end #if
end

#is_polymorphic_association?(association_name) ⇒ Boolean

debug @@Example_polymorphic_patterns=Set.new([/^()$/, /^set_()_target$/, /^([a-z0-9_]+)=$/, /^autosave_associated_records_for_()$/, /^loaded_()?$/])

Returns:

  • (Boolean)

116
117
118
# File 'app/models/generic_table_association.rb', line 116

def is_polymorphic_association?(association_name)
	return is_association_patterns?(association_name,@@Example_polymorphic_patterns)
end

#match_association_patterns?(association_name, association_pattern) ⇒ Boolean

association_patterns

Returns:

  • (Boolean)

76
77
78
79
80
81
82
# File 'app/models/generic_table_association.rb', line 76

def match_association_patterns?(association_name,association_pattern)
	patterns=association_methods(association_name).map do |n| 
		matchData=association_pattern.match(association_pattern)
	end #map
	
	instance_respond_to?(association_name)
end

#name_symbol(model_name) ⇒ Object

Returns model name in a canonical form from Class or string, … The return value is canonical in that multiple possible inputs produce the same output. always returns a plural, whereas a macro may have a singular argument. Generally returns association_table_name.class.name.tableize.to_sym for any object. tableize handles some pluralizing, but symbols are unchanged routine is meant to handle usual cases in Rails method naming not pathological cases. Does not assume an association. This flexibility should not be overused. It is intended for finding inverse associations and allowing assertion error messages to suggest what you might have intended.


137
138
139
140
141
142
143
144
145
146
147
# File 'app/models/generic_table_association.rb', line 137

def name_symbol(model_name)
	if model_name.kind_of?(Class) then
		return model_name.name.tableize.to_sym					
	elsif model_name.kind_of?(String) then
		return model_name.tableize.to_sym						
	elsif model_name.kind_of?(Symbol) then
		return model_name.to_sym
	else # other object
		return model_name.class.name.tableize.to_sym
	end #if
end