planter 0.0.8 → 0.0.12

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cefea9dd4547f81df2480f10a92ed64738475a21db8237dac4599a060a80cf19
4
- data.tar.gz: 660ecdca12dc88752d353a39e0a6fc0bef2582b7203628002e23f6d246d49589
3
+ metadata.gz: 37c19399e25198fe0545690d5b5568c5bd91b4736258af3d8664c36abe882889
4
+ data.tar.gz: a399b54a606d7c0e98d49f0bad5abff1fc4726d96eab3573c82d1dc649b83b1e
5
5
  SHA512:
6
- metadata.gz: 486bf0a34ac192c6c1295a1b628d25b5e685a83d92700f99291ef35e2ea58b30f5db976057ae87e03a76d48ee29bceacfcde5e5d1018488976f2304f079aafd1
7
- data.tar.gz: 3ab0665aa4c97a0a7f405bc93604256a90c2c7e88745d5ded6f908fc17f914fb76cc883f69c5a709fd5210902bc5039f80a294cc26548a8eead99695a1dda529
6
+ metadata.gz: 6275a47f463227b86374e327781edd92bbd9cdf9399bafa68c6c4cb3316ae812cf081509a26e81e04101f9cd4af43396f2c008477741f00f475ea09436353ba8
7
+ data.tar.gz: 1a5a27d9253b78ae0c1c0526c1f8dcb977a428ec5c62cb4239f5542413e1f5020c68d8ee0d356ded4c1f3094c7f449f03fefb72180250388de81f8c44c2c6a63
data/README.md CHANGED
@@ -19,10 +19,12 @@ Features include:
19
19
  You can view the documentation [here](https://evanthegrayt.github.io/planter/).
20
20
 
21
21
  ## Installation
22
- Add this line to your application's Gemfile:
22
+ Add the following line to your application's Gemfile. Because this plugin is
23
+ currently a pre-release version, it's recommended to lock it to a specific
24
+ version, as breaking changes may occur, even at the patch level.
23
25
 
24
26
  ```ruby
25
- gem 'planter'
27
+ gem 'planter', '0.0.10'
26
28
  ```
27
29
 
28
30
  And then execute:
@@ -50,8 +52,8 @@ Planter.configure do |config|
50
52
  ##
51
53
  # The list of seeders. These files are stored in the
52
54
  # config.seeders_directory, which can be changed below. When a new
53
- # seeeder is generated, it will be appended to the bottom of this
54
- # list. If the order is incorrect, you'll need to adjust the it.
55
+ # seeder is generated, it will be appended to the bottom of this
56
+ # list. If the order is incorrect, you'll need to adjust it.
55
57
  # Just be sure to keep the ending bracket on its own line, or the
56
58
  # generator won't know where to put new elements.
57
59
  config.seeders = %i[
@@ -64,6 +66,10 @@ Planter.configure do |config|
64
66
  ##
65
67
  # The directory where CSVs are kept.
66
68
  # config.csv_files_directory = 'db/seed_files'
69
+
70
+ ##
71
+ # The default trim mode for ERB.
72
+ # config.erb_trim_mode = nil
67
73
  end
68
74
  ```
69
75
 
@@ -133,18 +139,37 @@ class UsersSeeder < Planter::Seeder
133
139
  end
134
140
  ```
135
141
 
136
- `ERB` can be used in the CSV files if you name it with `.erb` at the end of the
137
- file name. For example, `users.csv.erb`. Note that lines starting with `<%` and
138
- ending with `%>` will not be considered rows, so you can use `ERB` rows to set
139
- values. For example:
142
+ `ERB` can be used in the CSV files if you end the file name with `.csv.erb`.
143
+ For example, `users.csv.erb`.
144
+
145
+ ```
146
+ participant_id,name
147
+ <%= Participant.find_by(email: 'test1@example.com').id %>,"Test User1"
148
+ <%= Participant.find_by(email: 'test2@example.com').id %>,"Test User2"
149
+ ```
150
+
151
+ Note that, if you need to change the trim mode for ERB, you can set a default in
152
+ the initializer.
153
+
154
+ ```ruby
155
+ Planter.configure do |config|
156
+ config.seeders = %i[
157
+ users
158
+ ]
159
+ config.erb_trim_mode = '<>'
160
+ end
161
+ ```
162
+
163
+ ...or, for individual seeders, via `seeding_method`.
140
164
 
141
- ```csv.erb
142
- email,login_attempts
143
- <% count = 1 %>
144
- test2@example.com,<%= count += 1 %>
145
- test2@example.com,<%= count += 1 %>
165
+ ```ruby
166
+ class UsersSeeder < Planter::Seeder
167
+ seeding_method :csv, erb_trim_mode: '<>'
168
+ end
146
169
  ```
147
170
 
171
+ For help with `erb_trim_mode`, see the help documentation for `ERB::new`.
172
+
148
173
  Running `rails planter:seed` will now seed your `users` table.
149
174
 
150
175
  ## Seeding from a data array
@@ -11,8 +11,8 @@ module Planter
11
11
  ##
12
12
  # The list of seeders. These files are stored in the
13
13
  # config.seeders_directory, which can be changed below. When a new
14
- # seeeder is generated, it will be appended to the bottom of this
15
- # list. If the order is incorrect, you'll need to adjust the it.
14
+ # seeder is generated, it will be appended to the bottom of this
15
+ # list. If the order is incorrect, you'll need to adjust it.
16
16
  # Just be sure to keep the ending bracket on its own line, or the
17
17
  # generator won't know where to put new elements.
18
18
  config.seeders = %i[
@@ -25,6 +25,10 @@ module Planter
25
25
  ##
26
26
  # The directory where CSVs are kept.
27
27
  # config.csv_files_directory = 'db/seed_files'
28
+
29
+ ##
30
+ # The default trim mode for ERB.
31
+ # config.erb_trim_mode = nil
28
32
  end
29
33
  EOF
30
34
  end
@@ -42,6 +42,15 @@ module Planter
42
42
  # @return [Boolean]
43
43
  attr_accessor :quiet
44
44
 
45
+ ##
46
+ # The default trim mode for ERB. Must be "%", "<>", ">", or "-".
47
+ # For more information, see documentation for +ERB::new+.
48
+ #
49
+ # @param [String] erb_trim_mode
50
+ #
51
+ # @return [String]
52
+ attr_accessor :erb_trim_mode
53
+
45
54
  ##
46
55
  # Create a new instance of the config.
47
56
  def initialize
@@ -65,6 +65,23 @@ module Planter
65
65
  # end
66
66
  # end
67
67
  #
68
+ # By default, all fields are used to look up the record. If it already
69
+ # exists, it is not re-created. If you have specific fields that a record
70
+ # should be looked-up by, you can pass the +unique_columns+ option. This will
71
+ # attempt to look up the record by those fields only, and if one doesn't
72
+ # exist, one will be created with the rest of the attributes. An example of
73
+ # when this would be useful is with Devise; you can't pass +password+ in the
74
+ # create method, so specifying +unique_columns+ on everything except
75
+ # +password+ allows it to be passed as an attribute to the +first_or_create+
76
+ # call.
77
+ # require 'planter'
78
+ # class UsersSeeder < Planter::Seeder
79
+ # seeding_method :data_array, unique_columns: %i[username email]
80
+ # def data
81
+ # [{username: 'foo', email: 'bar', password: 'Example'}]
82
+ # end
83
+ # end
84
+ #
68
85
  # If you need to seed a different way, put your own custom +seed+ method in
69
86
  # your seeder class and do whatever needs to be done.
70
87
  class Seeder
@@ -101,6 +118,10 @@ module Planter
101
118
  #
102
119
  # @kwarg [Symbol, String] csv_name
103
120
  #
121
+ # @kwarg [Symbol, String] unique_columns
122
+ #
123
+ # @kwarg [String] erb_trim_mode
124
+ #
104
125
  # @example
105
126
  # require 'planter'
106
127
  # class UsersSeeder < Planter::Seeder
@@ -109,15 +130,19 @@ module Planter
109
130
  # model: 'User'
110
131
  # parent_model: 'Person',
111
132
  # association: :users,
112
- # csv_name: :awesome_users
133
+ # csv_name: :awesome_users,
134
+ # unique_columns %i[username email],
135
+ # erb_trim_mode: '<>'
113
136
  # end
114
137
  def self.seeding_method(
115
138
  method,
116
139
  number_of_records: 1,
117
- model: to_s.delete_suffix('Seeder').singularize,
140
+ model: nil,
118
141
  parent_model: nil,
119
142
  association: nil,
120
- csv_name: nil
143
+ csv_name: nil,
144
+ unique_columns: nil,
145
+ erb_trim_mode: nil
121
146
  )
122
147
  if !SEEDING_METHODS.include?(method.intern)
123
148
  raise ArgumentError, "Method must be one of #{SEEDING_METHODS.join(', ')}"
@@ -127,10 +152,16 @@ module Planter
127
152
 
128
153
  @seeding_method = method
129
154
  @number_of_records = number_of_records
130
- @model = model
155
+ @model = model || to_s.delete_suffix('Seeder').singularize
131
156
  @parent_model = parent_model
132
157
  @association = @parent_model && (association || determine_association)
133
158
  @csv_file = determine_csv_filename(csv_name) if @seeding_method == :csv
159
+ @erb_trim_mode = erb_trim_mode || Planter.config.erb_trim_mode
160
+ @unique_columns =
161
+ case unique_columns
162
+ when String, Symbol then [unique_columns.intern]
163
+ when Array then unique_columns.map(&:intern)
164
+ end
134
165
  end
135
166
 
136
167
  def self.determine_association # :nodoc:
@@ -152,7 +183,7 @@ module Planter
152
183
  ).to_s + '.csv'
153
184
  [file, "#{file}.erb"].each do |f|
154
185
  fname = Rails.root.join(Planter.config.csv_files_directory, f).to_s
155
- return fname if File.file?(fname)
186
+ return fname if ::File.file?(fname)
156
187
  end
157
188
 
158
189
  raise ArgumentError, "Couldn't find csv for #{@model}"
@@ -225,14 +256,31 @@ module Planter
225
256
  @csv_file ||= self.class.instance_variable_get('@csv_file')
226
257
  end
227
258
 
259
+ ##
260
+ # When creating a record, the fields that will be used to look up the
261
+ # record. If it already exists, a new one will not be created.
262
+ #
263
+ # @return [Array]
264
+ def unique_columns
265
+ @unique_columns ||= self.class.instance_variable_get('@unique_columns')
266
+ end
267
+
268
+ ##
269
+ # What trim mode should ERB use?
270
+ #
271
+ # @return [String]
272
+ def erb_trim_mode
273
+ @erb_trim_mode ||= self.class.instance_variable_get('@erb_trim_mode')
274
+ end
275
+
228
276
  ##
229
277
  # Creates records from the +data+ attribute.
230
278
  def create_records
231
279
  data.each do |rec|
232
280
  number_of_records.times do
233
- model.constantize.where(
234
- rec.transform_values { |value| value == 'NULL' ? nil : value }
235
- ).first_or_create!
281
+ rec.transform_values { |value| value == 'NULL' ? nil : value }
282
+ unique, attrs = split_record(rec)
283
+ model.constantize.where(unique).first_or_create!(attrs)
236
284
  end
237
285
  end
238
286
  end
@@ -250,34 +298,47 @@ module Planter
250
298
 
251
299
  private
252
300
 
253
- def create_method
301
+ def create_method # :nodoc:
254
302
  parent_model.constantize.reflect_on_association(
255
303
  association
256
304
  ).macro.to_s.include?('many') ? :create_has_many : :create_has_one
257
305
  end
258
306
 
259
- def create_has_many(assoc_rec, association, rec)
260
- assoc_rec.public_send(association).where(rec).first_or_create!
307
+ def create_has_many(assoc_rec, association, rec) # :nodoc:
308
+ unique, attrs = split_record(rec)
309
+ assoc_rec.public_send(association).where(unique).first_or_create!(attrs)
261
310
  end
262
311
 
263
- def create_has_one(assoc_rec, association, rec)
264
- assoc_rec.public_send("create_#{association}", rec)
312
+ def create_has_one(assoc_rec, association, rec) # :nodoc:
313
+ if assoc_rec.public_send(association)
314
+ assoc_rec.public_send(association).update_attributes(rec)
315
+ else
316
+ assoc_rec.public_send("create_#{association}", rec)
317
+ end
265
318
  end
266
319
 
267
320
  def validate_attributes # :nodoc:
268
321
  case seeding_method.intern
269
322
  when :csv
270
- contents = File.read(csv_file)
323
+ contents = ::File.read(csv_file)
271
324
  if csv_file.end_with?('.erb')
272
- contents = ERB.new(contents, trim_mode: '<>').result(binding)
325
+ contents = ERB.new(contents, trim_mode: erb_trim_mode).result(binding)
273
326
  end
274
327
 
275
- @data ||= ::CSV.parse(contents, headers: true).map(&:to_hash)
328
+ @data ||= ::CSV.parse(
329
+ contents, headers: true, header_converters: :symbol
330
+ ).map(&:to_hash)
276
331
  when :data_array
277
332
  raise "Must define '@data'" if public_send(:data).nil?
278
333
  else
279
334
  raise("Must set 'seeding_method'")
280
335
  end
281
336
  end
337
+
338
+ def split_record(rec) # :nodoc:
339
+ return [rec, {}] unless unique_columns
340
+ u = unique_columns.each_with_object({}) { |c, h| h[c] = rec.delete(c) }
341
+ [u, rec]
342
+ end
282
343
  end
283
344
  end
@@ -21,7 +21,7 @@ module Planter
21
21
  # Patch version.
22
22
  #
23
23
  # @return [Integer]
24
- PATCH = 8
24
+ PATCH = 12
25
25
 
26
26
  ##
27
27
  # Version as +[MAJOR, MINOR, PATCH]+
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: planter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.8
4
+ version: 0.0.12
5
5
  platform: ruby
6
6
  authors:
7
7
  - Evan Gray
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-05-26 00:00:00.000000000 Z
11
+ date: 2021-11-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -72,7 +72,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
72
72
  - !ruby/object:Gem::Version
73
73
  version: '0'
74
74
  requirements: []
75
- rubygems_version: 3.2.3
75
+ rubygems_version: 3.2.22
76
76
  signing_key:
77
77
  specification_version: 4
78
78
  summary: Framework for seeding rails applications.