planter 0.0.10 → 0.0.14
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 +4 -4
- data/README.md +38 -10
- data/lib/generators/planter/initializer_generator.rb +10 -1
- data/lib/generators/planter/seeder_generator.rb +1 -1
- data/lib/planter/config.rb +9 -0
- data/lib/planter/seeder.rb +131 -146
- data/lib/planter/version.rb +1 -1
- data/lib/planter.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 65eb2897cfca2aa456d13a8044d6a86ed9b898aced01a3718e4d11f5dc718da1
|
4
|
+
data.tar.gz: 2dec806f05018f1bdf1e81282047dba3f049274cf6397aeaa8db55ff7bf8856c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 752f29be613b3ce52fad80262ec500db79176329ac802c44f582375be3304c2435653fea1698ac1475f7da938250833f6807fa4b98f558806594db331024dc21
|
7
|
+
data.tar.gz: 46c6632d2faed5ab3ee96a4084de5043dd4312048cd1299dbb45910b537e0f5376b087f80e0e97f5ebc041334876cf47f048bbc8df97e6b052489e5c4bccd8d4
|
data/README.md
CHANGED
@@ -60,12 +60,21 @@ Planter.configure do |config|
|
|
60
60
|
]
|
61
61
|
|
62
62
|
##
|
63
|
-
# The directory where the
|
63
|
+
# The directory where the seeders are kept.
|
64
64
|
# config.seeders_directory = 'db/seeds'
|
65
65
|
|
66
66
|
##
|
67
67
|
# The directory where CSVs are kept.
|
68
68
|
# config.csv_files_directory = 'db/seed_files'
|
69
|
+
|
70
|
+
##
|
71
|
+
# The default trim mode for ERB. Valid modes are:
|
72
|
+
# '%' enables Ruby code processing for lines beginning with %
|
73
|
+
# '<>' omit newline for lines starting with <% and ending in %>
|
74
|
+
# '>' omit newline for lines ending in %>
|
75
|
+
# '-' omit blank lines ending in -%>
|
76
|
+
# I recommend reading the help documentation for ERB::new()
|
77
|
+
# config.erb_trim_mode = nil
|
69
78
|
end
|
70
79
|
```
|
71
80
|
|
@@ -135,18 +144,37 @@ class UsersSeeder < Planter::Seeder
|
|
135
144
|
end
|
136
145
|
```
|
137
146
|
|
138
|
-
`ERB` can be used in the CSV files if you name
|
139
|
-
|
140
|
-
ending with `%>` will not be considered rows, so you can use `ERB` rows to set
|
141
|
-
values. For example:
|
147
|
+
`ERB` can be used in the CSV files if you end the file name with `.csv.erb`.
|
148
|
+
For example, `users.csv.erb`.
|
142
149
|
|
143
150
|
```
|
144
|
-
|
145
|
-
|
146
|
-
test2@example.com
|
147
|
-
test2@example.com,<%= count += 1 %>
|
151
|
+
participant_id,name
|
152
|
+
<%= Participant.find_by(email: 'test1@example.com').id %>,"Test User1"
|
153
|
+
<%= Participant.find_by(email: 'test2@example.com').id %>,"Test User2"
|
148
154
|
```
|
149
155
|
|
156
|
+
Note that, if you need to change the trim mode for ERB, you can set a default in
|
157
|
+
the initializer.
|
158
|
+
|
159
|
+
```ruby
|
160
|
+
Planter.configure do |config|
|
161
|
+
config.seeders = %i[
|
162
|
+
users
|
163
|
+
]
|
164
|
+
config.erb_trim_mode = '<>'
|
165
|
+
end
|
166
|
+
```
|
167
|
+
|
168
|
+
...or, for individual seeders, via `seeding_method`.
|
169
|
+
|
170
|
+
```ruby
|
171
|
+
class UsersSeeder < Planter::Seeder
|
172
|
+
seeding_method :csv, erb_trim_mode: '<>'
|
173
|
+
end
|
174
|
+
```
|
175
|
+
|
176
|
+
For help with `erb_trim_mode`, see the help documentation for `ERB::new`.
|
177
|
+
|
150
178
|
Running `rails planter:seed` will now seed your `users` table.
|
151
179
|
|
152
180
|
## Seeding from a data array
|
@@ -234,4 +262,4 @@ Request.
|
|
234
262
|
I do these projects for fun, and I enjoy knowing that they're helpful to people.
|
235
263
|
Consider starring [the repository](https://github.com/evanthegrayt/planter)
|
236
264
|
if you like it! If you love it, follow me [on
|
237
|
-
|
265
|
+
GitHub](https://github.com/evanthegrayt)!
|
@@ -19,12 +19,21 @@ module Planter
|
|
19
19
|
]
|
20
20
|
|
21
21
|
##
|
22
|
-
# The directory where the
|
22
|
+
# The directory where the seeders are kept.
|
23
23
|
# config.seeders_directory = 'db/seeds'
|
24
24
|
|
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. Valid modes are:
|
31
|
+
# '%' enables Ruby code processing for lines beginning with %
|
32
|
+
# '<>' omit newline for lines starting with <% and ending in %>
|
33
|
+
# '>' omit newline for lines ending in %>
|
34
|
+
# '-' omit blank lines ending in -%>
|
35
|
+
# I recommend reading the help documentation for ERB::new()
|
36
|
+
# config.erb_trim_mode = nil
|
28
37
|
end
|
29
38
|
EOF
|
30
39
|
end
|
@@ -3,7 +3,7 @@ module Planter
|
|
3
3
|
class SeederGenerator < Rails::Generators::Base
|
4
4
|
argument :seeder, required: true
|
5
5
|
|
6
|
-
desc "
|
6
|
+
desc "Creates a seeder file at #{::Planter.config.seeders_directory}"
|
7
7
|
|
8
8
|
def generate_seeders
|
9
9
|
seeder == 'ALL' ? tables.each { |t| generate(t) } : generate(seeder)
|
data/lib/planter/config.rb
CHANGED
@@ -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
|
data/lib/planter/seeder.rb
CHANGED
@@ -2,13 +2,13 @@
|
|
2
2
|
|
3
3
|
module Planter
|
4
4
|
##
|
5
|
-
# Class that seeders should inherit from.
|
6
|
-
#
|
7
|
-
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
5
|
+
# Class that seeders should inherit from. Seeders should be in +db/seeds+,
|
6
|
+
# and named +TABLE_seeder.rb+, where +TABLE+ is the name of the table being
|
7
|
+
# seeded (I.E. +users_seeder.rb+). If your seeder is named differently than
|
8
|
+
# the table, you'll need to specify the table with the +model+ option. The
|
9
|
+
# seeder's class name should be the same as the file name, but camelized. So,
|
10
|
+
# +UsersSeeder+. The directory where the seeder files are located can be
|
11
|
+
# changed via an initializer.
|
12
12
|
#
|
13
13
|
# The most basic way to seed is to have a CSV file with the same name as the
|
14
14
|
# table in +db/seed_files/+. So, +users.csv+. This CSV should have the
|
@@ -102,118 +102,24 @@ module Planter
|
|
102
102
|
attr_reader :data
|
103
103
|
|
104
104
|
##
|
105
|
-
#
|
106
|
-
# it which +seeding_method+ to use. The argument to this method must be
|
107
|
-
# included in the +SEEDING_METHODS+ array.
|
105
|
+
# What trim mode should ERB use?
|
108
106
|
#
|
109
|
-
# @
|
110
|
-
|
111
|
-
# @kwarg [Integer] number_of_records
|
112
|
-
#
|
113
|
-
# @kwarg [String] model
|
114
|
-
#
|
115
|
-
# @kwarg [String] parent_model
|
116
|
-
#
|
117
|
-
# @kwarg [Symbol, String] association
|
118
|
-
#
|
119
|
-
# @kwarg [Symbol, String] csv_name
|
120
|
-
#
|
121
|
-
# @kwarg [Symbol, String] unique_columns
|
122
|
-
#
|
123
|
-
# @example
|
124
|
-
# require 'planter'
|
125
|
-
# class UsersSeeder < Planter::Seeder
|
126
|
-
# seeding_method :csv,
|
127
|
-
# number_of_records: 2,
|
128
|
-
# model: 'User'
|
129
|
-
# parent_model: 'Person',
|
130
|
-
# association: :users,
|
131
|
-
# csv_name: :awesome_users,
|
132
|
-
# unique_columns %i[username email]
|
133
|
-
# end
|
134
|
-
def self.seeding_method(
|
135
|
-
method,
|
136
|
-
number_of_records: 1,
|
137
|
-
model: to_s.delete_suffix('Seeder').singularize,
|
138
|
-
parent_model: nil,
|
139
|
-
association: nil,
|
140
|
-
csv_name: nil,
|
141
|
-
erb_trim_mode: nil,
|
142
|
-
unique_columns: nil
|
143
|
-
)
|
144
|
-
if !SEEDING_METHODS.include?(method.intern)
|
145
|
-
raise ArgumentError, "Method must be one of #{SEEDING_METHODS.join(', ')}"
|
146
|
-
elsif association && !parent_model
|
147
|
-
raise ArgumentError, "Must specify :parent_model with :association"
|
148
|
-
end
|
149
|
-
|
150
|
-
@seeding_method = method
|
151
|
-
@number_of_records = number_of_records
|
152
|
-
@model = model
|
153
|
-
@parent_model = parent_model
|
154
|
-
@association = @parent_model && (association || determine_association)
|
155
|
-
@csv_file = determine_csv_filename(csv_name) if @seeding_method == :csv
|
156
|
-
@erb_trim_mode = erb_trim_mode
|
157
|
-
@unique_columns =
|
158
|
-
case unique_columns
|
159
|
-
when String, Symbol then [unique_columns.intern]
|
160
|
-
when Array then unique_columns.map(&:intern)
|
161
|
-
end
|
162
|
-
end
|
163
|
-
|
164
|
-
def self.determine_association # :nodoc:
|
165
|
-
associations =
|
166
|
-
@parent_model.constantize.reflect_on_all_associations.map(&:name)
|
167
|
-
table = to_s.delete_suffix('Seeder').underscore.split('/').last
|
168
|
-
|
169
|
-
[table, table.singularize].map(&:intern).each do |t|
|
170
|
-
return t if associations.include?(t)
|
171
|
-
end
|
172
|
-
|
173
|
-
raise ArgumentError, "Couldn't determine association name"
|
174
|
-
end
|
175
|
-
private_class_method :determine_association
|
176
|
-
|
177
|
-
def self.determine_csv_filename(csv_name) # :nodoc:
|
178
|
-
file = (
|
179
|
-
csv_name || "#{to_s.delete_suffix('Seeder').underscore}"
|
180
|
-
).to_s + '.csv'
|
181
|
-
[file, "#{file}.erb"].each do |f|
|
182
|
-
fname = Rails.root.join(Planter.config.csv_files_directory, f).to_s
|
183
|
-
return fname if ::File.file?(fname)
|
184
|
-
end
|
185
|
-
|
186
|
-
raise ArgumentError, "Couldn't find csv for #{@model}"
|
187
|
-
end
|
188
|
-
private_class_method :determine_csv_filename
|
189
|
-
|
190
|
-
##
|
191
|
-
# The default seed method. To use this method, your class must provide a
|
192
|
-
# valid +seeding_method+, and not implement its own +seed+ method.
|
193
|
-
def seed
|
194
|
-
validate_attributes
|
195
|
-
|
196
|
-
parent_model ? create_records_from_parent : create_records
|
197
|
-
end
|
198
|
-
|
199
|
-
protected
|
107
|
+
# @return [String]
|
108
|
+
class_attribute :erb_trim_mode
|
200
109
|
|
201
110
|
##
|
202
|
-
#
|
111
|
+
# When creating a record, the fields that will be used to look up the
|
112
|
+
# record. If it already exists, a new one will not be created.
|
203
113
|
#
|
204
|
-
# @return [
|
205
|
-
|
206
|
-
@seeding_method ||= self.class.instance_variable_get('@seeding_method')
|
207
|
-
end
|
114
|
+
# @return [Array]
|
115
|
+
class_attribute :unique_columns
|
208
116
|
|
209
117
|
##
|
210
118
|
# The model for the table being seeded. If the model name you need is
|
211
119
|
# different, change via +seeding_method+.
|
212
120
|
#
|
213
121
|
# @return [String]
|
214
|
-
|
215
|
-
@model ||= self.class.instance_variable_get('@model')
|
216
|
-
end
|
122
|
+
class_attribute :model
|
217
123
|
|
218
124
|
##
|
219
125
|
# The model of the parent. When provided with +association+, records in the
|
@@ -221,18 +127,7 @@ module Planter
|
|
221
127
|
# class must set this attribute via +seeding_method+.
|
222
128
|
#
|
223
129
|
# @return [String]
|
224
|
-
|
225
|
-
@parent_model ||= self.class.instance_variable_get('@parent_model')
|
226
|
-
end
|
227
|
-
|
228
|
-
##
|
229
|
-
# When using +parent_model+, the association name. Your class can set this
|
230
|
-
# attribute via +seeding_method+.
|
231
|
-
#
|
232
|
-
# @return [Symbol]
|
233
|
-
def association
|
234
|
-
@association ||= self.class.instance_variable_get('@association')
|
235
|
-
end
|
130
|
+
class_attribute :parent_model
|
236
131
|
|
237
132
|
##
|
238
133
|
# The number of records to create from each record in the +data+ array. If
|
@@ -240,36 +135,131 @@ module Planter
|
|
240
135
|
# +seeding_method+.
|
241
136
|
#
|
242
137
|
# @return [Integer]
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
138
|
+
class_attribute :number_of_records
|
139
|
+
|
140
|
+
##
|
141
|
+
# When using +parent_model+, the association name. Your class can set this
|
142
|
+
# attribute via +seeding_method+.
|
143
|
+
#
|
144
|
+
# @return [Symbol]
|
145
|
+
class_attribute :association
|
247
146
|
|
248
147
|
##
|
249
148
|
# The csv file corresponding to the model.
|
250
149
|
#
|
251
150
|
# @return [String]
|
252
|
-
|
253
|
-
@csv_file ||= self.class.instance_variable_get('@csv_file')
|
254
|
-
end
|
151
|
+
class_attribute :csv_file
|
255
152
|
|
256
153
|
##
|
257
|
-
#
|
258
|
-
# record. If it already exists, a new one will not be created.
|
154
|
+
# The seeding method specified.
|
259
155
|
#
|
260
|
-
# @return [
|
261
|
-
|
262
|
-
|
156
|
+
# @return [Symbol]
|
157
|
+
class_attribute :seed_method
|
158
|
+
|
159
|
+
##
|
160
|
+
# Access the metaclass so we can define public and private class methods.
|
161
|
+
class << self
|
162
|
+
##
|
163
|
+
# If your class is going to use the inherited +seed+ method, you must tell
|
164
|
+
# it which +seeding_method+ to use. The argument to this method must be
|
165
|
+
# included in the +SEEDING_METHODS+ array.
|
166
|
+
#
|
167
|
+
# @param [Symbol] seeding_method
|
168
|
+
#
|
169
|
+
# @kwarg [Integer] number_of_records
|
170
|
+
#
|
171
|
+
# @kwarg [String] model
|
172
|
+
#
|
173
|
+
# @kwarg [String] parent_model
|
174
|
+
#
|
175
|
+
# @kwarg [Symbol, String] association
|
176
|
+
#
|
177
|
+
# @kwarg [Symbol, String] csv_name
|
178
|
+
#
|
179
|
+
# @kwarg [Symbol, String] unique_columns
|
180
|
+
#
|
181
|
+
# @kwarg [String] erb_trim_mode
|
182
|
+
#
|
183
|
+
# @example
|
184
|
+
# require 'planter'
|
185
|
+
# class UsersSeeder < Planter::Seeder
|
186
|
+
# seeding_method :csv,
|
187
|
+
# number_of_records: 2,
|
188
|
+
# model: 'User'
|
189
|
+
# parent_model: 'Person',
|
190
|
+
# association: :users,
|
191
|
+
# csv_name: :awesome_users,
|
192
|
+
# unique_columns %i[username email],
|
193
|
+
# erb_trim_mode: '<>'
|
194
|
+
# end
|
195
|
+
def seeding_method(
|
196
|
+
method,
|
197
|
+
number_of_records: 1,
|
198
|
+
model: nil,
|
199
|
+
parent_model: nil,
|
200
|
+
association: nil,
|
201
|
+
csv_name: nil,
|
202
|
+
unique_columns: nil,
|
203
|
+
erb_trim_mode: nil
|
204
|
+
)
|
205
|
+
if !SEEDING_METHODS.include?(method.intern)
|
206
|
+
raise ArgumentError, "Method must be: #{SEEDING_METHODS.join(', ')}"
|
207
|
+
elsif association && !parent_model
|
208
|
+
raise ArgumentError, "Must specify :parent_model with :association"
|
209
|
+
end
|
210
|
+
|
211
|
+
self.seed_method = method
|
212
|
+
self.number_of_records = number_of_records
|
213
|
+
self.model = model || to_s.delete_suffix('Seeder').singularize
|
214
|
+
self.parent_model = parent_model
|
215
|
+
self.association = parent_model && (association || determine_association)
|
216
|
+
self.csv_file = determine_csv_filename(csv_name) if self.seed_method == :csv
|
217
|
+
self.erb_trim_mode = erb_trim_mode || Planter.config.erb_trim_mode
|
218
|
+
self.unique_columns =
|
219
|
+
case unique_columns
|
220
|
+
when String, Symbol then [unique_columns.intern]
|
221
|
+
when Array then unique_columns.map(&:intern)
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
private
|
226
|
+
|
227
|
+
def determine_association # :nodoc:
|
228
|
+
associations =
|
229
|
+
parent_model.constantize.reflect_on_all_associations.map(&:name)
|
230
|
+
table = to_s.delete_suffix('Seeder').underscore.split('/').last
|
231
|
+
|
232
|
+
[table, table.singularize].map(&:intern).each do |t|
|
233
|
+
return t if associations.include?(t)
|
234
|
+
end
|
235
|
+
|
236
|
+
raise ArgumentError, "Couldn't determine association name"
|
237
|
+
end
|
238
|
+
|
239
|
+
def determine_csv_filename(csv_name) # :nodoc:
|
240
|
+
file = (
|
241
|
+
csv_name || "#{to_s.delete_suffix('Seeder').underscore}"
|
242
|
+
).to_s + '.csv'
|
243
|
+
[file, "#{file}.erb"].each do |f|
|
244
|
+
fname = Rails.root.join(Planter.config.csv_files_directory, f).to_s
|
245
|
+
return fname if ::File.file?(fname)
|
246
|
+
end
|
247
|
+
|
248
|
+
raise ArgumentError, "Couldn't find csv for #{model}"
|
249
|
+
end
|
263
250
|
end
|
264
251
|
|
265
252
|
##
|
266
|
-
#
|
267
|
-
#
|
268
|
-
|
269
|
-
|
270
|
-
|
253
|
+
# The default seed method. To use this method, your class must provide a
|
254
|
+
# valid +seeding_method+, and not implement its own +seed+ method.
|
255
|
+
def seed
|
256
|
+
validate_attributes
|
257
|
+
|
258
|
+
parent_model ? create_records_from_parent : create_records
|
271
259
|
end
|
272
260
|
|
261
|
+
protected
|
262
|
+
|
273
263
|
##
|
274
264
|
# Creates records from the +data+ attribute.
|
275
265
|
def create_records
|
@@ -315,7 +305,7 @@ module Planter
|
|
315
305
|
end
|
316
306
|
|
317
307
|
def validate_attributes # :nodoc:
|
318
|
-
case
|
308
|
+
case seed_method.intern
|
319
309
|
when :csv
|
320
310
|
contents = ::File.read(csv_file)
|
321
311
|
if csv_file.end_with?('.erb')
|
@@ -333,13 +323,8 @@ module Planter
|
|
333
323
|
end
|
334
324
|
|
335
325
|
def split_record(rec) # :nodoc:
|
336
|
-
|
337
|
-
|
338
|
-
u[a] = rec.delete(a) if rec.key?(a)
|
339
|
-
end
|
340
|
-
return [u, rec] unless unique_columns
|
341
|
-
|
342
|
-
unique_columns.each { |c, h| h[c] = rec.delete(c) }
|
326
|
+
return [rec, {}] unless unique_columns
|
327
|
+
u = unique_columns.each_with_object({}) { |c, h| h[c] = rec.delete(c) }
|
343
328
|
[u, rec]
|
344
329
|
end
|
345
330
|
end
|
data/lib/planter/version.rb
CHANGED
data/lib/planter.rb
CHANGED
@@ -67,7 +67,7 @@ module Planter
|
|
67
67
|
# Planter.seed
|
68
68
|
def self.seed
|
69
69
|
seeders = ENV['SEEDERS']&.split(',') || config.seeders&.map(&:to_s)
|
70
|
-
raise RuntimeError, 'No seeders specified'
|
70
|
+
raise RuntimeError, 'No seeders specified' if seeders.blank?
|
71
71
|
|
72
72
|
seeders.each do |s|
|
73
73
|
require Rails.root.join(config.seeders_directory, "#{s}_seeder.rb").to_s
|
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.
|
4
|
+
version: 0.0.14
|
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-
|
11
|
+
date: 2021-12-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|