datashift 0.10.1 → 0.10.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. data/Rakefile +6 -1
  2. data/VERSION +1 -1
  3. data/datashift.gemspec +13 -6
  4. data/lib/datashift.rb +2 -20
  5. data/lib/datashift/exceptions.rb +2 -0
  6. data/lib/datashift/method_detail.rb +15 -29
  7. data/lib/datashift/method_dictionary.rb +36 -21
  8. data/lib/datashift/method_mapper.rb +56 -16
  9. data/lib/datashift/populator.rb +23 -0
  10. data/lib/datashift/querying.rb +86 -0
  11. data/lib/generators/csv_generator.rb +1 -4
  12. data/lib/generators/excel_generator.rb +28 -11
  13. data/lib/generators/generator_base.rb +12 -0
  14. data/lib/loaders/csv_loader.rb +9 -3
  15. data/lib/loaders/excel_loader.rb +14 -6
  16. data/lib/loaders/loader_base.rb +38 -125
  17. data/lib/loaders/paperclip/attachment_loader.rb +130 -62
  18. data/lib/loaders/paperclip/datashift_paperclip.rb +46 -12
  19. data/lib/loaders/paperclip/image_loading.rb +25 -41
  20. data/lib/thor/generate.thor +16 -6
  21. data/lib/thor/paperclip.thor +25 -5
  22. data/spec/Gemfile +3 -2
  23. data/spec/MissingAttachmentRecords/DEMO_001_ror_bag.jpeg +0 -0
  24. data/spec/{fixtures/images/DEMO_002_Powerstation.jpg → MissingAttachmentRecords/DEMO_002_Powerstation.jpeg} +0 -0
  25. data/spec/MissingAttachmentRecords/DEMO_002_Powerstation.jpg +0 -0
  26. data/spec/MissingAttachmentRecords/DEMO_003_ror_mug.jpeg +0 -0
  27. data/spec/MissingAttachmentRecords/DEMO_004_ror_ringer.jpeg +0 -0
  28. data/spec/excel_generator_spec.rb +28 -0
  29. data/spec/excel_loader_spec.rb +12 -17
  30. data/spec/fixtures/config/database.yml +1 -1
  31. data/spec/fixtures/db/datashift_test_models_db.sqlite +0 -0
  32. data/spec/fixtures/db/migrate/20121009161700_add_digitals.rb +24 -0
  33. data/spec/fixtures/images/DEMO_002_Powerstation.jpeg +0 -0
  34. data/spec/fixtures/models/digital.rb +14 -0
  35. data/spec/fixtures/models/owner.rb +5 -3
  36. data/spec/fixtures/test_model_defs.rb +4 -62
  37. data/spec/loader_spec.rb +42 -50
  38. data/spec/method_dictionary_spec.rb +3 -10
  39. data/spec/method_mapper_spec.rb +79 -20
  40. data/spec/paperclip_loader_spec.rb +95 -0
  41. data/spec/spec_helper.rb +44 -8
  42. metadata +236 -224
  43. data/lib/helpers/rake_utils.rb +0 -42
  44. data/spec/fixtures/models/test_model_defs.rb +0 -67
@@ -22,8 +22,12 @@ module Datashift
22
22
 
23
23
  include DataShift::Logging
24
24
 
25
- desc "attach", "Attach files from a directory\nwhere file names contain somewhere the lookup info"
26
-
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.
27
+ 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"
30
+
27
31
  # :dummy => dummy run without actual saving to DB
28
32
  method_option :input, :aliases => '-i', :required => true, :desc => "The input path containing images "
29
33
 
@@ -31,11 +35,27 @@ module Datashift
31
35
  method_option :recursive, :aliases => '-r', :type => :boolean, :desc => "Scan sub directories of input for images"
32
36
 
33
37
  method_option :attachment_klass, :required => true, :aliases => '-a', :desc => "Ruby Class name of the Attachment e.g Image, Icon"
