garden 0.0.15.pre → 0.0.16.pre

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.
@@ -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'