Class: DataShift::MethodMapper
- Includes:
- Logging
- Defined in:
- lib/datashift/method_mapper.rb
Instance Attribute Summary collapse
-
#method_details ⇒ Object
Returns the value of attribute method_details.
-
#missing_methods ⇒ Object
Returns the value of attribute missing_methods.
Instance Method Summary collapse
-
#contains_mandatory?(mandatory_list) ⇒ Boolean
Returns true if discovered methods contain every operator in mandatory_list.
-
#initialize ⇒ MethodMapper
constructor
A new instance of MethodMapper.
-
#map_inbound_headers_to_methods(klass, columns, options = {}) ⇒ Object
Build complete picture of the methods whose names listed in columns Handles method names as defined by a user, from spreadsheets or file headers where the names specified may not be exactly as required e.g handles capitalisation, white space, _ etc.
-
#method_names ⇒ Object
TODO populate unmapped with a real MethodDetail that is ‘null’ and create is_nil.
- #missing_mandatory(mandatory_list) ⇒ Object
-
#operator_names ⇒ Object
The true operator names discovered from model.
Methods included from Logging
Constructor Details
#initialize ⇒ MethodMapper
Returns a new instance of MethodMapper.
26 27 28 |
# File 'lib/datashift/method_mapper.rb', line 26 def initialize @method_details = [] end |
Instance Attribute Details
#method_details ⇒ Object
Returns the value of attribute method_details.
24 25 26 |
# File 'lib/datashift/method_mapper.rb', line 24 def method_details @method_details end |
#missing_methods ⇒ Object
Returns the value of attribute missing_methods.
24 25 26 |
# File 'lib/datashift/method_mapper.rb', line 24 def missing_methods @missing_methods end |
Instance Method Details
#contains_mandatory?(mandatory_list) ⇒ Boolean
Returns true if discovered methods contain every operator in mandatory_list
160 161 162 163 164 165 166 |
# File 'lib/datashift/method_mapper.rb', line 160 def contains_mandatory?( mandatory_list ) a = [*mandatory_list].collect { |f| f.downcase } puts a.inspect b = operator_names.collect { |f| f.downcase } puts b.inspect (a - b).empty? end |
#map_inbound_headers_to_methods(klass, columns, options = {}) ⇒ Object
Build complete picture of the methods whose names listed in columns Handles method names as defined by a user, from spreadsheets or file headers where the names specified may not be exactly as required e.g handles capitalisation, white space, _ etc
The header can also contain the fields to use in lookups, separated with Delimiters ::column_delim For example specify that lookups on has_one association called ‘product’, be performed using name’
product:name
The header can also contain a default value for the lookup field, again separated with Delimiters ::column_delim
For example specify lookups on assoc called ‘user’, be performed using ‘email’ == ‘[email protected]’
user:email:[email protected]
Returns: Array of matching method_details, including nils for non matched items
N.B Columns that could not be mapped are left in the array as NIL
This is to support clients that need to map via the index on @method_details
Other callers can simply call compact on the results if the index not important.
The MethodDetails instance will contain a pointer to the column index from which it was mapped.
Options:
[:force_inclusion] : List of columns that do not map to any operator but should be included in processing.
This provides the opportunity for loaders to provide specific methods to handle these fields
when no direct operator is available on the model or it's associations
[:include_all] : Include all headers in processing - takes precedence of :force_inclusion
63 64 65 66 67 68 69 70 71 72 73 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 101 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 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
# File 'lib/datashift/method_mapper.rb', line 63 def map_inbound_headers_to_methods( klass, columns, = {} ) # If klass not in MethodDictionary yet, add to dictionary all possible operators on klass # which can be used to map headers and populate an object of type klass unless(MethodDictionary::for?(klass)) DataShift::MethodDictionary.find_operators(klass) DataShift::MethodDictionary.build_method_details(klass) end mgr = DataShift::MethodDictionary.method_details_mgrs[klass] forced = [*[:force_inclusion]].compact.collect { |f| f.to_s.downcase } @method_details, @missing_methods = [], [] columns.each_with_index do |col_data, col_index| raw_col_data = col_data.to_s if(raw_col_data.nil? or raw_col_data.empty?) logger.warn("Column list contains empty or null column at index #{col_index}") @method_details << nil next end raw_col_name, where_field, where_value, *data = raw_col_data.split(Delimiters::column_delim) md = MethodDictionary::find_method_detail(klass, raw_col_name) if(md.nil?) if([:include_all] || forced.include?(raw_col_name.downcase)) logger.debug("Operator #{raw_col_name} not found but forced inclusion operative") md = MethodDictionary::add(klass, raw_col_name) end end if(md) md.name = raw_col_name md.column_index = col_index # put data back as string for now - leave it to clients to decide what to do with it later Populator::set_header_default_data(md.operator, data.join(Delimiters::column_delim)) if(where_field) logger.info("Lookup query field [#{where_field}] - specified for association #{md.operator}") md.find_by_value = where_value # Example : # Project:name:My Best Project # User (klass) has_one project (operator) lookup by name (find_by_operator) == 'My Best Project' (find_by_value) # User.project.where( :name => 'My Best Project') # check the finder method name is a valid field on the actual association class if(klass.reflect_on_association(md.operator) && klass.reflect_on_association(md.operator).klass.new.respond_to?(where_field)) md.find_by_operator = where_field logger.info("Complex Lookup specified for [#{md.operator}] : on field [#{md.find_by_operator}] (optional value [#{md.find_by_value}])") else logger.warn("Find by operator [#{where_field}] Not Found on association [#{md.operator}] on Class #{klass.name} (#{md.inspect})") logger.warn("Check column (#{md.column_index}) heading - e.g association field names are case sensitive") # TODO - maybe derived loaders etc want this data for another purpose - should we stash elsewhere ? end end else # TODO populate unmapped with a real MethodDetail that is 'null' and create is_nil logger.warn("No operator or association found for Header #{raw_col_name}") @missing_methods << raw_col_name end logger.debug("Column [#{col_data}] (#{col_index}) - mapped to :\n#{md.inspect}") @method_details << md end @method_details end |
#method_names ⇒ Object
TODO populate unmapped with a real MethodDetail that is ‘null’ and create is_nil
The raw client supplied names
149 150 151 |
# File 'lib/datashift/method_mapper.rb', line 149 def method_names() @method_details.compact.collect( &:name ) end |
#missing_mandatory(mandatory_list) ⇒ Object
168 169 170 |
# File 'lib/datashift/method_mapper.rb', line 168 def missing_mandatory( mandatory_list ) [ [*mandatory_list] - operator_names].flatten end |
#operator_names ⇒ Object
The true operator names discovered from model
154 155 156 |
# File 'lib/datashift/method_mapper.rb', line 154 def operator_names() @method_details.compact.collect( &:operator ) end |