34
- method_option :attach_to_klass, :required => true, :aliases => '-k', :desc => "Ruby Class name attachment belongs to e.g Product, Blog"
35
- method_option :attach_to_klass_field, :required => true, :aliases => '-f', :desc => "Attachment belongs to field e.g Product.image, Blog.digital"
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
+
36
40
 
37
- method_option :attach_to_lookup_field, :required => true, :aliases => '-l', :desc => "The field to use to find the :attach_to_klass record"
41
+ method_option :attach_to_field, :required => true, :aliases => '-f', :desc => "Attachment belongs to field e.g Product.image, Blog.digital"
38
42
 
43
+ method_option :attach_to_find_by_field, :required => true, :aliases => '-l', :desc => "The field to use to find the :attach_to_klass record"
44
+
45
+
46
+ # => :attach_to_find_by_field
47
+ # For the :attach_to_klass, this is the field used to search for the parent
48
+ # object to assign the new attachment to.
49
+ # Examples
50
+ # Owner has a unique 'name' field ... :attach_to_find_by_field = :name
51
+ # User has a unique 'login' field ... :attach_to_klass = :login
52
+ #
53
+ # => :attach_to_field
54
+ # Attribute/association to assign attachment to on :attach_to_klass.
55
+ # Examples
56
+ # :attach_to_field => digitals : Owner.digitals = attachment
57
+ # :attach_to_field => avatar : User.avatar = attachment
58
+
39
59
  method_option :split_file_name_on, :type => :string, :desc => "delimiter to progressivley split filename for lookup", :default => ' '
40
60
  method_option :case_sensitive, :type => :boolean, :desc => "Use case sensitive where clause to find :attach_to_klass"
41
61
  method_option :use_like, :type => :boolean, :desc => "Use :lookup_field LIKE 'string%' instead of :lookup_field = 'string' in where clauses to find :attach_to_klass"
data/spec/Gemfile CHANGED
@@ -18,7 +18,8 @@ end
18
18
 
19
19
  # DEFINE WHICH VERSIONS WE WANT TO TEST WITH
20
20
 
21
- gem 'spreadsheet'
22
-
23
21
  gem 'rails', '3.2.8'
24
22
 
23
+ gem 'spreadsheet'
24
+ gem 'paperclip'
25
+
@@ -164,6 +164,34 @@ describe 'Excel Generator' do
164
164
  end
165
165
 
166
166
 
167
+ it "should enable us to remove standard rails feilds from template .xls file ", :fail => true do
168
+
169
+ expect= result_file('project_plus_some_assoc_template_spec.xls')
170
+
171
+ gen = ExcelGenerator.new(expect)
172
+
173
+ options = {:remove_rails => true}
174
+
175
+ gen.generate_with_associations(Project, options)
176
+
177
+ File.exists?(expect).should be_true, "Failed to find expected result file #{expect}"
178
+
179
+ excel = Excel.new
180
+ excel.open(expect)
181
+
182
+ excel.worksheets.should have(1).items
183
+
184
+ excel.worksheet(0).name.should == 'Project'
185
+
186
+ headers = excel.worksheets[0].row(0)
187
+
188
+ ["id", "updated_at", "created_at"].each do |check|
189
+ headers.should_not include check
190
+ end
191
+
192
+
193
+ end
194
+
167
195
  it "should enable us to autosize columns in the .xls file" do
168
196
 
169
197
  expect= result_file('project_autosized_template_spec.xls')
@@ -14,32 +14,27 @@ include DataShift
14
14
 
15
15
  describe 'Excel Loader' do
16
16
 
17
- before(:all) do
17
+ include_context "ActiveRecordTestModelsConnected"
18
18
 
19
- # load our test model definitions - Project etc
20
- require ifixture_file('test_model_defs')
21
-
22
- db_connect( 'test_file' ) # , test_memory, test_mysql
19
+ before(:each) do
20
+ DataShift::MethodDictionary.clear
23
21
 
24
- # handle migration changes or reset of test DB
25
- migrate_up
26
-
27
- db_clear() # todo read up about proper transactional fixtures
28
-
29
- @assoc_klazz = Category
22
+ @method_mapper = DataShift::MethodMapper.new
30
23
  end
