garden 0.0.15.pre → 0.0.16.pre

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,32 @@
1
+ A utility for using different seed formats in your ActiveRecord database.
2
+
3
+ In process. Currently supports:
4
+
5
+ Excel spreadsheet format:
6
+
7
+ Garden.excel 'spreadsheetname'
8
+
9
+ CSV spreadsheet format:
10
+
11
+ Garden.csv 'spreadsheetname'
12
+
13
+ Common options:
14
+
15
+ :reference >> The column name to use as a reference for updating values.
16
+
17
+ :validate >> [Boolean][default=true] >> Whether to perform validations on ActiveRecord::Base instances
18
+
19
+ :only >> (Excel only) whitelist the worksheet names to seed
20
+ :worksheet >> (Excel only) whitelist the single worksheet name to seed
21
+
22
+ :table >> (CSV only) the table name to seed into (defaults to an interpretation based on the csv filename)
23
+
24
+ Callbacks:
25
+ Callbacks allow for methods and actions to be injected in the process of the seeding of data. The most common callbacks are those
26
+ that will be called on each instance that is created by the seed process.
27
+
28
+ :before_validation
29
+ If option is a method or Proc instance, it will be called with the record as the first argument.
30
+ If option is a symbol, Garden expects it refers to the name of a method for that instance and will call it on the record.
31
+
32
+
@@ -6,6 +6,7 @@ module Garden
6
6
  autoload :Spreadsheets
7
7
  autoload :Mediators
8
8
  autoload :Helpers
9
+ autoload :Models
9
10
  autoload :Instance
10
11
 
11
12
  # def self.plant
@@ -47,8 +47,9 @@ module Garden
47
47
  include Columns
48
48
 
49
49
  def initialize(clazz, attributes=nil, options={})
50
- @options = options.dup
51
-
50
+ @options = options.dup.symbolize_keys
51
+ # initialize_callbacks
52
+
52
53
  if @options.has_key? :reference
53
54
  @reference_column = @options.delete(:reference).to_sym
54
55
  @reference = attributes.delete @reference_column
@@ -65,6 +66,17 @@ module Garden
65
66
  assign_attributes attributes if attributes
66
67
  end
67
68
 
69
+ # def initialize_callbacks
70
+ # for name in active_record_callbacks do
71
+ #
72
+ #
73
+ #
74
+ # end
75
+ #
76
+ # @callbacks = {}
77
+ # @callbacks[:before_validation] = @options.delete(:before_validation) if @options.has_key?(:before_validation)
78
+ # end
79
+
68
80
  def assign_attributes(attributes)
69
81
 
70
82
  attributes.each do |key, value|
@@ -72,16 +84,16 @@ module Garden
72
84
  map_attribute key, value
73
85
  end
74
86
 
75
- if @object.valid?
76
- @object.save!
77
-
87
+ # execute_callback(:before_validation)
88
+
89
+ if @object.save(:validate => @options[:validate])
78
90
  if @reference.nil?
79
91
  puts ". Saved new instance: #{@clazz} #{@object.to_param}"
80
92
  else
81
93
  puts ". Saved existing instance: #{@clazz} #{@object.to_param}"
82
94
  end
83
95
  else
84
- puts "! Invalid instance: #{@object.to_param}"
96
+ puts "! Instance was not saved: #{@object.to_param}"
85
97
  # puts "#{@name}:"
86
98
  # puts " - Valid attributes: #{attributes.keys}"
87
99
  # puts " - Excel sheet keys: #{all_keys}"
@@ -91,7 +103,9 @@ module Garden
91
103
  # @object.errors.each do |error|
92
104
  # puts "Error => #{error}: #{@object.errors.get error}"
93
105
  # end
94
- puts @object.errors.to_a
106
+ if @object.errors.any?
107
+ puts @object.errors.to_a
108
+ end
95
109
  puts "."
96
110
  end
97
111
 
@@ -152,7 +166,7 @@ module Garden
152
166
  # build the association if it hasn't already been built.
153
167
  @object.send("build_#{assoc}".to_sym)
154
168
  end
155
- eval "@object.#{key} = '#{value.gsub(/[']/, '\\\\\'')}'"
169
+ eval "@object.#{key} = '#{value.to_s.gsub(/[']/, '\\\\\'')}'"
156
170
  return
157
171
  end
158
172
 
@@ -195,6 +209,34 @@ module Garden
195
209
 
196
210
  end
197
211
 
212
+ # def execute_callback name
213
+ # name = name.to_sym
214
+ # callback = @callbacks[name]
215
+ #
216
+ # if callback
217
+ #
218
+ # if active_record_callbacks.include?(name)
219
+ # # Execute a callback by applying it to the ActiveRecord model.
220
+ #
221
+ # else
222
+ #
223
+ # end
224
+ #
225
+ # # puts "Executing callback: #{name}, #{callback}, #{callback.class}"
226
+ # case callback
227
+ # when Proc, Method then callback.call(@object)
228
+ # when Symbol, String then record.send(callback.to_sym)
229
+ # end
230
+ # end
231
+ # end
232
+ #
233
+ # private
234
+
235
+ # def _execute_active_record_callback name, callback
236
+ #
237
+ # end
238
+
239
+
198
240
  end
