planter 0.0.8 → 0.0.12

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