Module: TestProf::AnyFixture

Extended by:
Logging
Defined in:
lib/test_prof/any_fixture.rb,
lib/test_prof/any_fixture/dsl.rb,
lib/test_prof/any_fixture/dump.rb,
lib/test_prof/any_fixture/dump/digest.rb,
lib/test_prof/any_fixture/dump/sqlite.rb,
lib/test_prof/any_fixture/dump/postgresql.rb,
lib/test_prof/any_fixture/dump/base_adapter.rb

Overview

Make DB fixtures from blocks.

Defined Under Namespace

Modules: DSL Classes: Cache, Configuration, Dump

Constant Summary collapse

INSERT_RXP =
/^INSERT INTO ([\S]+)/.freeze
MODIFY_RXP =
/^(INSERT INTO|UPDATE|DELETE FROM) ([\S]+)/i.freeze
ANY_FIXTURE_RXP =
/(\/\*|\-\-).*\bany_fixture:dump/.freeze
ANY_FIXTURE_IGNORE_RXP =
/(\/\*|\-\-).*\bany_fixture:ignore/.freeze

Constants included from Logging

Logging::COLORS

Class Method Summary collapse

Methods included from Logging

build_log_msg, colorize, log

Class Method Details

.cached(id) ⇒ Object



127
128
129
# File 'lib/test_prof/any_fixture.rb', line 127

def cached(id)
  cache.fetch(id) { yield }
end

.cleanObject

Clean all affected tables (but do not reset cache)



165
166
167
168
169
170
171
172
173
# File 'lib/test_prof/any_fixture.rb', line 165

def clean
  disable_referential_integrity do
    tables_cache.keys.reverse_each do |table|
      ActiveRecord::Base.connection.execute %(
        DELETE FROM #{table}
      )
    end
  end
end

.configObject



96
97
98
# File 'lib/test_prof/any_fixture.rb', line 96

def config
  @config ||= Configuration.new
end

.configure {|config| ... } ⇒ Object

Yields:



100
101
102
# File 'lib/test_prof/any_fixture.rb', line 100

def configure
  yield config
end

.register(id) ⇒ Object

Register a block of code as a fixture, returns the result of the block execution



119
120
121
122
123
124
125
# File 'lib/test_prof/any_fixture.rb', line 119

def register(id)
  cached(id) do
    ActiveSupport::Notifications.subscribed(method(:subscriber), "sql.active_record") do
      yield
    end
  end
end

.register_dump(name, clean: true, **options) ⇒ Object

Create and register new SQL dump. Use watch to provide additional paths to watch for dump re-generation



134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/test_prof/any_fixture.rb', line 134

def register_dump(name, clean: true, **options)
  called_from = caller_locations(1, 1).first.path
  watch = options.delete(:watch) || [called_from]
  cache_key = options.delete(:cache_key)
  skip = options.delete(:skip_if)

  id = "sql/#{name}"

  register_method = clean ? :register : :cached

  public_send(register_method, id) do
    dump = Dump.new(name, watch: watch, cache_key: cache_key)

    unless dump.force?
      next if skip&.call(dump: dump)

      next dump.within_prepared_env(import: true, **options) { dump.load } if dump.exists?
    end

    subscriber = ActiveSupport::Notifications.subscribe("sql.active_record", dump.subscriber)
    res = dump.within_prepared_env(**options) { yield }

    dump.commit!

    res
  ensure
    ActiveSupport::Notifications.unsubscribe(subscriber) if subscriber
  end
end

.report_statsObject



193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
# File 'lib/test_prof/any_fixture.rb', line 193

def report_stats
  if cache.stats.empty?
    log :info, "AnyFixture has not been used"
    return
  end

  msgs = []

  msgs <<
    "      AnyFixture usage stats:\n    MSG\n\n  first_column = cache.stats.keys.map(&:size).max + 2\n\n  msgs << format(\n    \"%\#{first_column}s  %12s  %9s  %12s\",\n    \"key\", \"build time\", \"hit count\", \"saved time\"\n  )\n\n  msgs << \"\"\n\n  total_spent = 0.0\n  total_saved = 0.0\n  total_miss = 0.0\n\n  cache.stats.to_a.sort_by { |(_, v)| -v[:hit] }.each do |(key, stats)|\n    total_spent += stats[:time]\n\n    saved = stats[:time] * stats[:hit]\n\n    total_saved += saved\n\n    total_miss += stats[:time] if stats[:hit].zero?\n\n    msgs << format(\n      \"%\#{first_column}s  %12s  %9d  %12s\",\n      key, stats[:time].duration, stats[:hit],\n      saved.duration\n    )\n  end\n\n  msgs <<\n    <<~MSG\n\n      Total time spent: \#{total_spent.duration}\n      Total time saved: \#{total_saved.duration}\n      Total time wasted: \#{total_miss.duration}\n    MSG\n\n  log :info, msgs.join(\"\\n\")\nend\n"

.reporting_enabledObject Also known as: reporting_enabled?



110
111
112
113
# File 'lib/test_prof/any_fixture.rb', line 110

def reporting_enabled
  warn "AnyFixture.reporting_enabled is deprecated and will be removed in 1.1. Use AnyFixture.config.reporting_enabled instead"
  config.reporting_enabled
end

.reporting_enabled=(val) ⇒ Object

Backward compatibility



105
106
107
108
# File 'lib/test_prof/any_fixture.rb', line 105

def reporting_enabled=(val)
  warn "AnyFixture.reporting_enabled is deprecated and will be removed in 1.1. Use AnyFixture.config.reporting_enabled instead"
  config.reporting_enabled = val
end

.resetObject

Reset all information and clean tables



176
177
178
179
180
# File 'lib/test_prof/any_fixture.rb', line 176

def reset
  clean
  tables_cache.clear
  cache.clear
end

.subscriber(_event, _start, _finish, _id, data) ⇒ Object



182
183
184
185
186
187
188
189
190
191
# File 'lib/test_prof/any_fixture.rb', line 182

def subscriber(_event, _start, _finish, _id, data)
  matches = data.fetch(:sql).match(INSERT_RXP)
  return unless matches

  table_name = matches[1]

  return if /sqlite_sequence/.match?(table_name)

  tables_cache[table_name] = true
end