Permalink
Browse files

refactoring data assignment into Populator

  • Loading branch information...
1 parent dd8b8b8 commit bfd80eed588f8d8de8930998a534ac5910cf4006 Thomas Statter committed Jan 15, 2013
@@ -20,10 +20,7 @@ module DataShift
class MethodDetail
include DataShift::Logging
-
- include DataShift::Populator
- extend DataShift::Populator
-
+
def self.supported_types_enum
@type_enum ||= Set[:assignment, :belongs_to, :has_one, :has_many]
@type_enum
@@ -33,10 +30,7 @@ def self.association_types_enum
@assoc_type_enum ||= Set[:belongs_to, :has_one, :has_many]
@assoc_type_enum
end
-
- # When looking up an association, try each of these in turn till a match
- # i.e find_by_name .. find_by_title and so on, lastly try the raw id
- @@insistent_find_by_list ||= [:name, :title, :id]
+
# Name is the raw, client supplied name
attr_accessor :name
@@ -115,60 +109,6 @@ def operator_class()
@operator_class
end
- def assign(record, value )
-
- @current_value = value
-
- # logger.info("WARNING nil value supplied for Column [#{@name}]") if(@current_value.nil?)
-
- if( operator_for(:belongs_to) )
-
- #puts "DEBUG : BELONGS_TO : #{@name} : #{operator} - Lookup #{@current_value} in DB"
- insistent_belongs_to(record, @current_value)
-
- elsif( operator_for(:has_many) )
-
- #puts "DEBUG : VALUE TYPE [#{value.class.name.include?(operator.classify)}] [#{ModelMapper.class_from_string(value.class.name)}]" unless(value.is_a?(Array))
-
- # The include? check is best I can come up with right now .. to handle module/namespaces
- # TODO - can we determine the real class type of an association
- # e.g given a association taxons, which operator.classify gives us Taxon, but actually it's Spree::Taxon
- # so how do we get from 'taxons' to Spree::Taxons ? .. check if further info in reflect_on_all_associations
-
- if(value.is_a?(Array) || value.class.name.include?(operator.classify))
- record.send(operator) << value
- else
- puts "ERROR #{value.class} - Not expected type for has_many #{operator} - cannot assign"
- end
-
- elsif( operator_for(:has_one) )
-
- #puts "DEBUG : HAS_MANY : #{@name} : #{operator}(#{operator_class}) - Lookup #{@current_value} in DB"
- if(value.is_a?(operator_class))
- record.send(operator + '=', value)
- else
- logger.error("ERROR #{value.class} - Not expected type for has_one #{operator} - cannot assign")
- # TODO - Not expected type - maybe try to look it up somehow ?"
- #insistent_has_many(record, @current_value)
- end
-
- elsif( operator_for(:assignment) && @col_type )
- #puts "DEBUG : COl TYPE defined for #{@name} : #{@assignment} => #{@current_value} #{@col_type.type}"
- # puts "DEBUG : Column [#{@name}] : COl TYPE CAST: #{@current_value} => #{@col_type.type_cast( @current_value ).inspect}"
- record.send( operator + '=' , @col_type.type_cast( @current_value ) )
-
- #puts "DEBUG : MethodDetails Assignment RESULT: #{record.send(operator)}"
-
- elsif( operator_for(:assignment) )
- #puts "DEBUG : Column [#{@name}] : Brute force assignment of value #{@current_value}"
- # brute force case for assignments without a column type (which enables us to do correct type_cast)
- # so in this case, attempt straightforward assignment then if that fails, basic ops such as to_s, to_i, to_f etc
- insistent_assignment(record, @current_value)
- else
- puts "WARNING: No operator found for assignment on #{self.inspect} for Column [#{@name}]"
- end
- end
-
def pp
"#{@name} => #{operator}"
end
@@ -222,12 +162,9 @@ def insistent_has_many( record, value )
end
end
end
-
- def insistent_assignment( record, value )
- Populator::insistent_assignment( record, value, operator)
- end
- private
+ private
+
# Return the operator's expected class, if can be derived, else nil
def get_operator_class()
if(operator_for(:has_many) || operator_for(:belongs_to) || operator_for(:has_one))
@@ -23,7 +23,7 @@ def self.for?(klass)
# 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 assignment operators as well as model's pure columns
+ # :instance_methods => if true include instance method type 'setters' as well as model's pure columns
#
def self.find_operators(klass, options = {} )
@@ -51,30 +51,18 @@ def self.find_operators(klass, options = {} )
if( options[: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(options[:instance_methods])
- if(options[:instance_methods])
-
- #puts "\nDEBUG: #{klass}.methods\n#{klass.methods.sort.collect.inspect}\n"
- setters = klass.accessible_attributes.sort
-
- # Since 3.2 :instance_methods returns lots more stuff like validations,
- # which since not appropriate we remove with defined_activerecord_methods
- if(klass.respond_to? :defined_activerecord_methods)
- setters += klass.instance_methods.grep(/\w+=/).sort - klass.defined_activerecord_methods
- end
-
- # get into same format as other names
- assignments[klass] += setters.map{|i| i.gsub(/=/, '')}
- end
-
- assignments[klass] -= has_many[klass] if(has_many[klass])
-
+ # 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] -= belongs_to[klass] if(belongs_to[klass])
- assignments[klass] -= self.has_one[klass] if(self.has_one[klass])
-
assignments[klass].uniq!
#puts "\nDEBUG: DICT Setters\n#{assignments[klass]}\n"
@@ -87,6 +75,18 @@ def self.find_operators(klass, options = {} )
end
end
+ 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
def self.add( klass, operator, type = :assignment)
method_details_mgr = get_method_details_mgr( klass )
@@ -172,7 +172,7 @@ 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
+ # 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)
Oops, something went wrong.

0 comments on commit bfd80ee

Please sign in to comment.