diff --git a/lib/oaken.rb b/lib/oaken.rb index 70e255b..b830360 100644 --- a/lib/oaken.rb +++ b/lib/oaken.rb @@ -16,16 +16,41 @@ module Stored singleton_class.attr_reader :lookup_paths @lookup_paths = ["db/seeds"] + def self.lookups_from(paths) + lookup_paths.product(paths).map(&File.method(:join)) + end + + class NoSeedsFoundError < ArgumentError; end + class Loader - def initialize(path) - @entries = Pathname.glob("#{path}{,/**/*}.rb").sort + def self.from(paths) + new Path.expand(paths).sort + end + + def initialize(paths) + @paths = paths end - def load_onto(seeds) = @entries.each do |path| + def load_onto(seeds) = @paths.each do |path| ActiveRecord::Base.transaction do seeds.class_eval path.read, path.to_s end end + + class Path + def self.expand(paths) + patterns = Oaken.lookups_from(paths).map { new _1 } + patterns.flat_map(&:to_a).tap do |found| + raise Oaken::NoSeedsFoundError, "found no seed files for #{paths.map(&:inspect).join(", ")} when searching with #{patterns.join(", ")}" if found.none? + end + end + + def initialize(path) + @pattern = "#{path}{,/**/*}.rb" + end + def to_s = @pattern + def to_a = Pathname.glob(@pattern) + end end def self.prepare(&block) = Seeds.instance_eval(&block) diff --git a/lib/oaken/seeds.rb b/lib/oaken/seeds.rb index de06bab..27cf9f1 100644 --- a/lib/oaken/seeds.rb +++ b/lib/oaken/seeds.rb @@ -62,17 +62,8 @@ class << self # class PaginationTest < ActionDispatch::IntegrationTest # setup { seed "cases/pagination" } # end - def seed(*directories) - Oaken.lookup_paths.product(directories).each do |path, directory| - load_from Pathname(path).join(directory.to_s) - end - end - - private def load_from(path) - @loader = Oaken::Loader.new path - @loader.load_onto self - ensure - @loader = nil + def seed(*paths) + Oaken::Loader.from(paths.map(&:to_s)).load_onto self end # `section` is purely for decorative purposes to carve up `Oaken.prepare` and seed files. diff --git a/test/dummy/test/models/oaken_test.rb b/test/dummy/test/models/oaken_test.rb index fc878bc..a589a22 100644 --- a/test/dummy/test/models/oaken_test.rb +++ b/test/dummy/test/models/oaken_test.rb @@ -96,4 +96,16 @@ def self.column_names = [] assert mod.respond_to?(:users) # Now respond_to_missing? hits. refute mod.respond_to?(:hmhm) end + + test "raises when no files found to seed" do + assert_raise(Oaken::NoSeedsFoundError) { seed "missing" }.tap do |error| + assert_match "db/seeds/missing{", error.message + assert_match "db/seeds/test/missing{", error.message + end + + assert_raise(Oaken::NoSeedsFoundError) { seed "test/cases/missing" }.tap do |error| + assert_match "db/seeds/test/cases/missing{", error.message + assert_match "db/seeds/test/test/cases/missing{", error.message + end + end end