31
24
 
25
+
26
+ include_context "ClearAndPopulateProject"
27
+
32
28
  before(:each) do
33
29
 
34
- Project.delete_all
35
-
36
30
  %w{category_001 category_002 category_003 category_004 category_005}.each do |cat|
37
- @assoc_klazz.find_or_create_by_reference(cat)
31
+ Category.find_or_create_by_reference(cat)
38
32
  end
39
33
 
40
- MethodDictionary.clear
41
- MethodDictionary.find_operators( Project )
42
- MethodDictionary.find_operators( @assoc_klazz )
34
+ DataShift::MethodDictionary.find_operators( Category )
35
+
36
+ DataShift::MethodDictionary.build_method_details( Category )
37
+
43
38
  end
44
39
 
45
40
  it "should be able to create a new excel loader and load object" do
@@ -2,7 +2,7 @@
2
2
  # These entires can be used in call to db_connect ( see spec_helper )
3
3
 
4
4
  <% adapter = 'sqlite3' %>
5
- <% adapter = 'jdbcsqlite3' if(Guards::jruby? ) %>
5
+ <% adapter = 'jdbcsqlite3' if(DataShift::Guards::jruby? ) %>
6
6
 
7
7
  test_mysql:
8
8
  adapter: jdbcmysql
@@ -0,0 +1,24 @@
1
+ # Author :: Tom Statter
2
+ # Date :: Oct 2012
3
+ # License:: MIT
4
+ #
5
+ # Details:: Migration for paperclip specs
6
+
7
+ class AddDigitals < ActiveRecord::Migration
8
+
9
+ def self.up
10
+
11
+ create_table :digitals do |t|
12
+ t.integer :owner_id
13
+ t.string :attachment_file_name
14
+ t.string :attachment_content_type
15
+ t.integer :attachment_file_size
16
+ t.timestamps
17
+ end
18
+
19
+ end
20
+
21
+ def self.down
22
+ drop_table :digitals
23
+ end
24
+ end
@@ -0,0 +1,14 @@
1
+ # To change this template, choose Tools | Templates
2
+ # and open the template in the editor.
3
+
4
+ require 'paperclip'
5
+
6
+ class Digital < ActiveRecord::Base
7
+
8
+ include Paperclip::Glue
9
+
10
+ attr_accessible :attachment
11
+
12
+ has_attached_file :attachment, :styles => { :medium => "300x300>", :thumb => "100x100>" }, :path => ":rails_root/private/digitals/:id/:basename.:extension"
13
+
14
+ end
@@ -1,5 +1,7 @@
1
-
2
-
3
1
  class Owner < ActiveRecord::Base
4
- belongs_to :project
2
+
3
+ belongs_to :project, :dependent => :destroy
4
+
5
+ has_many :digitals, :dependent => :destroy
6
+
5
7
  end
@@ -1,67 +1,9 @@
1
- # A set of models and associations we can use in our specs to test
2
- # basic database columns and also relationships
3
1
 
4
- # See Companion migration spec/db/migrate
5
2
 
6
- class Project < ActiveRecord::Base
3
+ # TODO investigate potential gem that might this require_all
7
4
 
8
- has_one :owner
9
-
10
- has_many :milestones
11
-
12
- has_many :loader_releases
13
- has_many :versions, :through => :loader_releases
14
-
15
-
16
- #has_many :release_versions, :through => :loader_releases, :source => :versions
17
-
18
- has_and_belongs_to_many :categories
19
-
20
- attr_accessible :value_as_string, :value_as_boolean, :value_as_double
21
-
22
- def multiply
23
- 10 * value_as_double
24
- end
5
+ base = File.join(File.dirname(__FILE__), 'models')
25
6
 
