Class: FixtureKit::ActiveRecordCoder

Inherits:
Coder
  • Object
show all
Defined in:
lib/fixture_kit/coders/active_record_coder.rb

Constant Summary collapse

EVENT =
"sql.active_record"
NAME_PATTERN =
/\A(?<model_name>.+?) (?:(?:Bulk )?(?:Insert|Upsert)|Create|Destroy|(?:Update|Delete)(?: All)?)\z/

Instance Method Summary collapse

Methods inherited from Coder

#encode

Instance Method Details

#decode(data) ⇒ Object



56
57
58
59
60
# File 'lib/fixture_kit/coders/active_record_coder.rb', line 56

def decode(data)
  data.transform_keys do |model_name|
    ActiveSupport::Inflector.constantize(model_name)
  end
end

#generate(parent_data: nil, &block) ⇒ Object



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/fixture_kit/coders/active_record_coder.rb', line 11

def generate(parent_data: nil, &block)
  captured_models = Set.new
  subscriber = lambda do |_event_name, _start, _finish, _id, payload|
    name = payload[:name].to_s
    model_name = name[NAME_PATTERN, :model_name]
    next unless model_name

    klass = ActiveSupport::Inflector.safe_constantize(model_name)
    next unless klass.is_a?(Class) && klass < ActiveRecord::Base

    captured_models.add(klass)
  end

  ActiveSupport::Notifications.subscribed(subscriber, EVENT, monotonic: true, &block)

  captured_models.map! { |model| base_table_model(model) }
  captured_models.merge(parent_data.keys) if parent_data

  generate_statements(captured_models)
end

#mount(data) ⇒ Object



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/fixture_kit/coders/active_record_coder.rb', line 32

def mount(data)
  models_by_pool(data).each do |pool, models|
    pool.with_connection do |connection|
      statements = models.flat_map do |model|
        [build_delete_sql(connection, model.table_name), data[model]].compact
      end

      connection.disable_referential_integrity do
        # execute_batch is private in current supported Rails versions.
        # This should be revisited when Rails 8.2 makes it public.
        connection.__send__(:execute_batch, statements, "FixtureKit Insert")
      end

      verify_foreign_keys!(connection)

      # Replayed INSERTs use explicit PKs, which Postgres sequences do not
      # observe. Re-sync the sequence so subsequent Model.create calls don't
      # collide with an id we just inserted. No-op on adapters whose PK
      # generators advance from explicit-id INSERTs (MySQL, SQLite).
      reset_primary_key_sequences(connection, models.map(&:table_name))
    end
  end
end