kaspth / oaken

A fresh blended alternative to Fixtures & FactoryBot for dev and test data.
MIT License
175 stars 6 forks source link

Make Oaken somewhat self-corrective #60

Closed kaspth closed 8 months ago

kaspth commented 10 months ago

If we run the drop, create, migrate below the database has changed while Oaken still believes the data is in the db and it's safe to replay the file when it's not.

The find will raise in that case and we can try to reset the file cache, so users can just rerun the command.

Test with:

RAILS_ENV=test bin/rails db:drop db:create db:migrate
bin/rails test

TODO: Hook into db:drop and reset our replay cache.

kaspth commented 10 months ago

Also toying around with an idea where we're checking that we've got all the findable data upfront, and if not, we know we can't replay the file.

But I'm not sure I like it.

diff --git a/lib/oaken/entry.rb b/lib/oaken/entry.rb
index 96a7439..71ece36 100644
--- a/lib/oaken/entry.rb
+++ b/lib/oaken/entry.rb
@@ -26,7 +26,7 @@ class Oaken::Entry < DelegateClass(PStore)

   def load_onto(seeds)
     transaction do
-      if replay?
+      if replay?(seeds)
         puts "Replaying #{@file}…"
         readers.each do |key, *args|
           define_reader(seeds.send(key), *args)
@@ -38,8 +38,8 @@ class Oaken::Entry < DelegateClass(PStore)
     end
   end

-  def replay?
-    checksum == @computed_checksum
+  def replay?(seeds)
+    checksum == @computed_checksum && expected_data_exists?(seeds)
   end

   def reset
@@ -51,4 +51,12 @@ class Oaken::Entry < DelegateClass(PStore)
     stored.instance_eval "def #{name}; find #{id}; end", @file, lineno
     readers << [stored.key, name, id, lineno]
   end
+
+  private
+    def expected_data_exists?(seeds)
+      readers&.group_by(&:first).to_h.any? do |key, values|
+        ids = values.map(&:third)
+        seeds.send(key).type.where(id: ids).size == ids.size
+      end
+    end
 end
kaspth commented 8 months ago

No longer needed after #71.