planter 0.0.2
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 +7 -0
- data/LICENSE +20 -0
- data/README.md +201 -0
- data/Rakefile +18 -0
- data/lib/planter.rb +122 -0
- data/lib/planter/config.rb +53 -0
- data/lib/planter/railtie.rb +6 -0
- data/lib/planter/seeder.rb +195 -0
- data/lib/planter/version.rb +7 -0
- data/lib/tasks/planter_tasks.rake +4 -0
- metadata +76 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: fe6195656eb33a7e774e6f5fb37e6f1dbcf6d7be33230c97605f291201d04de0
|
4
|
+
data.tar.gz: 68e04cc88dde75734fd06b69e0fd783f8f1849cb9d7f6e73fd33c18814cb1c61
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: dbcea200bc37aa0d691cc001a918bcafea73a6c37754f83dea3f56867c4cb0773f474d276477c71081c03a5cc83d592b5ff511e745005e3bb17919436943b33a
|
7
|
+
data.tar.gz: 26f4beb0e5613aedbb6308bcad145a5cd39c20f328fbfa6fb7db0f6bb588128c6c031c014ef00a61d519f246e89eea9e14b05d4126a990fca7235349a9615c9f
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2021 Evan Gray
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,201 @@
|
|
1
|
+
# Planter
|
2
|
+
> Pre-release version! Anything is subject to change in the near future!
|
3
|
+
|
4
|
+
Seeds for Rails applications can get complicated fast, and Rails doesn't provide
|
5
|
+
much for assisting with this process. This plugin seeks to rectify that by
|
6
|
+
providing easy ways to seed specific tables by hooking into the existing `rails
|
7
|
+
db:seed` task.
|
8
|
+
|
9
|
+
Features include:
|
10
|
+
|
11
|
+
- Seed tables from CSV files, an array of hashes, or custom methods.
|
12
|
+
- Seed specific tables with `rails db:seed TABLES=users,addresses`.
|
13
|
+
- Control the number of records being created.
|
14
|
+
- Seed associations.
|
15
|
+
|
16
|
+
## Installation
|
17
|
+
Add this line to your application's Gemfile:
|
18
|
+
|
19
|
+
```ruby
|
20
|
+
gem 'planter'
|
21
|
+
```
|
22
|
+
|
23
|
+
And then execute:
|
24
|
+
|
25
|
+
```bash
|
26
|
+
$ bundle
|
27
|
+
```
|
28
|
+
|
29
|
+
Or install it yourself as:
|
30
|
+
|
31
|
+
```bash
|
32
|
+
$ gem install planter
|
33
|
+
```
|
34
|
+
|
35
|
+
## Usage
|
36
|
+
Let's assume you'd like to seed your `users` table.
|
37
|
+
|
38
|
+
To get started, simply add the following to your `db/seeds.rb` file. Note that
|
39
|
+
the `config.tables` should be an array of the tables to seed. They should be in
|
40
|
+
the correct order to successfully seed the tables when considering associations.
|
41
|
+
|
42
|
+
```ruby
|
43
|
+
require 'planter'
|
44
|
+
|
45
|
+
Planter.configure do |config|
|
46
|
+
config.tables = %i[ users ]
|
47
|
+
end
|
48
|
+
|
49
|
+
Planter.seed
|
50
|
+
```
|
51
|
+
|
52
|
+
Then, create a directory called `db/seeds`, and create a file called
|
53
|
+
`db/seeds/users_seeder.rb`. In that file, create the following class. Note the
|
54
|
+
name of the seeder is the name of the table, plus `Seeder`, and it inherits from
|
55
|
+
`Planter::Seeder`.
|
56
|
+
|
57
|
+
```ruby
|
58
|
+
class UsersSeeder < Planter::Seeder
|
59
|
+
end
|
60
|
+
```
|
61
|
+
|
62
|
+
You then need to choose a seeding method, of which there are currently three.
|
63
|
+
|
64
|
+
### Seeding from CSV
|
65
|
+
To seed from CSV, you simply need to add the following to your seeder class.
|
66
|
+
|
67
|
+
```ruby
|
68
|
+
class UsersSeeder < Planter::Seeder
|
69
|
+
seeding_method :standard_csv
|
70
|
+
end
|
71
|
+
```
|
72
|
+
|
73
|
+
Then, create a directory called `db/seed_files`, and create a csv file called
|
74
|
+
`db/seed_files/users.csv`. In this file, the header should be the field names,
|
75
|
+
and the rest of the rows should be the corresponding data.
|
76
|
+
|
77
|
+
```
|
78
|
+
email,username
|
79
|
+
test1@example.com,test1
|
80
|
+
test2@example.com,test2
|
81
|
+
```
|
82
|
+
|
83
|
+
If the CSV files are not located in the project, you can specify a `:csv_file`
|
84
|
+
option. Note that the value must be a full path.
|
85
|
+
|
86
|
+
```ruby
|
87
|
+
class UsersSeeder < Planter::Seeder
|
88
|
+
seeding_method :standard_csv, csv_file: '/home/me/users.csv'
|
89
|
+
end
|
90
|
+
```
|
91
|
+
|
92
|
+
Running `rails db:seed` will now seed your `users` table.
|
93
|
+
|
94
|
+
## Seeding from a data array
|
95
|
+
If you need dynamic seeds, you can add something similar to the following to
|
96
|
+
your seeder class. In this example, we'll use
|
97
|
+
[faker](https://github.com/faker-ruby/faker).
|
98
|
+
|
99
|
+
```ruby
|
100
|
+
require 'faker' # You should really just require this in `db/seeds.rb`.
|
101
|
+
|
102
|
+
class UsersSeeder < Planter::Seeder
|
103
|
+
seeding_method :data_array, number_of_records: 10
|
104
|
+
|
105
|
+
def data
|
106
|
+
[{
|
107
|
+
email: Faker::Internet.email,
|
108
|
+
username: Faker::Name.name
|
109
|
+
}]
|
110
|
+
end
|
111
|
+
end
|
112
|
+
```
|
113
|
+
|
114
|
+
The `number_of_records` option allows you to only create one array element, but
|
115
|
+
create ten records. If you leave this option off, you'll need your array to have
|
116
|
+
ten elements to create ten records. It's also worth noting that setting an
|
117
|
+
instance variable called `@data` from an `initialize` method would also work, as
|
118
|
+
the `Planter::Seeder` parent class automatically provides `attr_reader :data`.
|
119
|
+
|
120
|
+
Running `rails db:seed` should now seed your `users` table.
|
121
|
+
|
122
|
+
You can also seed children records for every existing record of a parent model.
|
123
|
+
For example, to seed an address for every user, you'd need to create an
|
124
|
+
`AddressesSeeder` that uses the `parent_model` option, as seen below.
|
125
|
+
|
126
|
+
```ruby
|
127
|
+
require 'faker'
|
128
|
+
|
129
|
+
class AddressesSeeder < Planter::Seeder
|
130
|
+
seeding_method :data_array, parent_model: 'User'
|
131
|
+
|
132
|
+
def data
|
133
|
+
[{
|
134
|
+
street: Faker::Address.street_address,
|
135
|
+
city: Faker::Address.city,
|
136
|
+
state: Faker::Address.state_abbr,
|
137
|
+
zip: Faker::Address.zip
|
138
|
+
}]
|
139
|
+
end
|
140
|
+
end
|
141
|
+
```
|
142
|
+
|
143
|
+
Note that specifying `number_of_records` in this instance will create that many
|
144
|
+
records *for each record of the parent model*. You can also specify the
|
145
|
+
association if it's different from the table name, using the `assocation:`
|
146
|
+
option. Currently, associations are assumed to be as `has_many`, so the
|
147
|
+
association is plural by default. Any help with making this more heuristically
|
148
|
+
complete would be welcome.
|
149
|
+
|
150
|
+
### Custom seeds
|
151
|
+
To write your own custom seeds, just overload the `seed` method and do whatever
|
152
|
+
you need to do.
|
153
|
+
|
154
|
+
```ruby
|
155
|
+
class UsersSeeder < Planter::Seeder
|
156
|
+
USERS = {
|
157
|
+
'test1@example.com' => { username: 'John Smith' }
|
158
|
+
'test2@example.com' => { username: 'Jane Smith' }
|
159
|
+
}
|
160
|
+
|
161
|
+
def seed
|
162
|
+
USERS.each { |email, attrs| User.where(email).first_or_create!(attrs) }
|
163
|
+
end
|
164
|
+
end
|
165
|
+
```
|
166
|
+
|
167
|
+
## Customization
|
168
|
+
You can change the directories of both the seeder files and the csv files. In
|
169
|
+
your `configure` block in `db/seeds.rb`, you can add the following. Note that,
|
170
|
+
in both instances, the path should be relative to `Rails.root`.
|
171
|
+
|
172
|
+
```ruby
|
173
|
+
require 'planter'
|
174
|
+
|
175
|
+
Planter.configure do |config|
|
176
|
+
config.seeders_directory = 'db/seeder_classes'
|
177
|
+
config.csv_files_directory = 'db/csvs'
|
178
|
+
config.tables = %i[
|
179
|
+
users
|
180
|
+
addresses
|
181
|
+
]
|
182
|
+
end
|
183
|
+
|
184
|
+
Planter.seed
|
185
|
+
```
|
186
|
+
|
187
|
+
## License
|
188
|
+
The gem is available as open source under the terms of the [MIT
|
189
|
+
License](https://opensource.org/licenses/MIT).
|
190
|
+
|
191
|
+
## Reporting Bugs and Requesting Features
|
192
|
+
If you have an idea or find a bug, please [create an
|
193
|
+
issue](https://github.com/evanthegrayt/planter/issues/new). Just make sure
|
194
|
+
the topic doesn't already exist. Better yet, you can always submit a Pull
|
195
|
+
Request.
|
196
|
+
|
197
|
+
## Self-Promotion
|
198
|
+
I do these projects for fun, and I enjoy knowing that they're helpful to people.
|
199
|
+
Consider starring [the repository](https://github.com/evanthegrayt/planter)
|
200
|
+
if you like it! If you love it, follow me [on
|
201
|
+
Github](https://github.com/evanthegrayt)!
|
data/Rakefile
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'bundler/setup'
|
2
|
+
require 'bundler/gem_tasks'
|
3
|
+
require 'rake/testtask'
|
4
|
+
require 'rdoc/task'
|
5
|
+
|
6
|
+
Rake::TestTask.new(:test) do |t|
|
7
|
+
t.libs << 'test'
|
8
|
+
t.pattern = 'test/**/*_test.rb'
|
9
|
+
t.verbose = false
|
10
|
+
end
|
11
|
+
|
12
|
+
RDoc::Task.new do |rdoc|
|
13
|
+
rdoc.main = 'README.md'
|
14
|
+
rdoc.rdoc_dir = 'doc'
|
15
|
+
rdoc.rdoc_files.include('README.md', 'lib/**/*.rb')
|
16
|
+
end
|
17
|
+
|
18
|
+
task default: :test
|
data/lib/planter.rb
ADDED
@@ -0,0 +1,122 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'csv'
|
4
|
+
require 'planter/version'
|
5
|
+
require 'planter/railtie'
|
6
|
+
require 'planter/config'
|
7
|
+
require 'planter/seeder'
|
8
|
+
|
9
|
+
##
|
10
|
+
# Class that seeders should inherit from. Seeder files should be in +db/seeds+,
|
11
|
+
# and named +TABLE_seeder.rb+, where +TABLE+ is the name of the table being
|
12
|
+
# seeded (I.E. +users_seeder.rb+). The seeder's class name should be the same
|
13
|
+
# as the file name, but camelized. So, +UsersSeeder+. The directory where the
|
14
|
+
# seeder files are located can be changed via an initializer.
|
15
|
+
#
|
16
|
+
# The most basic way to seed is to have a CSV file with the same name as the
|
17
|
+
# table in +db/seed_files/+. So, +users.csv+. This CSV should have the table's
|
18
|
+
# column names as header. To seed using this method, your class should look
|
19
|
+
# like the following. Note that +:csv_file+ is not required; it defaults to the
|
20
|
+
# table name with a +csv+ file extension. The directory where the seed files
|
21
|
+
# are kept can be changed via an initializer.
|
22
|
+
# # db/seeds/users_seeder.rb
|
23
|
+
# require 'planter'
|
24
|
+
# class UsersSeeder < Planter::Seeder
|
25
|
+
# seeding_method :standard_csv, csv_file: '/home/me/users.csv'
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# Another way to seed is to create records from a data array. To do this, your
|
29
|
+
# class must implement a +data+ attribute or method, which is an array of
|
30
|
+
# hashes. Note that this class already provides the +attr_reader+ for this
|
31
|
+
# attribute, so the most you have to do it create instance variables in your
|
32
|
+
# constructor. If if you want your data to be different for each new record
|
33
|
+
# (via Faker, +Array#sample+, etc.), you'll probably want to supply a method
|
34
|
+
# called data that returns an array of new data each time.
|
35
|
+
# require 'planter'
|
36
|
+
# class UsersSeeder < Planter::Seeder
|
37
|
+
# seeding_method :data_array
|
38
|
+
# def data
|
39
|
+
# [{foo: 'bar', baz: 'bar'}]
|
40
|
+
# end
|
41
|
+
# end
|
42
|
+
#
|
43
|
+
# In both of the above methods, you can specify +parent_model+ and
|
44
|
+
# +association+. If specified, records will be created via that parent model's
|
45
|
+
# association. If +association+ is not provided, it will be assumed to be the
|
46
|
+
# model name, pluralized and snake-cased (implying a +has_many+ relationship).
|
47
|
+
# For example, if we're seeding the users table, and the model is +User+, the
|
48
|
+
# association will default to +users+.
|
49
|
+
# require 'planter'
|
50
|
+
# class UsersSeeder < Planter::Seeder
|
51
|
+
# seeding_method :data_array, parent_model: 'Person', association: :users
|
52
|
+
# def data
|
53
|
+
# [{foo: 'bar', baz: 'bar'}]
|
54
|
+
# end
|
55
|
+
# end
|
56
|
+
#
|
57
|
+
# You can also set +number_of_records+ to determine how many times each record
|
58
|
+
# in the +data+ array will get created. The default is 1. Note that if this
|
59
|
+
# attribute is set alongside +parent_model+ and +association+,
|
60
|
+
# +number_of_records+ will be how many records will be created for each record
|
61
|
+
# in the parent table.
|
62
|
+
# require 'planter'
|
63
|
+
# class UsersSeeder < Planter::Seeder
|
64
|
+
# seeding_method :data_array, number_of_records: 5
|
65
|
+
# def data
|
66
|
+
# [{foo: 'bar', baz: 'bar'}]
|
67
|
+
# end
|
68
|
+
# end
|
69
|
+
#
|
70
|
+
# If you need to seed a different way, put your own custom +seed+ method in
|
71
|
+
# your seeder class and do whatever needs to be done.
|
72
|
+
module Planter
|
73
|
+
##
|
74
|
+
# The seeder configuration.
|
75
|
+
#
|
76
|
+
# @return [Planter::Config]
|
77
|
+
def self.config
|
78
|
+
@config ||= Planter::Config.new
|
79
|
+
end
|
80
|
+
|
81
|
+
##
|
82
|
+
# Resets the config back to its initial state.
|
83
|
+
#
|
84
|
+
# @return [Planter::Config]
|
85
|
+
def self.reset_config
|
86
|
+
@config = Planter::Config.new
|
87
|
+
end
|
88
|
+
|
89
|
+
##
|
90
|
+
# Quick way of configuring the directories via an initializer.
|
91
|
+
#
|
92
|
+
# @return [self]
|
93
|
+
#
|
94
|
+
# @example
|
95
|
+
# Planter.configure do |app_seeder|
|
96
|
+
# app_seeder.tables = %i[users]
|
97
|
+
# app_seeder.seeders_directory = 'db/seeds'
|
98
|
+
# app_seeder.csv_files_directory = 'db/seed_files'
|
99
|
+
# end
|
100
|
+
def self.configure
|
101
|
+
config.tap { |c| yield c }
|
102
|
+
end
|
103
|
+
|
104
|
+
##
|
105
|
+
# This is the method to call from your +db/seeds.rb+. It seeds the tables
|
106
|
+
# listed in +Planter.config.tables+. To seed specific tables at
|
107
|
+
# runtime, you can set the +TABLES+ environmental variable to a
|
108
|
+
# comma-separated list of tables.
|
109
|
+
#
|
110
|
+
# @example
|
111
|
+
# rails db:seed TABLES=users,accounts
|
112
|
+
def self.seed
|
113
|
+
tables = ENV['TABLES']&.split(',') || config.tables&.map(&:to_s)
|
114
|
+
raise RuntimeError, 'No tables specified; nothing to do' unless tables&.any?
|
115
|
+
|
116
|
+
tables.each do |table|
|
117
|
+
require Rails.root.join(config.seeders_directory, "#{table}_seeder.rb").to_s
|
118
|
+
puts "Seeding #{table}" unless config.quiet
|
119
|
+
"#{table.camelize}Seeder".constantize.new.seed
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Planter
|
4
|
+
##
|
5
|
+
# Configure the application seeder.
|
6
|
+
#
|
7
|
+
# @example
|
8
|
+
# Planter.configure { |seeder| seeder.tables = %i[users] }
|
9
|
+
class Config
|
10
|
+
##
|
11
|
+
# Tell the application where the seeder classes are kept. Must be a path
|
12
|
+
# relative to +Rails.root+.
|
13
|
+
#
|
14
|
+
# @param [String] directory
|
15
|
+
#
|
16
|
+
# @return [String]
|
17
|
+
attr_accessor :seeders_directory
|
18
|
+
|
19
|
+
##
|
20
|
+
# Tell the application where the CSV seed files are kept. Must be a path
|
21
|
+
# relative to +Rails.root+.
|
22
|
+
#
|
23
|
+
# @param [String] directory
|
24
|
+
#
|
25
|
+
# @return [String]
|
26
|
+
attr_accessor :csv_files_directory
|
27
|
+
|
28
|
+
##
|
29
|
+
# Tell the application what tables to seed. Elements should be in the correct
|
30
|
+
# order, and can be strings or symbols.
|
31
|
+
#
|
32
|
+
# @param [Array] tables
|
33
|
+
#
|
34
|
+
# @return [Array]
|
35
|
+
attr_accessor :tables
|
36
|
+
|
37
|
+
##
|
38
|
+
# When true, don't print output when seeding.
|
39
|
+
#
|
40
|
+
# @param [Boolean] quiet
|
41
|
+
#
|
42
|
+
# @return [Boolean]
|
43
|
+
attr_accessor :quiet
|
44
|
+
|
45
|
+
##
|
46
|
+
# Create a new instance of the config.
|
47
|
+
def initialize
|
48
|
+
@quiet = false
|
49
|
+
@seeders_directory = ::File.join('db', 'seeds')
|
50
|
+
@csv_files_directory = ::File.join('db', 'seed_files')
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,195 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Planter
|
4
|
+
##
|
5
|
+
# The class your seeder files should inherit from.
|
6
|
+
class Seeder
|
7
|
+
##
|
8
|
+
# The allowed seeding methods.
|
9
|
+
#
|
10
|
+
# @return [Array]
|
11
|
+
SEEDING_METHODS = %i[standard_csv data_array].freeze
|
12
|
+
|
13
|
+
##
|
14
|
+
# Array of hashes used to create records. Your class must set this
|
15
|
+
# attribute when using +data_hash+ seeding method, although it's probably
|
16
|
+
# more likely that you'll want to define a method that returns a new set of
|
17
|
+
# data each time (via +Faker+, +Array#sample+, etc.). When using
|
18
|
+
# +standard_csv+, +data+ will be set to the data within the csv. You can
|
19
|
+
# override this.
|
20
|
+
#
|
21
|
+
# @return [Array]
|
22
|
+
attr_reader :data
|
23
|
+
|
24
|
+
##
|
25
|
+
# If your class is going to use the inherited +seed+ method, you must tell
|
26
|
+
# it which +seeding_method+ to use. The argument to this method must be
|
27
|
+
# included in the +SEEDING_METHODS+ array.
|
28
|
+
#
|
29
|
+
# @param [Symbol] seeding_method
|
30
|
+
#
|
31
|
+
# @param [Hash] options
|
32
|
+
#
|
33
|
+
# @example
|
34
|
+
# require 'planter'
|
35
|
+
# class UsersSeeder < Planter::Seeder
|
36
|
+
# seeding_method :data_array,
|
37
|
+
# model: 'User'
|
38
|
+
# parent_model: 'Person',
|
39
|
+
# association: :users,
|
40
|
+
# number_of_records: 2
|
41
|
+
# end
|
42
|
+
def self.seeding_method(method, **options)
|
43
|
+
if !SEEDING_METHODS.include?(method.intern)
|
44
|
+
raise ArgumentError, "Method must be one of #{SEEDING_METHODS.join(', ')}"
|
45
|
+
elsif options[:association] && !options[:parent_model]
|
46
|
+
raise ArgumentError, "Must specify :parent_model with :association"
|
47
|
+
end
|
48
|
+
|
49
|
+
@seeding_method = method
|
50
|
+
@number_of_records = options.fetch(:number_of_records, 1)
|
51
|
+
@model = options.fetch(:model, to_s.delete_suffix('Seeder').singularize)
|
52
|
+
@parent_model = options[:parent_model]
|
53
|
+
@association = @parent_model && options.fetch(:association) do
|
54
|
+
determine_association(options)
|
55
|
+
end
|
56
|
+
return unless @seeding_method == :standard_csv
|
57
|
+
|
58
|
+
@csv_file = options.fetch(:csv_file, Rails.root.join(
|
59
|
+
Planter.config.csv_files_directory,
|
60
|
+
"#{to_s.delete_suffix('Seeder').underscore}.csv"
|
61
|
+
).to_s)
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.determine_association(options) # :nodoc:
|
65
|
+
associations =
|
66
|
+
@parent_model.constantize.reflect_on_all_associations.map(&:name)
|
67
|
+
table = to_s.delete_suffix('Seeder').underscore.split('/').last
|
68
|
+
|
69
|
+
[table, table.singularize].map(&:intern).each do |t|
|
70
|
+
return t if associations.include?(t)
|
71
|
+
end
|
72
|
+
|
73
|
+
raise ArgumentError, 'Could not determine association name'
|
74
|
+
end
|
75
|
+
private_class_method :determine_association
|
76
|
+
|
77
|
+
##
|
78
|
+
# The default seed method. To use this method, your class must provide a
|
79
|
+
# valid +seeding_method+, and not implement its own +seed+ method.
|
80
|
+
def seed
|
81
|
+
validate_attributes
|
82
|
+
|
83
|
+
parent_model ? create_records_from_parent : create_records
|
84
|
+
end
|
85
|
+
|
86
|
+
protected
|
87
|
+
|
88
|
+
##
|
89
|
+
# The seeding method specified.
|
90
|
+
#
|
91
|
+
# @return [Symbol]
|
92
|
+
def seeding_method
|
93
|
+
@seeding_method ||= self.class.instance_variable_get('@seeding_method')
|
94
|
+
end
|
95
|
+
|
96
|
+
##
|
97
|
+
# The model for the table being seeded. If the model name you need is
|
98
|
+
# different, change via +seeding_method+.
|
99
|
+
#
|
100
|
+
# @return [String]
|
101
|
+
def model
|
102
|
+
@model ||= self.class.instance_variable_get('@model')
|
103
|
+
end
|
104
|
+
|
105
|
+
##
|
106
|
+
# The model of the parent. When provided with +association+, records in the
|
107
|
+
# +data+ array, will be created for each record in the parent table. Your
|
108
|
+
# class must set this attribute via +seeding_method+.
|
109
|
+
#
|
110
|
+
# @return [String]
|
111
|
+
def parent_model
|
112
|
+
@parent_model ||= self.class.instance_variable_get('@parent_model')
|
113
|
+
end
|
114
|
+
|
115
|
+
##
|
116
|
+
# When using +parent_model+, the association name. Your class can set this
|
117
|
+
# attribute via +seeding_method+.
|
118
|
+
#
|
119
|
+
# @return [Symbol]
|
120
|
+
def association
|
121
|
+
@association ||= self.class.instance_variable_get('@association')
|
122
|
+
end
|
123
|
+
|
124
|
+
##
|
125
|
+
# The number of records to create from each record in the +data+ array. If
|
126
|
+
# nil, defaults to 1, but you can override this in your class via
|
127
|
+
# +seeding_method+.
|
128
|
+
#
|
129
|
+
# @return [Integer]
|
130
|
+
def number_of_records
|
131
|
+
@number_of_records ||=
|
132
|
+
self.class.instance_variable_get('@number_of_records')
|
133
|
+
end
|
134
|
+
|
135
|
+
##
|
136
|
+
# The csv file corresponding to the model.
|
137
|
+
#
|
138
|
+
# @return [String]
|
139
|
+
def csv_file
|
140
|
+
@csv_file ||= self.class.instance_variable_get('@csv_file')
|
141
|
+
end
|
142
|
+
|
143
|
+
##
|
144
|
+
# Creates records from the +data+ attribute.
|
145
|
+
def create_records
|
146
|
+
data.each do |rec|
|
147
|
+
number_of_records.times do
|
148
|
+
model.constantize.where(
|
149
|
+
rec.transform_values { |value| value == 'NULL' ? nil : value }
|
150
|
+
).first_or_create!
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
##
|
156
|
+
# Create records from the +data+ attribute for each record in the
|
157
|
+
# +parent_table+, via the specified +association+.
|
158
|
+
def create_records_from_parent
|
159
|
+
parent_model.constantize.all.each do |assoc_rec|
|
160
|
+
number_of_records.times do
|
161
|
+
data.each { |rec| send(create_method, assoc_rec, association, rec) }
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
private
|
167
|
+
|
168
|
+
def create_method
|
169
|
+
parent_model.constantize.reflect_on_association(
|
170
|
+
association
|
171
|
+
).macro.to_s.include?('many') ? :create_has_many : :create_has_one
|
172
|
+
end
|
173
|
+
|
174
|
+
def create_has_many(assoc_rec, association, rec)
|
175
|
+
assoc_rec.public_send(association).where(rec).first_or_create!
|
176
|
+
end
|
177
|
+
|
178
|
+
def create_has_one(assoc_rec, association, rec)
|
179
|
+
assoc_rec.public_send("create_#{association}", rec)
|
180
|
+
end
|
181
|
+
|
182
|
+
def validate_attributes # :nodoc:
|
183
|
+
case seeding_method.intern
|
184
|
+
when :standard_csv
|
185
|
+
raise "#{csv_file} does not exist" unless ::File.file?(csv_file)
|
186
|
+
|
187
|
+
@data ||= ::CSV.table(csv_file).map(&:to_hash)
|
188
|
+
when :data_array
|
189
|
+
raise "Must define '@data'" if public_send(:data).nil?
|
190
|
+
else
|
191
|
+
raise("Must set 'seeding_method'")
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
metadata
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: planter
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Evan Gray
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2021-05-23 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 6.1.3
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 6.1.3.1
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 6.1.3
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 6.1.3.1
|
33
|
+
description: Create a seeder for each table in your database, and easily seed from
|
34
|
+
CSV or custom methods
|
35
|
+
email:
|
36
|
+
- evanthegrayt@vivaldi.net
|
37
|
+
executables: []
|
38
|
+
extensions: []
|
39
|
+
extra_rdoc_files: []
|
40
|
+
files:
|
41
|
+
- LICENSE
|
42
|
+
- README.md
|
43
|
+
- Rakefile
|
44
|
+
- lib/planter.rb
|
45
|
+
- lib/planter/config.rb
|
46
|
+
- lib/planter/railtie.rb
|
47
|
+
- lib/planter/seeder.rb
|
48
|
+
- lib/planter/version.rb
|
49
|
+
- lib/tasks/planter_tasks.rake
|
50
|
+
homepage: https://github.com/evanthegrayt/planter
|
51
|
+
licenses:
|
52
|
+
- MIT
|
53
|
+
metadata:
|
54
|
+
allowed_push_host: https://rubygems.org
|
55
|
+
homepage_uri: https://github.com/evanthegrayt/planter
|
56
|
+
source_code_uri: https://github.com/evanthegrayt/planter
|
57
|
+
post_install_message:
|
58
|
+
rdoc_options: []
|
59
|
+
require_paths:
|
60
|
+
- lib
|
61
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
62
|
+
requirements:
|
63
|
+
- - ">="
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
67
|
+
requirements:
|
68
|
+
- - ">="
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: '0'
|
71
|
+
requirements: []
|
72
|
+
rubygems_version: 3.2.3
|
73
|
+
signing_key:
|
74
|
+
specification_version: 4
|
75
|
+
summary: Framework for seeding rails applications.
|
76
|
+
test_files: []
|