lib/dirty_seed/seeder.rb in dirty_seed-0.2.0 vs lib/dirty_seed/seeder.rb in dirty_seed-0.2.1

- old
+ new

@@ -1,90 +1,118 @@ # frozen_string_literal: true module DirtySeed # Represents an Active Record model class Seeder - attr_reader :model, :instances, :errors + attr_reader :model, :records, :errors - # Initializes an instance + # Initializes an record # @param model [DirtySeed::Model] # @return [DirtySeed::Seeder] def initialize(model) @model = model - @instances = [] + @records = [] @errors = [] end # Creates records # @param count [Integer] # @return [Array<Object>] - def seed(count) - logger.seed(model) - @count = count + def seed(qty = 1) + self.quantity = qty + logger.seed_model_message(model) create_records - @errors.uniq! - instances + records end - # Returns the number of successfully seeded records - # @return [Integer] - def score - instances.count - end - - # Returns the errors as list - # @return [String] - def error_list - errors.join(', ') - end - private + attr_accessor :successive_errors, :quantity + attr_writer :errors + # Returns the logger # @return [DirtySeed::Logger] def logger DirtySeed::Logger.instance end # Creates records # @return [void] + # @note To take advantage of the faker uniqueness system, all params needs to be defined + # Then all records can be created with these params + # In other words: do not justcreate record one after the other def create_records - logger.start_line - data = params_collection - @count.times do |i| - instance = model.new(data[i]) - save(instance) - # rescue from errors on initialize - rescue StandardError => e - @errors << e.message - logger.error + self.successive_errors = 0 + params_collection.each do |params| + break if exceeded_successive_errors? + + record = initialize_record(params) + record && save(record) end - logger.break_line end - # Tries to save instance in database - # Populates instances and errors and log message + # Is the successive errors maximum reached? + # @return [Boolean] + # @note The purpose is to stop trying to seed if to many errors happen + def exceeded_successive_errors? + return false if successive_errors < 3 + + logger.abort + true + end + + # Initialize a record + # @param params [Hash] params to pass to #new + # @return [Object] instance of model + def initialize_record(params) + model.new(params) + # rescue from errors on initialize + rescue StandardError => e + add_standard_error(e) + end + + # Tries to save record in database + # Populates records and errors and log message # @return [void] - def save(instance) - if instance.save + def save(record) + if record.save + records << record + self.successive_errors = 0 logger.success - @instances << instance else - logger.fail - @errors.concat(instance.errors.full_messages) + add_record_errors(record) end # rescue from errors on save rescue StandardError => e - @errors << e.message - logger.error + add_standard_error(e) end + # Adds record errors + # @param record [Object] instance of model + # @return [void] + def add_record_errors(record) + self.errors |= record.errors.full_messages + self.successive_errors = successive_errors + 1 + logger.failure + end + + # Adds standard error + # @param error [Error] error inheriting from StandardError + # @return [void] + def add_standard_error(error) + self.errors |= [logger.clean(error.message)] + self.successive_errors = successive_errors + 1 + logger.failure + end + # Generate records params # @return [Array<Hash>] where Hash is params for one record + # @note If model has no attributes and no associations, return empty hashes def params_collection data = Hash[attributes_collection + associations_collection] - data.values.transpose.map { |vs| data.keys.zip(vs).to_h } + data = data.values.transpose.map { |vs| data.keys.zip(vs).to_h } + data.any? ? data : Array.new(quantity, {}) end # Generate attributes params # Each sub-array contains the attribute name and a collection of values # @return [Array<Array>] @@ -94,11 +122,11 @@ # [an_integer, [1, 2]] # ] def attributes_collection model.attributes.map do |attribute| Faker::UniqueGenerator.clear - [attribute.name, Array.new(@count) { attribute.value }] + [attribute.name, Array.new(quantity) { attribute.value }] end end # Generate associations params # Each sub-array contains the association name and a collection of values @@ -108,10 +136,10 @@ # ["alfa", [#<Alfa>, #<Alfa>]], # ["bravo", [#<Bravo>, #<Bravo>]] # ] def associations_collection model.associations.map do |association| - [association.name, Array.new(@count) { association.value }] + [association.name, Array.new(quantity) { association.value }] end end end end