26
- end
27
-
28
- class Owner < ActiveRecord::Base
29
- belongs_to :project
30
- end
31
-
32
- class Milestone < ActiveRecord::Base
33
- belongs_to :project
34
- #validate the name, cost
35
-
36
- delegate :title, :title=, :to => :project
37
- end
38
-
39
- # had_and_belongs to join table
40
- class Category < ActiveRecord::Base
41
- has_and_belongs_to_many :projects
42
- end
43
-
44
-
45
- class Version < ActiveRecord::Base
46
- has_many :releases
47
-
48
- has_one :long_and_complex_table_linked_to_version
49
- end
50
-
51
- # Join Table with additional columns
52
- class LoaderRelease < ActiveRecord::Base
53
-
54
- belongs_to :project
55
- belongs_to :version
56
-
57
- #validate the name
58
- end
59
-
60
- class Empty < ActiveRecord::Base
61
- end
62
-
63
- # Join Table with additional columns
64
- class LongAndComplexTableLinkedToVersion < ActiveRecord::Base
65
-
66
- belongs_to :version
7
+ Dir[ File.join(base, '*.rb') ].each do |file|
8
+ require File.join(base, File.basename(file, File.extname(file) ))
67
9
  end
data/spec/loader_spec.rb CHANGED
@@ -11,71 +11,66 @@ require 'erb'
11
11
 
12
12
  describe 'Basic Loader' do
13
13
 
14
- before(:all) do
15
-
16
- # load our test model definitions - Project etc
17
- require ifixture_file('test_model_defs')
14
+ include_context "ActiveRecordTestModelsConnected"
18
15
 
19
- db_connect( 'test_file' ) # , test_memory, test_mysql
20
-
21
- migrate_up
22
- @klazz = Project
23
- end
16
+ include_context "ClearAndPopulateProject"
24
17
 
25
- before(:each) do
26
- MethodDictionary.clear
27
- MethodDictionary.find_operators( @klazz )
18
+ before(:each) do
19
+ @loader = DataShift::LoaderBase.new(Project)
28
20
  end
29
21
 
30
22
  it "should be able to create a new loader and load object" do
31
- loader = LoaderBase.new( @klazz )
32
-
33
- loader.load_object.should_not be_nil
34
- loader.load_object.should be_is_a(@klazz)
35
- loader.load_object.new_record?.should be_true
23
+ @loader.load_object.should_not be_nil
24
+ @loader.load_object.should be_is_a(Project)
25
+ @loader.load_object.new_record?.should be_true
36
26
  end
37
27
 
28
+
38
29
  it "should process a string field against an assigment method detail" do
39
30
 
40
- loader = LoaderBase.new(Project)
31
+ column = 'Value As String'
32
+ row = 'Another Lazy fox '
33
+
34
+ @loader.find_and_process(column, row)
35
+
36
+ @loader.load_object.errors.should have_exactly(0).items
37
+ end
38
+
39
+ it "should process a string field against an assigment method detail" do
41
40
 
42
41
  column = 'Value As String'
43
42
  row = 'Another Lazy fox '
44
43
 
45
- loader.find_and_process(column, row)
44
+ @loader.find_and_process(column, row)
46
45
 
47
- loader.load_object.value_as_string.should == row
46
+ @loader.load_object.value_as_string.should == row
48
47
  end
49
48
 
50
49
  it "should process a text field against an assigment method detail" do
51
50
 
52
- loader = LoaderBase.new(Project)
53
-
54
51
  column = :value_as_text
55
52
  row = "Another Lazy fox\nJumped over something and bumped,\nHis head"
56
53
 
57
- loader.find_and_process(column, row)
54
+ @loader.find_and_process(column, row)
58
55
 
59
- loader.load_object.value_as_text.should == row
56
+ @loader.load_object.value_as_text.should == row
60
57
 
61
58
  end
62
59
 
63
60
  it "should process a boolean field against an assigment method detail" do
64
61
 
65
- loader = LoaderBase.new(Project)
66
-
67
62
  column = :value_as_boolean
68
63
  row = true
69
64
 
70
- loader.find_and_process(column, row)
65
+ @loader.find_and_process(column, row)
71
66
 
72
- loader.load_object.value_as_boolean.should == row
67
+ @loader.load_object.value_as_boolean.should == row
73
68
 
