Class: Planter::Seeder

Inherits:
Object
  • Object
show all
Defined in:
lib/planter/seeder.rb

Overview

Class that seeders should inherit from. Seeders should be in db/seeds, and named TABLE_seeder.rb, where TABLE is the name of the table being seeded (I.E. users_seeder.rb). If your seeder is named differently than the table, you’ll need to specify the table with the model option. The seeder’s class name should be the same as the file name, but camelized. So, UsersSeeder. The directory where the seeder files are located can be changed via an initializer.

The most basic way to seed is to have a CSV file with the same name as the table in db/seed_files/. So, users.csv. This CSV should have the table’s column names as header. To seed using this method, your class should look like the following. Note that :csv_name and :model are only required if your seeder or csv are named differently than the table being seeded. The directory where the seed files are kept can be changed via an initializer.

# db/seeds/users_seeder.rb
require 'planter'
class UsersSeeder < Planter::Seeder
  seeding_method :csv, csv_name: :users, model: 'User'
end

Another way to seed is to create records from a data array. To do this, your class must implement a data attribute or method, which is an array of hashes. Note that this class already provides the attr_reader for this attribute, so the most you have to do is create instance variables in your constructor. If if you want your data to be different for each new record (via Faker, Array#sample, etc.), you’ll probably want to supply a method called data that returns an array of new data each time.

require 'planter'
class UsersSeeder < Planter::Seeder
  seeding_method :data_array
  def data
    [{foo: 'bar', baz: 'bar'}]
  end
end

In both of the above methods, you can specify a parent association, which is the belongs_to association name in your model, which, when specified, records will be created for each record in the parent table. For example, if we’re seeding the users table, and the model is User, which belongs to Person, then doing the following will create a user record for each record in the Person table. Note that nothing is automatically done to prevent any validation errors; you must do this on your own, mostly likely using Faker or a similar library.

require 'planter'
class UsersSeeder < Planter::Seeder
  seeding_method :data_array, parent: :person
  def data
    [{foo: 'bar', baz: 'bar'}]
  end
end

You can also set number_of_records to determine how many times each record in the data array will get created. The default is 1. Note that if this attribute is set alongside parent, number_of_records will be how many records will be created for each record in the parent table.

require 'planter'
class UsersSeeder < Planter::Seeder
  seeding_method :data_array, number_of_records: 5
  def data
    [{foo: 'bar', baz: 'bar'}]
  end
end

By default, all fields are used to look up the record. If it already exists, it is not re-created. If you have specific fields that a record should be looked-up by, you can pass the unique_columns option. This will attempt to look up the record by those fields only, and if one doesn’t exist, one will be created with the rest of the attributes. An example of when this would be useful is with Devise; you can’t pass password in the create method, so specifying unique_columns on everything except password allows it to be passed as an attribute to the first_or_create call.

require 'planter'
class UsersSeeder < Planter::Seeder
  seeding_method :data_array, unique_columns: %i[username email]
  def data
    [{username: 'foo', email: 'bar', password: 'Example'}]
  end
end

If you need to seed a different way, put your own custom seed method in your seeder class and do whatever needs to be done.

Constant Summary collapse

SEEDING_METHODS =

The allowed seeding methods.

Returns:

  • (Array)
%i[csv data_array].freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#dataArray (readonly)

Array of hashes used to create records. Your class must set this attribute when using data_array seeding method, although it’s probably more likely that you’ll want to define a method that returns a new set of data each time (via Faker, Array#sample, etc.). When using csv, data will be set to the data within the csv. You can override this.

Returns:

  • (Array)


103
104
105
# File 'lib/planter/seeder.rb', line 103

def data
  @data
end

Class Method Details

.seeding_method(seed_method, number_of_records: 1, model: nil, parent: nil, csv_name: nil, unique_columns: nil, erb_trim_mode: nil) ⇒ Object

If your class is going to use the inherited seed method, you must tell it which seeding_method to use. The argument to this method must be included in the SEEDING_METHODS array.

Examples:

require 'planter'
class UsersSeeder < Planter::Seeder
  seeding_method :csv,
    number_of_records: 2,
    model: 'User'
    parent: :person,
    csv_name: :awesome_users,
    unique_columns %i[username email],
    erb_trim_mode: '<>'
end

Parameters:

  • seed_method (Symbol)


183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
# File 'lib/planter/seeder.rb', line 183

def self.seeding_method(
  seed_method,
  number_of_records: 1,
  model: nil,
  parent: nil,
  csv_name: nil,
  unique_columns: nil,
  erb_trim_mode: nil
)
  if !SEEDING_METHODS.include?(seed_method.intern)
    raise ArgumentError, "Method must be: #{SEEDING_METHODS.join(', ')}"
  end

  self.seed_method = seed_method
  self.number_of_records = number_of_records
  self.model = model || to_s.delete_suffix('Seeder').singularize
  self.parent = parent
  self.csv_name = csv_name || to_s.delete_suffix('Seeder').underscore
  self.erb_trim_mode = erb_trim_mode || Planter.config.erb_trim_mode
  self.unique_columns =
    case unique_columns
    when String, Symbol then [unique_columns.intern]
    when Array then unique_columns.map(&:intern)
    end
end

Instance Method Details

#csv_nameString

The csv file corresponding to the model.

Returns:

  • (String)


145
# File 'lib/planter/seeder.rb', line 145

class_attribute :csv_name

#erb_trim_modeString

What trim mode should ERB use?

Returns:

  • (String)


109
# File 'lib/planter/seeder.rb', line 109

class_attribute :erb_trim_mode

#modelString

The model for the table being seeded. If the model name you need is different, change via seeding_method.

Returns:

  • (String)


123
# File 'lib/planter/seeder.rb', line 123

class_attribute :model

#number_of_recordsInteger

The number of records to create from each record in the data array. If nil, defaults to 1, but you can override this in your class via seeding_method.

Returns:

  • (Integer)


139
# File 'lib/planter/seeder.rb', line 139

class_attribute :number_of_records

#parentString

The model of the parent. When provided with association, records in the data array, will be created for each record in the parent table. Your class must set this attribute via seeding_method.

Returns:

  • (String)


131
# File 'lib/planter/seeder.rb', line 131

class_attribute :parent

#seedObject

The default seed method. To use this method, your class must provide a valid seeding_method, and not implement its own seed method.



212
213
214
215
216
217
# File 'lib/planter/seeder.rb', line 212

def seed
  validate_attributes
  extract_data_from_csv if seed_method == :csv

  parent ? create_records_from_parent : create_records
end

#seed_methodSymbol

The seeding method specified.

Returns:

  • (Symbol)


151
# File 'lib/planter/seeder.rb', line 151

class_attribute :seed_method

#unique_columnsArray

When creating a record, the fields that will be used to look up the record. If it already exists, a new one will not be created.

Returns:

  • (Array)


116
# File 'lib/planter/seeder.rb', line 116

class_attribute :unique_columns