199
241
 
200
242
  Instance.send :include, Helpers::RealInstance
@@ -2,72 +2,35 @@ module Garden
2
2
  module Mediators
3
3
  class Table
4
4
 
5
- # def self.parse_table_name namish
6
- # namish.parameterize.underscore
7
- # end
8
-
9
- def self.find_model_class namish
10
- clazz = nil
11
- namish = namish.singularize
5
+ def initialize namish, options={}
6
+ @instance_options = options.reverse_merge!({:validate => true})
12
7
 
13
- begin
14
- # try the format as it should be. Camelcase, and with :: or / for modules
15
- # Module::Classname
16
- clazz = namish.underscore.classify.constantize
17
- rescue
18
- begin
19
- # try the format "Class Name" by turning spaced words into camelcase
20
- clazz = namish.parameterize.underscore.classify.constantize
21
- rescue
22
- begin
23
- # try the format "Class Name" by turning spaced words into module separators
24
- clazz = namish.gsub(/ /, "/").underscore.classify.constantize
25
- rescue
26
- puts "Nope"
27
- end
28
- end
29
- end
30
- clazz
31
- end
32
-
33
- def initialize namish
34
- @instance_options ||= {}
8
+ # puts "Instance options: #{@instance_options}"
35
9
 
36
- @clazz = Table.find_model_class namish
10
+ @clazz = Models.find namish, @instance_options
37
11
 
38
12
  if @clazz.nil? || !@clazz.new.is_a?(ActiveRecord::Base)
39
13
  puts "!! Class '#{namish}' could not be parsed to an ActiveRecord subclass."
40
14
  end
41
15
 
42
- # Get the ActiveRecord model from the tablename.
43
- # begin
44
- # @clazz = @name.classify.constantize
45
- # raise "Class #{@clazz.to_s} is not an ActiveRecord subclass." unless @clazz.new.is_a?(ActiveRecord::Base)
46
- # rescue Exception => e
47
- # puts " ** Could not derive ActiveRecord model from the provided name: #{namish}. Exception: #{e.message}"
48
- # end
49
-
50
- # @instance = @clazz.new
51
-
52
16
  end
53
17
 
54
18
  def valid?
55
19
  @clazz != nil
56
20
  end
57
-
58
- # def parse_headers array
59
- # # @headers = array.map { |header| header.to_s.parameterize.underscore }
60
- # @headers = array.map { |header| header.to_s.strip.gsub(/ /, '-').underscore }
61
- # end
62
21
 
63
22
  def reference_by col_name
64
23
  @instance_options[:reference] = col_name
65
24
  end
66
25
 
67
- # def relationships
68
- # @relationships
69
- # end
70
- #
26
+ def validate=(val)
27
+ @instance_options[:validate] = val
28
+ end
29
+
30
+ def validate
31
+ @instance_options[:validate]
32
+ end
33
+
71
34
  def row attributes
72
35
  Instance.new @clazz, attributes, @instance_options.dup
73
36
  end
@@ -79,7 +42,7 @@ module Garden
79
42
  false
80
43
  end
81
44
  end
82
-
45
+
83
46
  end
84
47
  end
85
48
  end
@@ -0,0 +1,77 @@
1
+ module Garden
2
+ class Models
3
+
4
+ CALLBACKS = ActiveRecord::Callbacks::CALLBACKS
5
+
6
+
7
+ def self.find namish, options={}
8
+
9
+ # We return the found class if we've already found it.
10
+ @@found ||= {}
11
+ return @@found[namish.to_s] if @@found.has_key?(namish.to_s)
12
+
13
+ clazz = nil
14
+ namish = namish.singularize
15
+
16
+ begin
17
+ # try the format as it should be. Camelcase, and with :: or / for modules
18
+ # Module::Classname
19
+ clazz = namish.underscore.classify.constantize
20
+ rescue
21
+ begin
22
+ # try the format "Class Name" by turning spaced words into camelcase
23
+ clazz = namish.parameterize.underscore.classify.constantize
24
+ rescue
25
+ begin
26
+ # try the format "Class Name" by turning spaced words into module separators
27
+ clazz = namish.gsub(/ /, "/").underscore.classify.constantize
28
+ rescue
29
+ puts "Nope"
30
+ end
31
+ end
32
+ end
33
+
34
+ if clazz
35
+ apply_callbacks clazz, options
36
+ @@found[namish.to_s] = clazz
37
+ end
38
+ clazz
39
+
40
+ end
41
+
42
+ def self.apply_callbacks clazz, callbacks
43
+ @@created_callbacks ||= []
44
+
45
+ for name in CALLBACKS do
46
+ if callbacks.has_key?(name)
47
+ callback = callbacks[name]
48
+
49
+ # Will add a callback to the ActiveRecord model
50
+ clazz.send name, Proc.new{ |record| Garden::Models.execute_callback(record, callback) }
51
+
52
+ # Retain a reference to the created callback so we can remove it later
53
+ key = name.to_s.gsub(/^(before|after|around)_/, '')
54
+ list_name = "_#{key}_callbacks"
55
+ callback_name = clazz.send(list_name).last.filter
56
+
57
+ @@created_callbacks << { :class => clazz, :list => list_name, :callback => callback_name }
58
+ end
59
+ end
60
+
61
+ end
62
+
63
+ def self.execute_callback record, callback
64
+ # puts "Executing callback on #{record.inspect}, #{callback}"
65
+
66
+ case callback
67
+ when Proc then callback.call(record)
68
+ when Symbol, String then record.send(callback.to_sym)
69
+ end
70
+
71
+ end
72
+
73
+
74
+
75
+ end
76
+ end
77
+
@@ -7,7 +7,8 @@ module Garden
7
7
  class AbstractSpreadsheet