74
69
  row = 'false'
75
70
 
76
- loader.find_and_process(column, row)
71
+ @loader.find_and_process(column, row)
77
72
 
78
- loader.load_object.value_as_boolean.should == false
73
+ @loader.load_object.value_as_boolean.should == false
79
74
 
80
75
 
81
76
  end
@@ -84,38 +79,35 @@ describe 'Basic Loader' do
84
79
  end
85
80
 
86
81
  it "should process various date formats against a date assigment operator" do
87
-
88
- loader = LoaderBase.new(Project)
89
-
90
82
  column = :value_as_datetime
91
83
 
92
- loader.find_and_process(column, Time.now)
93
- loader.load_object.value_as_datetime.should_not be_nil
84
+ @loader.find_and_process(column, Time.now)
85
+ @loader.load_object.value_as_datetime.should_not be_nil
94
86
 
95
- loader.find_and_process(column, "2011-07-23")
96
- loader.load_object.value_as_datetime.should_not be_nil
87
+ @loader.find_and_process(column, "2011-07-23")
88
+ @loader.load_object.value_as_datetime.should_not be_nil
97
89
 
98
- loader.find_and_process(column, "Sat Jul 23 09:01:56 +0100 2011")
99
- loader.load_object.value_as_datetime.should_not be_nil
90
+ @loader.find_and_process(column, "Sat Jul 23 09:01:56 +0100 2011")
91
+ @loader.load_object.value_as_datetime.should_not be_nil
100
92
 
101
- loader.find_and_process(column, Time.now.to_s(:db))
102
- loader.load_object.value_as_datetime.should_not be_nil
93
+ @loader.find_and_process(column, Time.now.to_s(:db))
94
+ @loader.load_object.value_as_datetime.should_not be_nil
103
95
 
104
- loader.find_and_process(column, "Jul 23 2011 23:02:59")
105
- loader.load_object.value_as_datetime.should_not be_nil
96
+ @loader.find_and_process(column, "Jul 23 2011 23:02:59")
97
+ @loader.load_object.value_as_datetime.should_not be_nil
106
98
 
107
- if(Guards.jruby?)
108
- loader.find_and_process(column, "07/23/2011") # dd/mm/YYYY
109
- loader.load_object.value_as_datetime.should_not be_nil
99
+ if(DataShift::Guards.jruby?)
100
+ @loader.find_and_process(column, "07/23/2011") # dd/mm/YYYY
101
+ @loader.load_object.value_as_datetime.should_not be_nil
110
102
  end
111
103
 
112
104
  # bad casts - TODO - is this really an error needs raising ?
113
- loader.find_and_process(column, "2011 07 23")
114
- loader.load_object.value_as_datetime.should be_nil
105
+ @loader.find_and_process(column, "2011 07 23")
106
+ @loader.load_object.value_as_datetime.should be_nil
115
107
 
116
108
 
117
- loader.find_and_process(column, "2011-23-07")
118
- loader.load_object.value_as_datetime.should be_nil
109
+ @loader.find_and_process(column, "2011-23-07")
110
+ @loader.load_object.value_as_datetime.should be_nil
119
111
 
120
112
  end
121
113
 
@@ -7,19 +7,12 @@
7
7
  # MethodMapper provides the bridge between 'strings' e.g column headings
8
8
  # and a classes different types of assignment operators
9
9
  #
10
- require File.dirname(__FILE__) + '/spec_helper'
10
+ require File.join(File.dirname(__FILE__), 'spec_helper')
11
11
 
12
- describe 'Method Mapping' do
12
+ describe 'Method Dictionary' do
13
13
 
14
- before(:all) do
15
-
16
- # load our test model definitions - Project etc
17
- require ifixture_file('test_model_defs')
14
+ include_context "ActiveRecordTestModelsConnected"
18
15
 
19
- db_connect( 'test_file' ) # , test_memory, test_mysql
20
-
21
- migrate_up
22
- end
23
16
 
24
17
  before(:each) do
25
18
  MethodDictionary.clear