Class: DataShift::MethodDictionary
Class Method Summary collapse
- .add(klass, operator, type = :assignment) ⇒ Object
- .assignments ⇒ Object
- .assignments_for(klass) ⇒ Object
- .belongs_to ⇒ Object
- .belongs_to_for(klass) ⇒ Object
-
.build_method_details(klass, options = {}) ⇒ Object
Build a thorough and usable picture of the operators by building dictionary of our MethodDetail objects which can be used to import/export data to objects of type ‘klass’ Subsequent calls with same class will return existign mapping To over ride this behaviour, supply :force => true to force regeneration.
- .clear ⇒ Object
- .column_key(klass, column) ⇒ Object
- .column_type_for(klass, column) ⇒ Object
- .column_types ⇒ Object
-
.dump(klass) ⇒ Object
Dump out all available operators.
-
.find_method_detail(klass, external_name, conditions = nil) ⇒ Object
For a client supplied name/header - find the operator i.e appropriate call + column type.
-
.find_method_detail_if_column(klass, external_name) ⇒ Object
Assignments can contain things like delegated methods, this returns a matching method details only when a true database column.
-
.find_operators(klass, options = {}) ⇒ Object
Create simple picture of all the operator names for assignment available on an AR model, grouped by type of association (includes belongs_to and has_many which provides both << and = ) Options: :reload => clear caches and re-perform lookup :instance_methods => if true include instance method type ‘setters’ as well as model’s pure columns.
-
.for?(klass) ⇒ Boolean
Return true if dictionary has been populated for klass.
- .get_method_details_mgr(klass) ⇒ Object
- .has_many ⇒ Object
- .has_many_for(klass) ⇒ Object
- .has_one ⇒ Object
- .has_one_for(klass) ⇒ Object
-
.method_details_mgrs ⇒ Object
Store a Mgr per mapped klass.
- .setters(klass) ⇒ Object
-
.substitutions(external_name) ⇒ Object
TODO - check out regexp to do this work better plus Inflections ?? Want to be able to handle any of [“Count On hand”, ‘count_on_hand’, “Count OnHand”, “COUNT ONHand” etc].
Methods included from Logging
Class Method Details
.add(klass, operator, type = :assignment) ⇒ Object
90 91 92 93 94 95 |
# File 'lib/datashift/method_dictionary.rb', line 90 def self.add( klass, operator, type = :assignment) method_details_mgr = get_method_details_mgr( klass ) md = MethodDetail.new(operator, klass, operator, type) method_details_mgr << md return md end |
.assignments ⇒ Object
248 249 250 251 |
# File 'lib/datashift/method_dictionary.rb', line 248 def self.assignments @assignments ||= {} @assignments end |
.assignments_for(klass) ⇒ Object
271 272 273 |
# File 'lib/datashift/method_dictionary.rb', line 271 def self.assignments_for(klass) assignments[klass] || [] end |
.belongs_to ⇒ Object
233 234 235 236 |
# File 'lib/datashift/method_dictionary.rb', line 233 def self.belongs_to @belongs_to ||={} @belongs_to end |
.belongs_to_for(klass) ⇒ Object
259 260 261 |
# File 'lib/datashift/method_dictionary.rb', line 259 def self.belongs_to_for(klass) belongs_to[klass] || [] end |
.build_method_details(klass, options = {}) ⇒ Object
Build a thorough and usable picture of the operators by building dictionary of our MethodDetail objects which can be used to import/export data to objects of type ‘klass’ Subsequent calls with same class will return existign mapping To over ride this behaviour, supply :force => true to force regeneration
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
# File 'lib/datashift/method_dictionary.rb', line 102 def self.build_method_details( klass, = {} ) return method_details_mgrs[klass] if(method_details_mgrs[klass] && ![:force]) method_details_mgr = MethodDetailsManager.new( klass ) method_details_mgrs[klass] = method_details_mgr assignments_for(klass).each do |n| method_details_mgr << MethodDetail.new(n, klass, n, :assignment, column_types[klass]) end has_one_for(klass).each do |n| method_details_mgr << MethodDetail.new(n, klass, n, :has_one) end has_many_for(klass).each do |n| method_details_mgr << MethodDetail.new(n, klass, n, :has_many) end belongs_to_for(klass).each do |n| method_details_mgr << MethodDetail.new(n, klass, n, :belongs_to) end method_details_mgr end |
.clear ⇒ Object
209 210 211 212 213 214 215 216 |
# File 'lib/datashift/method_dictionary.rb', line 209 def self.clear belongs_to.clear has_many.clear assignments.clear column_types.clear has_one.clear method_details_mgrs.clear end |
.column_key(klass, column) ⇒ Object
218 219 220 |
# File 'lib/datashift/method_dictionary.rb', line 218 def self.column_key(klass, column) "#{klass.name}:#{column}" end |
.column_type_for(klass, column) ⇒ Object
275 276 277 |
# File 'lib/datashift/method_dictionary.rb', line 275 def self.column_type_for(klass, column) column_types[klass] ? column_types[klass][column] : [] end |
.column_types ⇒ Object
253 254 255 256 |
# File 'lib/datashift/method_dictionary.rb', line 253 def self.column_types @column_types ||= {} @column_types end |
.dump(klass) ⇒ Object
Dump out all available operators
150 151 152 153 |
# File 'lib/datashift/method_dictionary.rb', line 150 def self.dump( klass ) method_details_mgr = get_method_details_mgr( klass ) #TODO end |
.find_method_detail(klass, external_name, conditions = nil) ⇒ Object
For a client supplied name/header - find the operator i.e appropriate call + column type
e.g Given users entry in spread sheet check for pluralization, missing underscores etc
If not nil, returned method can be used directly in for example klass.new.send( call, .… )
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 |
# File 'lib/datashift/method_dictionary.rb', line 162 def self.find_method_detail( klass, external_name, conditions = nil ) method_details_mgr = get_method_details_mgr( klass ) # first try for an exact match across all association types MethodDetail::supported_types_enum.each do |t| method_detail = method_details_mgr.find(external_name, t) return method_detail.clone if(method_detail) end # Now try various alternatives of the name substitutions(external_name).each do |n| # Try each association type, returning first that contains matching operator with name n MethodDetail::supported_types_enum.each do |t| method_detail = method_details_mgr.find(n, t) return method_detail.clone if(method_detail) end end nil end |
.find_method_detail_if_column(klass, external_name) ⇒ Object
Assignments can contain things like delegated methods, this returns a matching method details only when a true database column
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 |
# File 'lib/datashift/method_dictionary.rb', line 186 def self.find_method_detail_if_column( klass, external_name ) method_details_mgr = get_method_details_mgr( klass ) # first try for an exact match across all association types MethodDetail::supported_types_enum.each do |t| method_detail = method_details_mgr.find(external_name, t) return method_detail.clone if(method_detail && method_detail.col_type) end # Now try various alternatives substitutions(external_name).each do |n| # Try each association type, returning first that contains matching operator with name n MethodDetail::supported_types_enum.each do |t| method_detail = method_details_mgr.find(n, t) return method_detail.clone if(method_detail && method_detail.col_type) end end nil end |
.find_operators(klass, options = {}) ⇒ Object
Create simple picture of all the operator names for assignment available on an AR model, grouped by type of association (includes belongs_to and has_many which provides both << and = ) Options:
:reload => clear caches and re-perform lookup
:instance_methods => if true include instance method type 'setters' as well as model's pure columns
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 |
# File 'lib/datashift/method_dictionary.rb', line 27 def self.find_operators(klass, = {} ) raise "Cannot find operators supplied klass nil #{klass}" if(klass.nil?) logger.debug("MethodDictionary - building operators information for #{klass}") # Find the has_many associations which can be populated via << if( [:reload] || has_many[klass].nil? ) has_many[klass] = klass.reflect_on_all_associations(:has_many).map { |i| i.name.to_s } klass.reflect_on_all_associations(:has_and_belongs_to_many).inject(has_many[klass]) { |x,i| x << i.name.to_s } end # Find the belongs_to associations which can be populated via Model.belongs_to_name = OtherArModelObject if( [:reload] || belongs_to[klass].nil? ) belongs_to[klass] = klass.reflect_on_all_associations(:belongs_to).map { |i| i.name.to_s } end # Find the has_one associations which can be populated via Model.has_one_name = OtherArModelObject if( [:reload] || has_one[klass].nil? ) has_one[klass] = klass.reflect_on_all_associations(:has_one).map { |i| i.name.to_s } end # Find the model's column associations which can be populated via xxxxxx= value # Note, not all reflections return method names in same style so we convert all to # the raw form i.e without the '=' for consistency if( [:reload] || assignments[klass].nil? ) assignments[klass] = klass.column_names # get into consistent format with other assignments names i.e remove the = for now assignments[klass] += setters(klass).map{|i| i.gsub(/=/, '')} if([:instance_methods]) # Now remove all the associations assignments[klass] -= has_many[klass] if(has_many[klass]) assignments[klass] -= belongs_to[klass] if(belongs_to[klass]) assignments[klass] -= has_one[klass] if(has_one[klass]) # TODO remove assignments with id # assignments => tax_id but already in belongs_to => tax assignments[klass].uniq! assignments[klass].each do |assign| column_types[klass] ||= {} column_def = klass.columns.find{ |col| col.name == assign } column_types[klass].merge!( assign => column_def) if column_def end end end |
.for?(klass) ⇒ Boolean
Return true if dictionary has been populated for klass
16 17 18 19 |
# File 'lib/datashift/method_dictionary.rb', line 16 def self.for?(klass) any = has_many[klass] || belongs_to[klass] || has_one[klass] || assignments[klass] return any != nil end |
.get_method_details_mgr(klass) ⇒ Object
222 223 224 |
# File 'lib/datashift/method_dictionary.rb', line 222 def self.get_method_details_mgr( klass ) method_details_mgrs[klass] || MethodDetailsManager.new( klass ) end |
.has_many ⇒ Object
238 239 240 241 |
# File 'lib/datashift/method_dictionary.rb', line 238 def self.has_many @has_many ||= {} @has_many end |
.has_many_for(klass) ⇒ Object
263 264 265 |
# File 'lib/datashift/method_dictionary.rb', line 263 def self.has_many_for(klass) has_many[klass] || [] end |
.has_one ⇒ Object
243 244 245 246 |
# File 'lib/datashift/method_dictionary.rb', line 243 def self.has_one @has_one ||= {} @has_one end |
.has_one_for(klass) ⇒ Object
267 268 269 |
# File 'lib/datashift/method_dictionary.rb', line 267 def self.has_one_for(klass) has_one[klass] || [] end |
.method_details_mgrs ⇒ Object
Store a Mgr per mapped klass
228 229 230 231 |
# File 'lib/datashift/method_dictionary.rb', line 228 def self.method_details_mgrs @method_details_mgrs ||= {} @method_details_mgrs end |
.setters(klass) ⇒ Object
77 78 79 80 81 82 83 84 85 86 87 88 |
# File 'lib/datashift/method_dictionary.rb', line 77 def self.setters( klass ) # N.B In 1.8 these return strings, in 1.9 symbols. # map everything to strings a #setters = klass.accessible_attributes.sort.collect( &:to_s ) # remove methodsa that start with '_' @keep_only_pure_setters ||= Regexp.new(/^[a-zA-Z]\w+=/) setters = klass.instance_methods.grep(@keep_only_pure_setters).sort.collect( &:to_s ) setters.uniq end |
.substitutions(external_name) ⇒ Object
TODO - check out regexp to do this work better plus Inflections ?? Want to be able to handle any of [“Count On hand”, ‘count_on_hand’, “Count OnHand”, “COUNT ONHand” etc]
132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
# File 'lib/datashift/method_dictionary.rb', line 132 def self.substitutions(external_name) name = external_name.to_s [ name.downcase, name.tableize, name.gsub(' ', '_'), name.gsub(' ', '_').downcase, name.gsub(/(\s+)/, '_').downcase, name.gsub(' ', ''), name.gsub(' ', '').downcase, name.gsub(' ', '_').underscore ] end |