8
8
  def initialize filepath, options={}
9
9
  options ||= {}
10
- @options = options.reverse_merge! :some_option => "nevermind"
10
+ # @options = options.reverse_merge! {}
11
+ @options = options
11
12
  open filepath
12
13
  end
13
14
 
@@ -15,7 +16,12 @@ module Garden
15
16
  end
16
17
 
17
18
  def build_mediator name
18
- @mediator = Mediators::Table.new name
19
+ validation = @options[:validate]
20
+ validation = true if validation.nil?
21
+
22
+ @options[:validate] = true if @options[:validate].nil?
23
+
24
+ @mediator = Mediators::Table.new name, @options#:validate => validation
19
25
  raise "Invalid mediator for table #{name}" unless @mediator.valid?
20
26
  @mediator.reference_by(@options[:reference]) if @options.has_key?(:reference)
21
27
  @mediator
@@ -33,7 +39,7 @@ module Garden
33
39
 
34
40
  excel_spreadsheet = ::Spreadsheet.open filepath
35
41
 
36
- worksheet_names = @options[:only] || @options[:worksheet] || excel_spreadsheet.worksheets.collect { |table| table.name }
42
+ worksheet_names = @options.delete(:only) || @options.delete(:worksheet) || excel_spreadsheet.worksheets.collect { |table| table.name }
37
43
  worksheet_names = [worksheet_names] unless worksheet_names.is_a?(Enumerable)
38
44
 
39
45
  # Import the worksheets
@@ -50,12 +56,12 @@ module Garden
50
56
  # Expects the first row to be the headers.
51
57
  headers = rows.shift.map { |header| header.to_s.strip.gsub(/ /, '-').underscore }
52
58
  rows.each do |row|
53
- attributes = parse_worksheet_row(headers, row)
59
+ attributes = parse_worksheet_attributes(headers, row)
54
60
  @mediator.row attributes
55
61
  end
56
62
  end
57
63
 
58
- def parse_worksheet_row keys, values
64
+ def parse_worksheet_attributes keys, values
59
65
  h = {}
60
66
  keys.each_index do |index|
61
67
  key = keys[index].to_sym
@@ -1,3 +1,3 @@
1
1
  module Garden
2
- VERSION = "0.0.15.pre"
2
+ VERSION = "0.0.16.pre"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: garden
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.15.pre
4
+ version: 0.0.16.pre
5
5
  prerelease: 7
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-11-14 00:00:00.000000000Z
12
+ date: 2011-12-16 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: spreadsheet
16
- requirement: &70211128028900 !ruby/object:Gem::Requirement
16
+ requirement: &70188181388160 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,7 +21,7 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70211128028900
24
+ version_requirements: *70188181388160
25
25
  description: ! 'Allows you to organize your seeds in different formats. Typical seeds.rb,
26
26
  yaml fixtures, and a variety of spreadsheet formats. '
27
27
  email:
@@ -32,7 +32,7 @@ extra_rdoc_files: []
32
32
  files:
33
33
  - .gitignore
34
34
  - Gemfile
35
- - README.markdown
35
+ - README.textile
36
36
  - Rakefile
37
37
  - garden.gemspec
38
38
  - lib/garden.rb
@@ -40,6 +40,7 @@ files:
40
40
  - lib/garden/helpers/real_instance.rb
41
41
  - lib/garden/instance.rb
42
42
  - lib/garden/mediators.rb
43
+ - lib/garden/models.rb
43
44
  - lib/garden/spreadsheets.rb
44
45
  - lib/garden/version.rb
45
46
  homepage: ''
@@ -1,5 +0,0 @@
1
- A utility for using different seed formats in your ActiveRecord database.
2
-
3
- In process. Currently supports Excel spreadsheet format.
4
-
5
- Garden.excel 'spreadsheetname'