class ConfigScripts::Seeds::SeedSet
This class represents a set of related seeds.
These seeds will be stored as CSV files in a folder together.
Attributes
@return [Hash<Integer, SeedSet>] The seed sets that have been defined.
@return [String] The name of the folder to which we will write the seeds.
@return [String] The name of the folder for this seed set.
@return [Hash] Arbitrary extra data passed in when defining the seed set.
@return [Proc] The block that will be run when resetting the records during a load.
@return [Hash] A hash mapping class names to the {SeedType} instances describing how to handle seeds for that class within this set.
@return [Integer] A number identifying this set. Seed sets will be run from the one with the lowest number to the highest.
Public Class Methods
This method wipes out our records of registered seed sets.
@return [Hash]
The new list of seed sets.
# File lib/config_scripts/seeds/seed_set.rb, line 62 def clear_registered_sets @registered_sets = {} end
This method runs a block on each set that the app has defined.
The block will be given one parameter, which is the seed set.
@param [String] set_number
The number of the set that we should run.
@return [Array]
# File lib/config_scripts/seeds/seed_set.rb, line 115 def each_set(set_number=nil, &block) @registered_sets ||= {} self.load_seed_sets if set_number if self.registered_sets[set_number] block.call(self.registered_sets[set_number]) end else self.registered_sets.keys.sort.each do |set_number| block.call(self.registered_sets[set_number]) end end end
This method lists every seed set, with its set number. @return [Array]
# File lib/config_scripts/seeds/seed_set.rb, line 101 def list self.each_set do |set| puts "#{set.set_number}: #{set.name}" end end
This method loads all of the seed definitions from the files in the db/seeds/definitions
directory.
# File lib/config_scripts/seeds/seed_set.rb, line 68 def load_seed_sets Dir[Rails.root.join('db', 'seeds', 'definitions', '*')].each do |file| require file end end
This method creates a new seed set.
It should be given a block, which will be run on the instance, and which should use the {#seeds_for} method to define seed types.
@param [String] name
The name for the folder for the seeds.
@param [Integer] set_number
The set_number in which this seed set should be run.
@param [String] folder
The folder that we should use for this seed set. If this is not provided, we will use the name.
@param [Hash] options
Additional information that can be made accessible to the seed type definitions.
# File lib/config_scripts/seeds/seed_set.rb, line 150 def initialize(name, set_number=1, folder=nil, options = {}, &block) @name = name.to_s @set_number = set_number @folder = folder || @name @options = options @seed_types = {} @unscoped_classes = [] self.instance_eval(&block) if block_given? ConfigScripts::Seeds::SeedSet.register_seed_set(self) end
This method loads the data from every seed set into the database.
@param [Integer] set_number
The number of the set to read.
@return [Array]
# File lib/config_scripts/seeds/seed_set.rb, line 93 def read(set_number=nil) self.each_set set_number do |set| set.read(set_number.present?) end end
This method adds a new seed set to our registry.
If there is already a registered seed set with this set’s set_number
, the number will be incremented until it is available.
@param [SeedSet] set
The new seed set.
@return [SeedSet]
# File lib/config_scripts/seeds/seed_set.rb, line 49 def register_seed_set(set) @registered_sets ||= {} while @registered_sets[set.set_number] return if @registered_sets[set.set_number] == set set.set_number += 1 end @registered_sets[set.set_number] = set end
This method writes the data for every seed set to its seed data folder.
@param [Integer] set_number
The number of the set to write.
@return [Array]
# File lib/config_scripts/seeds/seed_set.rb, line 83 def write(set_number=nil) self.each_set(set_number, &:write) end
Public Instance Methods
This method reads the data for this seed set from its seed folder.
It will load the data for each seed type’s file, enclosing all the seed types in a transaction block.
@param [Boolean] reset
Whether we should reset the existing records before loading the seeds.
# File lib/config_scripts/seeds/seed_set.rb, line 199 def read(reset=false) self.read_with_unscoped(reset, @unscoped_classes) end
This method reads the data for this seed set from its seed folder.
@param [Boolean] reset
Whether we should reset the existing records before loading the seeds.
@param [Array<Class>] unscoped_classes
The classes that we need to remove default scopes from before loading the seeds.
# File lib/config_scripts/seeds/seed_set.rb, line 211 def read_with_unscoped(reset, unscoped_classes) if unscoped_classes.any? unscoped_classes.first.unscoped { self.read_with_unscoped(reset, unscoped_classes[1..-1]) } else folder_path = Rails.root.join('db', 'seeds', 'data', self.folder) FileUtils.mkdir_p(folder_path) puts "Reading seeds for #{self.name} from #{folder_path}" ActiveRecord::Base.transaction do self.reset_records if reset self.seed_types.each do |klass, seed_type| seed_type.read_from_folder(folder_path) end end end end
This method finds a record based on a unique identifier in the seed data.
This will look for a seed type for the class, and use its {#record_for_seed_identifier} method to get the record.
The result of this will be memoized so that we do not have to keep looking up the records.
@param [Class] klass
The model class for the record we are finding.
@param [Array<String>] identifier
The identifier components from the seed data.
@return [ActiveRecord::Base]
The model record.
# File lib/config_scripts/seeds/seed_set.rb, line 333 def record_for_seed_identifier(klass, identifier) seed_type = self.seed_type_for_class(klass) return nil unless seed_type @record_cache ||= {} @record_cache[klass] ||= {} cache_identifier = identifier.dup while cache_identifier.any? record = @record_cache[klass][cache_identifier] if record cache_identifier.count.times { identifier.shift } return record end cache_identifier.pop end if seed_type cache_identifier = identifier.dup record = seed_type.record_for_seed_identifier(identifier) if identifier.any? cache_identifier = cache_identifier[0...-1*identifier.count] end @record_cache[klass][cache_identifier] = record end record end
This method resets all the existing records that could be populated by this seed set.
# File lib/config_scripts/seeds/seed_set.rb, line 229 def reset_records self.reset_block.call if self.reset_block end
This method gets a unique identifier for a record when writing seeds that refer to it.
It will look for a seed type that handles seeds for a class in the record’s class heirarchy, and use that seed type’s {#seed_identifier_for_record} method. If it cannot find a seed type, it will use the record’s ID.
@param [ActiveRecord::Base] record
The record whose identifier we are generating.
@return [String]
# File lib/config_scripts/seeds/seed_set.rb, line 307 def seed_identifier_for_record(record) seed_type = self.seed_type_for_class(record.class) if seed_type seed_type.seed_identifier_for_record(record) else record.id rescue nil end end
This method gets a seed type that we have on file for a class.
@param [Class] klass
The class whose seeds we are dealing with.
@return [SeedType]
# File lib/config_scripts/seeds/seed_set.rb, line 284 def seed_type_for_class(klass) while klass && klass != ActiveRecord::Base seed_type = self.seed_types[klass] if seed_type return seed_type end klass = klass.superclass end end
This method defines a new seed type within this seed set.
This method should be given a block, which will be passed to the initializer for the new seed type.
@param [Class] klass
The model class whose seed data this stores.
@param [String] filename
The name of the file in which the seed data should be stored. If this is not provided, it will use the name of the class. This should not include the file extension.
@return [SeedType]
# File lib/config_scripts/seeds/seed_set.rb, line 249 def seeds_for(klass, filename=nil, &block) filename ||= klass.name.underscore.pluralize @seed_types[klass] = SeedType.new(self, klass, filename, &block) end
This method specifies classes that will be unscoped when writing the seed data.
@param [Array<Class>] classes
The classes to unscope.
@return [Array<Class>]
The new list of unscoped classes.
# File lib/config_scripts/seeds/seed_set.rb, line 272 def unscope(*classes) @unscoped_classes += classes end
This method defines a block that will be run when resetting existing records.
This block will be run when loading a seed set as a one-off, but not when loading all the seed sets.
@return [Proc]
# File lib/config_scripts/seeds/seed_set.rb, line 261 def when_resetting(&block) @reset_block = block end
This method writes the data for this seed set to its seed folder.
It will create the folder and then write the file for each seed type that has been defined.
# File lib/config_scripts/seeds/seed_set.rb, line 167 def write self.write_with_unscoped(@unscoped_classes) end
This method writes the data for this seed set to its seed folder.
It will remove all default scopes from the classes provided before doing the write.
@param [Array<Class>] unscoped_classes
The classes whose scopes we will remove.
# File lib/config_scripts/seeds/seed_set.rb, line 177 def write_with_unscoped(unscoped_classes) if unscoped_classes.any? unscoped_classes.first.unscoped do self.write_with_unscoped(unscoped_classes[1..-1]) end else folder_path = Rails.root.join('db', 'seeds', 'data', self.folder) FileUtils.mkdir_p(folder_path) puts "Writing seeds for #{self.name} to #{folder_path}" self.seed_types.each do |klass, seed_type| seed_type.write_to_folder(folder_path) end end end