datashift 0.10.2 → 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.10.2
1
+ 0.11.0
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "datashift"
8
- s.version = "0.10.2"
8
+ s.version = "0.11.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Thomas Statter"]
12
- s.date = "2012-10-21"
12
+ s.date = "2012-10-23"
13
13
  s.description = "Comprehensive tools to import/export between Excel/CSV and ActiveRecord databases, Rails apps, and any Ruby project."
14
14
  s.email = "rubygems@autotelik.co.uk"
15
15
  s.extra_rdoc_files = [
@@ -12,13 +12,11 @@ module DataShift
12
12
  class MethodDictionary
13
13
 
14
14
  include DataShift::Logging
15
-
16
- def initialize
17
- end
18
-
19
- # Has the dictionary been populated for klass
15
+
16
+ # Return true if dictionary has been populated for klass
20
17
  def self.for?(klass)
21
- return !(has_many[klass] || belongs_to[klass] || has_one[klass] || assignments[klass]).nil?
18
+ any = has_many[klass] || belongs_to[klass] || has_one[klass] || assignments[klass]
19
+ return any != nil
22
20
  end
23
21
 
24
22
  # Create simple picture of all the operator names for assignment available on an AR model,
@@ -84,8 +84,7 @@ module DataShift
84
84
  DataShift::MethodDictionary.build_method_details(klass)
85
85
  end
86
86
 
87
- forced = [*options[:force_inclusion]].compact
88
- forced.collect! { |f| f.downcase }
87
+ forced = [*options[:force_inclusion]].compact.collect { |f| f.to_s.downcase }
89
88
 
90
89
  @method_details, @missing_methods = [], []
91
90
 
@@ -94,7 +93,7 @@ module DataShift
94
93
  raw_col_data = col_data.to_s
95
94
 
96
95
  if(raw_col_data.nil? or raw_col_data.empty?)
97
- logger.warn("Column list contains empty or null columns")
96
+ logger.warn("Column list contains empty or null column at index #{col_index}")
98
97
  @method_details << nil
99
98
  next
100
99
  end
@@ -103,10 +102,10 @@ module DataShift
103
102
 
104
103
  md = MethodDictionary::find_method_detail( klass, raw_col_name )
105
104
 
106
- # TODO be nice if we could cheeck that the assoc on klass responds to the specified
105
+ # TODO be nice if we could check that the assoc on klass responds to the specified
107
106
  # lookup key now (nice n early)
108
107
  # active_record_helper = "find_by_#{lookup}"
109
- if(md.nil? && options[:include_all] || forced.include?(raw_col_name.downcase))
108
+ if(md.nil? && (options[:include_all] || forced.include?(raw_col_name.downcase)) )
110
109
  md = MethodDictionary::add(klass, raw_col_name)
111
110
  end
112
111
 
@@ -149,7 +148,9 @@ module DataShift
149
148
 
150
149
  # Returns true if discovered methods contain every operator in mandatory_list
151
150
  def contains_mandatory?( mandatory_list )
152
- [ [*mandatory_list] - operator_names].flatten.empty?
151
+ a = [*mandatory_list].collect { |f| f.downcase }
152
+ b = operator_names.collect { |f| f.downcase }
153
+ (a - b).empty?
153
154
  end
154
155
 
155
156
  def missing_mandatory( mandatory_list )
@@ -31,7 +31,7 @@ module DataShift
31
31
  record.send(op, value.send( f) )
32
32
  break
33
33
  rescue => e
34
- #puts "DEBUG: insistent_assignment: #{e.inspect}"
34
+ puts "DEBUG: insistent_assignment: #{e.inspect}"
35
35
  if f == Populator::insistent_method_list.last
36
36
  puts "I'm sorry I have failed to assign [#{value}] to #{operator}"
37
37
  raise "I'm sorry I have failed to assign [#{value}] to #{operator}" unless value.nil?
@@ -86,8 +86,8 @@ module DataShift
86
86
 
87
87
  include DataShift::CsvLoading
88
88
 
89
- def initialize(klass, object = nil, options = {})
90
- super( klass, object, options )
89
+ def initialize(klass, find_operators = true, object = nil, options = {})
90
+ super( klass, find_operators, object, options )
91
91
  raise "Cannot load - failed to create a #{klass}" unless @load_object
92
92
  end
93
93
 
@@ -44,7 +44,6 @@ module DataShift
44
44
  puts "\n\n\nLoading from Excel file: #{file_name}"
45
45
 
46
46
  sheet_number = options[:sheet_number] || 0
47
-
48
47
 
49
48
  @sheet = @excel.worksheet( sheet_number )
50
49
 
@@ -66,14 +65,11 @@ module DataShift
66
65
  end
67
66
 
68
67
  raise MissingHeadersError, "No headers found - Check Sheet #{@sheet} is complete and Row #{header_row_index} contains headers" if(@headers.empty?)
69
-
70
68
 
71
69
  # Create a method_mapper which maps list of headers into suitable calls on the Active Record class
72
70
  # For example if model has an attribute 'price' will map columns called Price, price, PRICE etc to this attribute
73
71
  populate_method_mapper_from_headers( @headers, options )
74
72
 
75
- @method_mapper
76
-
77
73
  logger.info "Excel Loader processing #{@sheet.num_rows} rows"
78
74
 
79
75
  loaded_objects.clear
@@ -105,10 +101,9 @@ module DataShift
105
101
 
106
102
  # Iterate over method_details, working on data out of associated Excel column
107
103
  @method_mapper.method_details.each do |method_detail|
108
-
109
-
104
+
110
105
  next unless method_detail # TODO populate unmapped with a real MethodDetail that is 'null' and create is_nil
111
-
106
+
112
107
  value = row[method_detail.column_index]
113
108
 
114
109
  contains_data = true unless(value.nil? || value.to_s.empty?)
@@ -155,8 +150,8 @@ module DataShift
155
150
 
156
151
  include ExcelLoading
157
152
 
158
- def initialize(klass, object = nil, options = {})
159
- super( klass, object, options )
153
+ def initialize(klass, find_operators = true, object = nil, options = {})
154
+ super( klass, find_operators, object, options )
160
155
  raise "Cannot load - failed to create a #{klass}" unless @load_object
161
156
  end
162
157
 
@@ -39,25 +39,25 @@ module DataShift
39
39
  #
40
40
  # Options to drive building the method dictionary for a class, enabling headers to be mapped to operators on that class.
41
41
  #
42
+ # find_operators [default = true] : Populate method dictionary with operators and method details
43
+ #
42
44
  # Options
43
- # :load [default = true] : Load the method dictionary for object_class
44
45
  #
45
46
  # :reload : Force load of the method dictionary for object_class even if already loaded
46
- # :instance_methods : Include setter type instance methods for assignment as well as AR columns
47
-
48
-
49
- def initialize(object_class, object = nil, options = {})
47
+ # :instance_methods : Include setter/delegate style instance methods for assignment, as well as AR columns
48
+ #
49
+ def initialize(object_class, find_operators = true, object = nil, options = {})
50
50
  @load_object_class = object_class
51
-
51
+
52
52
  # Gather names of all possible 'setter' methods on AR class (instance variables and associations)
53
- unless(MethodDictionary::for?(object_class) && options[:reload] == false)
54
- #puts "Building Method Dictionary for class #{object_class}"
53
+ if((find_operators && !MethodDictionary::for?(object_class)) || options[:reload])
54
+ puts "Building Method Dictionary for class #{object_class}"
55
55
  DataShift::MethodDictionary.find_operators( @load_object_class, :reload => options[:reload], :instance_methods => options[:instance_methods] )
56
56
 
57
57
  # Create dictionary of data on all possible 'setter' methods which can be used to
58
58
  # populate or integrate an object of type @load_object_class
59
59
  DataShift::MethodDictionary.build_method_details(@load_object_class)
60
- end if(options[:load] || options[:reload])
60
+ end
61
61
 
62
62
  @method_mapper = DataShift::MethodMapper.new
63
63
  @config = options.dup # clone can cause issues like 'can't modify frozen hash'
@@ -152,10 +152,10 @@ module DataShift
152
152
  raise MappingDefinitionError, "Missing mappings for columns : #{@method_mapper.missing_methods.join(",")}" if(strict)
153
153
  end
154
154
 
155
- unless(@method_mapper.contains_mandatory?(mandatory) )
156
- @method_mapper.missing_mandatory(mandatory).each { |e| puts "ERROR: Mandatory column missing - expected column '#{e}'" }
155
+ unless(mandatory.empty? || @method_mapper.contains_mandatory?(mandatory) )
156
+ @method_mapper.missing_mandatory(mandatory).each { |er| puts "ERROR: Mandatory column missing - expected column '#{er}'" }
157
157
  raise MissingMandatoryError, "Mandatory columns missing - please fix and retry."
158
- end unless(mandatory.empty?)
158
+ end
159
159
 
160
160
  @method_mapper
161
161
  end
@@ -184,6 +184,7 @@ module DataShift
184
184
  prepare_data(method_detail, data)
185
185
  process()
186
186
  else
187
+ puts "No matching method found for column #{column_name}"
187
188
  @load_object.errors.add(:base, "No matching method found for column #{column_name}")
188
189
  end
189
190
  end
@@ -20,20 +20,16 @@ module DataShift
20
20
 
21
21
  attr_writer :attach_to_field
22
22
  attr_reader :attachment_path, :loading_files_cache
23
+
23
24
 
24
-
25
- # If we have instantiated a method detail based on the attch to class and fields
26
- # return that otherwise return the raw format of :attach_to_find_by_field
27
-
28
- def attach_to_field
29
- @attach_to_method_detail || @attach_to_field
30
- end
31
-
25
+ # Constructor
26
+ #
32
27
  # Options
33
-
28
+ #
34
29
  # => :attach_to_klass
35
- # A class that has a relationship with - has_many, has_one or belongs_to - the attachment
30
+ # A class that has a relationship with the attachment (has_many, has_one or belongs_to etc)
36
31
  # The instance of :attach_to_klass can be searched for and the new attachment assigned.
32
+ #
37
33
  # Examples
38
34
  # Owner has_many pdfs and mp3 files as Digitals .... :attach_to_klass = Owner
39
35
  # User has a single image used as an avatar ... :attach_to_klass = User
@@ -41,6 +37,7 @@ module DataShift
41
37
  # => :attach_to_find_by_field
42
38
  # For the :attach_to_klass, this is the field used to search for the parent
43
39
  # object to assign the new attachment to.
40
+ #
44
41
  # Examples
45
42
  # Owner has a unique 'name' field ... :attach_to_find_by_field = :name
46
43
  # User has a unique 'login' field ... :attach_to_klass = :login
@@ -48,27 +45,31 @@ module DataShift
48
45
  # => :attach_to_field
49
46
  # Attribute/association to assign attachment to on :attach_to_klass.
50
47
  # Examples
48
+ #
51
49
  # :attach_to_field => digitals : Owner.digitals = attachment
52
50
  # :attach_to_field => avatar : User.avatar = attachment
53
51
  #
54
52
  #
55
- def initialize(attachment_klazz, attachment = nil, options = {})
53
+ def initialize(attachment_klazz, find_operators = true, attachment = nil, options = {})
56
54
 
57
55
  init_from_options( options )
58
-
59
- opts = options.merge(:load => false)
60
-
61
- super( attachment_klazz, attachment, opts )
56
+
57
+ super( attachment_klazz, find_operators, attachment, options.dup )
62
58
 
63
59
  puts "Attachment Class is #{load_object_class}" if(@verbose)
64
60
 
65
61
  raise "Failed to create Attachment for loading" unless @load_object
66
62
  end
63
+
67
64
 
65
+ # Options
66
+ # :reload
67
+ # :attach_to_klass, :attach_to_field, :attach_to_find_by_field
68
+ #
68
69
  def init_from_options( options )
69
-
70
- @attach_to_klass = options[:attach_to_klass] || @attach_to_klass || nil
71
70
 
71
+ @attach_to_klass = options[:attach_to_klass] || @attach_to_klass || nil
72
+
72
73
  unless(@attach_to_klass.nil? || (MethodDictionary::for?(@attach_to_klass) && options[:reload] == false))
73
74
  #puts "Building Method Dictionary for class #{object_class}"
74
75
  DataShift::MethodDictionary.find_operators( @attach_to_klass, :reload => options[:reload], :instance_methods => true )
@@ -86,6 +87,15 @@ module DataShift
86
87
  end
87
88
  end
88
89
 
90
+
91
+ # If we have instantiated a method detail based on the attach to class and fields
92
+ # return that otherwise return the raw format of :attach_to_find_by_field
93
+
94
+ def attach_to_field
95
+ @attach_to_method_detail || @attach_to_field
96
+ end
97
+
98
+
89
99
  # This version creates attachments and also attaches them to instances of :attach_to_klazz
90
100
  #
91
101
  # Options
@@ -125,7 +135,7 @@ module DataShift
125
135
 
126
136
  record = nil
127
137
 
128
- puts "try to find record where #{attach_to_find_by_field} == #{base_name}"
138
+ puts "Attempting to find matching record where #{attach_to_find_by_field} ~= #{base_name}"
129
139
  record = get_record_by(attach_to_klass, attach_to_find_by_field, base_name, split_on)
130
140
 
131
141
  if(record)
@@ -139,12 +149,11 @@ module DataShift
139
149
 
140
150
  # Check if attachment must have an associated record
141
151
  if(record)
142
- puts "now create attachment"
143
152
  reset()
144
153
 
145
154
  create_attachment(@load_object_class, file_name, record, attach_to_field, options)
146
155
 
147
- puts "Added Attachment #{File.basename(file_name)} to #{record.send(attach_to_find_by_field)} : #{record.id}" if(@verbose)
156
+ puts "Added Attachment #{File.basename(file_name)} to #{record.send(attach_to_find_by_field)}(id : #{record.id})" if(@verbose)
148
157
  end
149
158
 
150
159
  end
@@ -153,7 +162,7 @@ module DataShift
153
162
  FileUtils.mkdir_p('MissingAttachmentRecords') unless File.directory?('MissingAttachmentRecords')
154
163
 
155
164
  puts "WARNING : #{missing_records.size} of #{loading_files_cache.size} files could not be attached to a #{@load_object_class}"
156
- puts "For your convenience a copy of files with MISSING #{@load_object_class} : ./MissingAttachmentRecords"
165
+ puts "For your convenience files with MISSING #{attach_to_klass} have been copied to : MissingAttachmentRecords"
157
166
  missing_records.each do |i|
158
167
  puts "Copying #{i} to MissingAttachmentRecords folder" if(options[:verbose])
159
168
  FileUtils.cp( i, 'MissingAttachmentRecords') unless(options[:dummy] == 'true')
@@ -56,7 +56,7 @@ module DataShift
56
56
  #
57
57
  # Pass through hash of attributes to klass initializer
58
58
  #
59
- # :has_attached_file_attribute
59
+ # :has_attached_file_name
60
60
  #
61
61
  # Paperclip attachment name defined with macro 'has_attached_file :name'
62
62
  #
@@ -71,7 +71,7 @@ module DataShift
71
71
  #
72
72
  def create_attachment(klass, attachment_path, record = nil, attach_to_record_field = nil, options = {})
73
73
 
74
- has_attached_file_attribute = options[has_attached_file_attribute] ? options[:has_attached_file_attribute].to_sym : :attachment
74
+ has_attached_file_attribute = options[:has_attached_file_name] ? options[:has_attached_file_name].to_sym : :attachment
75
75
 
76
76
  attributes = { has_attached_file_attribute => get_file(attachment_path) }
77
77
 
@@ -81,6 +81,7 @@ module DataShift
81
81
 
82
82
  #attributes.merge!(attach_to_record_field.to_sym => record) if(record && attach_to_record_field)
83
83
 
84
+ puts attributes.inspect
84
85
  begin
85
86
 
86
87
  @attachment = klass.new(attributes, :without_protection => true)
@@ -92,11 +93,12 @@ module DataShift
92
93
  attach_to_record_field.assign(record, @attachment)
93
94
  else
94
95
  # assume its not a has_many and try basic send
95
- record.send(attach_to_record_field + '=', @attachment)
96
+ record.send("#{attach_to_record_field}=", @attachment)
96
97
  end if(record && attach_to_record_field)
97
98
 
98
99
  else
99
100
  puts "ERROR : Problem saving to DB : #{@attachment.inspect}"
101
+ puts @attachment.errors.messages.inspect
100
102
  end
101
103
 
102
104
  @attachment
@@ -14,9 +14,6 @@ module DataShift
14
14
 
15
15
  include DataShift::Paperclip
16
16
 
17
- def initialize(attachment_klazz, attachment = nil, options = {})
18
- super( attachment_klazz, attachment, options )
19
- end
20
17
 
21
18
  # Note the paperclip attachment model defines the storage path via something like :
22
19
  #
@@ -33,15 +30,17 @@ module DataShift
33
30
  # :viewable_record
34
31
  #
35
32
  def create_attachment(klass, attachment_path, record = nil, attach_to_record_field = nil, options = {})
36
-
37
- attachment_options = options.dup
38
-
39
- attributes = {:alt => (options[:alt] || "") }
40
-
41
- attributes[:position] = (!options[:position] && record and record.respond_to?(:images)) ? record.images.length : 0
33
+
34
+ image_attributes = { :attributes =>
35
+ { :alt => (options[:alt] || ""),
36
+ :position => (!options[:position] && record and record.respond_to?(:images)) ? record.images.length : 0
37
+ }
38
+ }
42
39
 
43
- attachment_options.merge!( attributes )
44
-
40
+ attachment_options = options.dup.merge(image_attributes)
41
+
42
+ #puts "DEBUG : create_attachment options : #{attachment_options.inspect}"
43
+
45
44
  super(klass, attachment_path, record, attach_to_record_field, attachment_options)
46
45
  end
47
46
 
@@ -63,11 +63,11 @@ module Datashift
63
63
  logger.info("INFO: Using loader : #{loader.class}")
64
64
  rescue
65
65
  logger.error("INFO: No specific #{model}Loader found - using generic ExcelLoader")
66
- loader = DataShift::ExcelLoader.new(klass)
66
+ loader = DataShift::ExcelLoader.new(klass, true)
67
67
  end
68
68
  else
69
69
  logger.info("No Loader specified - using generic ExcelLoader")
70
- loader = DataShift::ExcelLoader.new(klass)
70
+ loader = DataShift::ExcelLoader.new(klass, true)
71
71
  end
72
72
 
73
73
  logger.info("ARGS #{options.inspect}")
@@ -22,11 +22,32 @@ module Datashift
22
22
 
23
23
  include DataShift::Logging
24
24
 
25
- desc "attach", "Attach files from a directory\nThe attachment file names must contain the lookup info within them.
26
- The instance of :attach_to_klass can be searched for and the new attachment assigned.
25
+ desc "attach", "Create paperclip attachments and attach to a Model from files in a directory.
26
+ This is specifically for the use case where the paperclip attachments are stored in a class, such as Image, Icon, Asset,
27
+ and this class has a relationship, such as belongs_to, with another class, such as Product, User, Document.
28
+
29
+ Each matching file is used to create an instance of the paperclip attachment, given by :attachment_klass.
30
+
31
+ The class with the relationship, can be specified via :attach_to_klass
32
+
27
33
  Examples
28
- Owner has_many pdfs and mp3 files as Digitals .... :attach_to_klass = Owner
29
- User has a single image used as an avatar ... :attach_to_klass = User"
34
+ Owner has_many pdfs and mp3 files as Digitals .... :attachment_klass = Digital and :attach_to_klass = Owner
35
+ User has a single Image used as an avatar ... attachment_klass = Image and :attach_to_klass = User
36
+
37
+ The file name is used to lookup the instance of :attach_to_klass to assign the new attachment to, via :attach_to_find_by_field
38
+
39
+ So say we have a file called smithj_avatar.gif, and we want to lookup Users by login
40
+
41
+ :attach_to_find_by_field = login => Run a loookup based on find_by_login == 'smithj'
42
+
43
+ Once instance of :attach_to_klass found, the new attachment is assigned.
44
+
45
+ The attribute to assign new attachment to is gtiven by :attach_to_field
46
+
47
+ Examples
48
+ :attach_to_field => digitals : Owner.digitals = attachment(Digital)
49
+ :attach_to_field => avatar : User.avatar = attachment(Image)"
50
+
30
51
 
31
52
  # :dummy => dummy run without actual saving to DB
32
53
  method_option :input, :aliases => '-i', :required => true, :desc => "The input path containing images "
@@ -35,13 +56,11 @@ module Datashift
35
56
  method_option :recursive, :aliases => '-r', :type => :boolean, :desc => "Scan sub directories of input for images"
36
57
 
37
58
  method_option :attachment_klass, :required => true, :aliases => '-a', :desc => "Ruby Class name of the Attachment e.g Image, Icon"
38
- method_option :attach_to_klass, :required => true, :aliases => '-k', :desc => "A class that has a relationship with the attachment (has_many, has_one, belongs_to)"
39
-
40
-
41
- method_option :attach_to_field, :required => true, :aliases => '-f', :desc => "Attachment belongs to field e.g Product.image, Blog.digital"
42
59
 
60
+ method_option :attach_to_klass, :required => true, :aliases => '-k', :desc => "A class that has a relationship with the attachment (has_many, has_one, belongs_to)"
43
61
  method_option :attach_to_find_by_field, :required => true, :aliases => '-l', :desc => "The field to use to find the :attach_to_klass record"
44
-
62
+ method_option :attach_to_field, :required => true, :aliases => '-f', :desc => "Attachment belongs to field e.g Product.image, Blog.digital"
63
+
45
64
 
46
65
  # => :attach_to_find_by_field
47
66
  # For the :attach_to_klass, this is the field used to search for the parent
@@ -31,9 +31,6 @@ describe 'Excel Loader' do
31
31
  Category.find_or_create_by_reference(cat)
32
32
  end
33
33
 
34
- DataShift::MethodDictionary.find_operators( Category )
35
-
36
- DataShift::MethodDictionary.build_method_details( Category )
37
34
 
38
35
  end
39
36
 
@@ -57,6 +54,11 @@ describe 'Excel Loader' do
57
54
 
58
55
  it "should process multiple associationss from single column" do
59
56
 
57
+
58
+ DataShift::MethodDictionary.find_operators( Category )
59
+
60
+ DataShift::MethodDictionary.build_method_details( Category )
61
+
60
62
  Project.find_by_title('001').should be_nil
61
63
  count = Project.count
62
64
 
@@ -8,25 +8,34 @@
8
8
  # and a classes different types of assignment operators
9
9
  #
10
10
  require File.join(File.dirname(__FILE__), 'spec_helper')
11
-
11
+
12
+ require 'method_dictionary'
13
+
12
14
  describe 'Method Dictionary' do
13
15
 
16
+
14
17
  include_context "ActiveRecordTestModelsConnected"
15
18
 
19
+ include DataShift
16
20
 
17
21
  before(:each) do
18
22
  MethodDictionary.clear
19
- MethodDictionary.find_operators( Project )
20
- MethodDictionary.find_operators( Milestone )
21
23
  end
22
24
 
23
25
  it "should store dictionary for multiple AR models" do
26
+
27
+ MethodDictionary.find_operators( Project )
28
+ MethodDictionary.find_operators( Milestone )
29
+
24
30
  MethodDictionary.assignments.size.should == 2
25
31
  MethodDictionary.has_many.size.should == 2
26
32
  end
27
33
 
28
34
  it "should populate method dictionary for a given AR model" do
29
35
 
36
+ MethodDictionary.find_operators( Project )
37
+ MethodDictionary.find_operators( Milestone )
38
+
30
39
  MethodDictionary.has_many.should_not be_empty
31
40
  MethodDictionary.has_many[Project].should include('milestones')
32
41
 
@@ -48,6 +57,8 @@ describe 'Method Dictionary' do
48
57
 
49
58
  it "should populate assigment members without the equivalent association names" do
50
59
 
60
+ MethodDictionary.find_operators( Project )
61
+
51
62
  # we should remove has-many & belongs_to from basic assignment set as they require a DB lookup
52
63
  # or a Model.create call, not a simple assignment
53
64
 
@@ -58,6 +69,9 @@ describe 'Method Dictionary' do
58
69
 
59
70
  it "should populate assignment operators for method details for different forms of a column name" do
60
71
 
72
+ MethodDictionary.find_operators( Project )
73
+ MethodDictionary.find_operators( Milestone )
74
+
61
75
  MethodDictionary.build_method_details( Project )
62
76
 
63
77
  [:value_as_string, 'value_as_string', "VALUE as_STRING", "value as string"].each do |format|
@@ -83,6 +97,8 @@ describe 'Method Dictionary' do
83
97
 
84
98
  it "should populate column types for assignment operators in method details" do
85
99
 
100
+ MethodDictionary.find_operators( Project )
101
+
86
102
  MethodDictionary.build_method_details( Project )
87
103
 
88
104
  [:value_as_string, 'value_as_string', "VALUE as_STRING", "value as string"].each do |format|
@@ -101,6 +117,8 @@ describe 'Method Dictionary' do
101
117
 
102
118
  it "should populate required Class for assignment operators based on column type" do
103
119
 
120
+ MethodDictionary.find_operators( Project )
121
+
104
122
  MethodDictionary.build_method_details( Project )
105
123
 
106
124
  [:value_as_string, 'value_as_string', "VALUE as_STRING", "value as string"].each do |format|
@@ -116,6 +134,9 @@ describe 'Method Dictionary' do
116
134
 
117
135
  it "should populate belongs_to operator for method details for different forms of a column name" do
118
136
 
137
+ MethodDictionary.find_operators( Project )
138
+ MethodDictionary.find_operators( Milestone )
139
+
119
140
  MethodDictionary.build_method_details( Project )
120
141
  MethodDictionary.build_method_details( Milestone )
121
142
 
@@ -184,10 +205,24 @@ describe 'Method Dictionary' do
184
205
  method_details.operator_class.should == LongAndComplexTableLinkedToVersion
185
206
  end
186
207
  end
208
+
209
+ it "should return false on for?(klass) if find_operators hasn't been called for klass" do
210
+ MethodDictionary.clear
211
+ MethodDictionary::for?(Project).should == false
212
+ MethodDictionary::find_operators(Project)
213
+ MethodDictionary::for?(Project).should == true
214
+
215
+ end
187
216
 
188
-
217
+ it "should return false on for?(klass) if find_operators hasn't been called for klass" do
218
+ MethodDictionary.clear
219
+ MethodDictionary::for?(Project).should == false
220
+ end
221
+
189
222
  it "should find has_many operator for method details" do
190
-
223
+
224
+ MethodDictionary.find_operators( Project )
225
+
191
226
  MethodDictionary.build_method_details( Project )
192
227
 
193
228
  [:milestones, "Mile Stones", 'mileSTONES', 'MileStones'].each do |format|
@@ -208,6 +243,9 @@ describe 'Method Dictionary' do
208
243
 
209
244
 
210
245
  it "should return nil when non existent column name" do
246
+
247
+ MethodDictionary.find_operators( Project )
248
+
211
249
  ["On sale", 'on_sale'].each do |format|
212
250
  detail = MethodDictionary.find_method_detail( Project, format )
213
251
 
@@ -221,11 +259,16 @@ describe 'Method Dictionary' do
221
259
  end
222
260
 
223
261
  it "should not by default map setter methods" do
262
+ MethodDictionary.find_operators( Milestone )
263
+
224
264
  MethodDictionary.assignments[Milestone].should_not include('title')
225
265
  end
226
266
 
227
267
  it "should support reload and inclusion of setter methods" do
228
268
 
269
+ MethodDictionary.find_operators( Project )
270
+ MethodDictionary.find_operators( Milestone )
271
+
229
272
  MethodDictionary.assignments[Milestone].should_not include('title')
230
273
 
231
274
  MethodDictionary.find_operators( Milestone, :reload => true, :instance_methods => true )
@@ -38,7 +38,7 @@ describe 'PaperClip Bulk Loader' do
38
38
  end
39
39
 
40
40
  it "should create a new paperclip loader and define attachment class" do
41
- loader = DataShift::Paperclip::AttachmentLoader.new(@attachment_klass, nil, @common_options)
41
+ loader = DataShift::Paperclip::AttachmentLoader.new(@attachment_klass, true, nil, @common_options)
42
42
 
43
43
  loader.load_object_class.should == Digital
44
44
  loader.load_object.should be_a Digital
@@ -50,7 +50,7 @@ describe 'PaperClip Bulk Loader' do
50
50
 
51
51
  opts = { :attach_to_klass => Owner }.merge(@common_options)
52
52
 
53
- loader = DataShift::Paperclip::AttachmentLoader.new(@attachment_klass, nil, opts)
53
+ loader = DataShift::Paperclip::AttachmentLoader.new(@attachment_klass, true, nil, opts)
54
54
 
55
55
  loader.attach_to_klass.should == Owner
56
56
  end
metadata CHANGED
@@ -1,58 +1,50 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: datashift
3
- version: !ruby/object:Gem::Version
4
- version: 0.10.2
3
+ version: !ruby/object:Gem::Version
5
4
  prerelease:
5
+ version: 0.11.0
6
6
  platform: ruby
7
- authors:
7
+ authors:
8
8
  - Thomas Statter
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-10-21 00:00:00.000000000 Z
13
- dependencies:
14
- - !ruby/object:Gem::Dependency
12
+
13
+ date: 2012-10-23 00:00:00 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
15
16
  name: spreadsheet
16
- requirement: !ruby/object:Gem::Requirement
17
+ requirement: &id001 !ruby/object:Gem::Requirement
17
18
  none: false
18
- requirements:
19
- - - ! '>='
20
- - !ruby/object:Gem::Version
21
- version: '0'
19
+ requirements:
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: "0"
22
23
  type: :runtime
23
24
  prerelease: false
24
- version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
- requirements:
27
- - - ! '>='
28
- - !ruby/object:Gem::Version
29
- version: '0'
30
- - !ruby/object:Gem::Dependency
25
+ version_requirements: *id001
26
+ - !ruby/object:Gem::Dependency
31
27
  name: rubyzip
32
- requirement: !ruby/object:Gem::Requirement
28
+ requirement: &id002 !ruby/object:Gem::Requirement
33
29
  none: false
34
- requirements:
35
- - - ! '>='
36
- - !ruby/object:Gem::Version
37
- version: '0'
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: "0"
38
34
  type: :runtime
39
35
  prerelease: false
40
- version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
- requirements:
43
- - - ! '>='
44
- - !ruby/object:Gem::Version
45
- version: '0'
46
- description: Comprehensive tools to import/export between Excel/CSV and ActiveRecord
47
- databases, Rails apps, and any Ruby project.
36
+ version_requirements: *id002
37
+ description: Comprehensive tools to import/export between Excel/CSV and ActiveRecord databases, Rails apps, and any Ruby project.
48
38
  email: rubygems@autotelik.co.uk
49
39
  executables: []
40
+
50
41
  extensions: []
51
- extra_rdoc_files:
42
+
43
+ extra_rdoc_files:
52
44
  - LICENSE.txt
53
45
  - README.markdown
54
46
  - README.rdoc
55
- files:
47
+ files:
56
48
  - .document
57
49
  - LICENSE.txt
58
50
  - README.markdown
@@ -229,28 +221,31 @@ files:
229
221
  - tasks/file_tasks.rake
230
222
  - tasks/word_to_seedfu.rake
231
223
  homepage: http://github.com/autotelik/datashift
232
- licenses:
224
+ licenses:
233
225
  - MIT
234
226
  post_install_message:
235
227
  rdoc_options: []
236
- require_paths:
228
+
229
+ require_paths:
237
230
  - lib
238
- required_ruby_version: !ruby/object:Gem::Requirement
231
+ required_ruby_version: !ruby/object:Gem::Requirement
239
232
  none: false
240
- requirements:
241
- - - ! '>='
242
- - !ruby/object:Gem::Version
243
- version: '0'
244
- required_rubygems_version: !ruby/object:Gem::Requirement
233
+ requirements:
234
+ - - ">="
235
+ - !ruby/object:Gem::Version
236
+ version: "0"
237
+ required_rubygems_version: !ruby/object:Gem::Requirement
245
238
  none: false
246
- requirements:
247
- - - ! '>='
248
- - !ruby/object:Gem::Version
249
- version: '0'
239
+ requirements:
240
+ - - ">="
241
+ - !ruby/object:Gem::Version
242
+ version: "0"
250
243
  requirements: []
244
+
251
245
  rubyforge_project:
252
246
  rubygems_version: 1.8.24
253
247
  signing_key:
254
248
  specification_version: 3
255
249
  summary: Shift data betwen Excel/CSV and any Ruby app
256
250
  test_files: []
251
+