-
-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Rewrite loading …and also the gem it seems (#54)
* First stab at rewriting our loading structure * Expose loader on Seeds and each loadable * Keep track of current entry to track readers properly * Delete old implementation; I'm already feeling pretty confident about where this new version is headed * Use a PStore to help store our details between runs * Fix Ruby 3.0 support * Move this down for hopefully cleaner diff * Blend our concepts between Entry and Store a bit and see what that's like * I do love me some instance variables but also… um * Tweak message a bit * Inject current environment in path prefix * Extract store_path to a config; still reliant on Rails.env, but that's ok for now * Slim Loader some more, not sure if we need it, but I like it for now * Move Entry out of Loader namespace * Graduate Entry into its own file * We're not relying on YAML anymore * Extract more concepts into files and refactor a bit * Inject env via a Railtie * Prepare for supplanting loading from test/seeds; skip loader reentrance checks now that they fail * Mirror type, key argument structure and refit the code a bit …I'm not quite sure why yet * Make an attempt at defining what our default preseeding is * Replace preregister and connection need with a method_missing lazy hook * Make db/seeds work as a top-level configuration point for Oaken; I'm pretty sleepy so this is probably somewhat experimental * Include an env override to reset cache in case it's corrupt * Don't make seeds all-in by default to allow one-off cases. By having our loading be all-in we need to exclude a lot of found file paths, and gives users less control to tweak things. Instead we can have lookup paths to help define our loading behavior, and then for each given path we can look in those. This lets us support one-off cases for e.g. a pagination test where you want to load many objects but you don't need those for other tests. I'm setting up a pattern of those being in `db/seeds/cases` or `db/seeds/<env>/cases`.
- Loading branch information
Showing
14 changed files
with
179 additions
and
133 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
require "digest/md5" | ||
require "pstore" | ||
|
||
class Oaken::Entry < DelegateClass(PStore) | ||
def self.store_accessor(name) | ||
define_method(name) { self[name] } and define_method("#{name}=") { |value| self[name] = value } | ||
end | ||
store_accessor :checksum | ||
store_accessor :readers | ||
|
||
def self.within(directory) | ||
Pathname.glob("#{directory}{,/**/*}.rb").sort.map { new _1 } | ||
end | ||
|
||
def initialize(pathname) | ||
@file, @pathname = pathname.to_s, pathname | ||
@computed_checksum = Digest::MD5.hexdigest(@pathname.read) | ||
|
||
prepared_store_path = Oaken.store_path.join(pathname).tap { _1.dirname.mkpath } | ||
super PStore.new(prepared_store_path) | ||
end | ||
|
||
def load_onto(seeds) | ||
transaction do | ||
if replay? | ||
puts "Replaying #{@file}…" | ||
readers.each do |key, name, id, lineno| | ||
seeds.send(key).instance_eval "def #{name}; find #{id}; end", @file, lineno | ||
end | ||
else | ||
reset | ||
seeds.class_eval @pathname.read, @file | ||
end | ||
end | ||
end | ||
|
||
def replay? | ||
checksum == @computed_checksum | ||
end | ||
|
||
def reset | ||
self.checksum = @computed_checksum | ||
self.readers = Set.new | ||
end | ||
|
||
def define_reader(stored, name, id) | ||
lineno = self.lineno | ||
stored.instance_eval "def #{name}; find #{id}; end", @file, lineno | ||
readers << [stored.key, name, id, lineno] | ||
end | ||
|
||
def lineno | ||
caller_locations(3, 10).find { _1.path == @file }.lineno | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
class Oaken::Railtie < Rails::Railtie | ||
initializer "oaken.defaults" do | ||
Oaken.lookup_paths << "db/seeds/#{Rails.env}" | ||
Oaken.store_path = Oaken.store_path.join(Rails.env) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
module Oaken::Seeds | ||
extend self | ||
|
||
def self.respond_to_missing?(name, ...) | ||
Oaken.inflector.classify(name).safe_constantize || super | ||
end | ||
|
||
def self.method_missing(name, ...) | ||
name = name.to_s | ||
if type = Oaken.inflector.classify(name).safe_constantize | ||
register type, name | ||
public_send(name, ...) | ||
else | ||
super | ||
end | ||
end | ||
|
||
def self.register(type, key = nil) | ||
stored = provider.new(type, key) and define_method(stored.key) { stored } | ||
end | ||
def self.provider = Oaken::Stored::ActiveRecord | ||
|
||
singleton_class.attr_reader :loader | ||
delegate :entry, to: :loader | ||
|
||
module Loading | ||
def seed(*directories) | ||
Oaken.lookup_paths.each do |path| | ||
directories.each do |directory| | ||
@loader = Oaken::Loader.new Pathname(path).join(directory.to_s) | ||
@loader.load_onto Oaken::Seeds | ||
end | ||
end | ||
end | ||
end | ||
extend Loading | ||
|
||
def self.included(klass) | ||
klass.extend Loading | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
class Oaken::Stored::ActiveRecord < Struct.new(:type, :key) | ||
def initialize(type, key = nil) | ||
super(type, key || Oaken.inflector.tableize(type.name)) | ||
end | ||
delegate :find, :insert_all, to: :type | ||
|
||
def create(reader = nil, **attributes) | ||
type.create!(**attributes).tap do |record| | ||
define_reader reader, record.id if reader | ||
end | ||
end | ||
|
||
def insert(reader = nil, **attributes) | ||
type.new(attributes).validate! | ||
type.insert(attributes).tap do | ||
define_reader reader, type.where(attributes).pick(:id) if reader | ||
end | ||
end | ||
|
||
def define_reader(name, id) | ||
Oaken::Seeds.entry.define_reader(self, name, id) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,6 @@ | ||
class Account < ApplicationRecord | ||
has_many :administratorships | ||
has_many :users, through: :administratorships | ||
|
||
has_many :menus | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,5 @@ | ||
Oaken.seeds do | ||
register Menu::Item | ||
|
||
seed :accounts, :data | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
item_id = accounts.kaspers_donuts.menus.first.items.pick(:id) | ||
|
||
orders.insert_all \ | ||
[{ user_id: users.kasper.id, item_id: item_id }] * 100 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
raise "This seed file executed outside of production" unless Rails.env.production? |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
plans.insert :test_premium, title: "Premium", price_cents: 20_00 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
require "test_helper" | ||
|
||
class PaginationTest < ActiveSupport::TestCase | ||
seed "cases/pagination" | ||
|
||
test "pagination sorta" do | ||
assert_operator Order.count, :>=, 100 | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters