fixture_farm 1.0.1 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +51 -16
- data/bin/fixture_farm.rb +13 -3
- data/lib/fixture_farm/fixture_recorder.rb +29 -7
- data/lib/fixture_farm/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d3a39068e7447367066d1947cf1f14d16366d10e88e91ae922ff3953b7667ff5
|
4
|
+
data.tar.gz: 7f28f26923b51368511ed5ef8c55531f2d405ba36d11ea802caedbc554fbcf0a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 84a8649ace5e14d8dd09b94cdde3d15f02ebd8bd602f706b48ec48f9bff9ab4ea0170fd26827886ee8b0595909d930ce16e61d21e422df9b9e9a7c545df248b7
|
7
|
+
data.tar.gz: d25f84374a79d33ee8ee117656c59e7523d4087dd3dc9065de7a540b882b5cd2fd9897e4aee3aa23af3a8f0eb43ee5168efb2d390dc12ecbde8b1a3b0fd22656
|
data/README.md
CHANGED
@@ -55,7 +55,12 @@ include FixtureFarm::ActiveJobHook if defined?(FixtureFarm)
|
|
55
55
|
Then start/stop recording using tasks:
|
56
56
|
|
57
57
|
```bash
|
58
|
-
bundle exec fixture_farm record
|
58
|
+
bundle exec fixture_farm record
|
59
|
+
# OR
|
60
|
+
bundle exec fixture_farm record name_prefix
|
61
|
+
# OR
|
62
|
+
bundle exec fixture_farm record name_prefix:replaces_name
|
63
|
+
|
59
64
|
bundle exec fixture_farm status
|
60
65
|
bundle exec fixture_farm stop
|
61
66
|
```
|
@@ -88,6 +93,25 @@ Assuming there was a parent fixture `dave` that didn't have any children, this t
|
|
88
93
|
|
89
94
|
`record_fixtures` accepts optional name prefix, that applies to all new fixture names.
|
90
95
|
|
96
|
+
#### Fixture Name Replacement
|
97
|
+
|
98
|
+
`record_fixtures` also supports hash arguments for advanced fixture naming control:
|
99
|
+
|
100
|
+
```ruby
|
101
|
+
# Replace 'client_1' with 'new_client' in fixture names, or use 'new_client' as prefix if not found
|
102
|
+
record_fixtures(new_client: :client_1) do
|
103
|
+
User.create!(name: 'Test User', email: 'test@example.com')
|
104
|
+
end
|
105
|
+
```
|
106
|
+
|
107
|
+
This works in two ways:
|
108
|
+
- **Replacement**: If a generated fixture name contains `client_1`, it gets replaced with `new_client`
|
109
|
+
- **Prefixing**: If a generated fixture name doesn't contain `client_1`, it gets prefixed with `new_client_`
|
110
|
+
|
111
|
+
For example:
|
112
|
+
- A user fixture that would be named `client_1_user_1` becomes `new_client_user_1` (replacement)
|
113
|
+
- A user fixture that would be named `user_1` becomes `new_client_user_1` (prefixing)
|
114
|
+
|
91
115
|
### Automatic fixture naming
|
92
116
|
|
93
117
|
Generated fixture names are based on the first `belongs_to` association of the model. E.g., if a new post fixtures belongs_to to a user fixture `bob`, the name is going to be `bob_post_1`.
|
@@ -100,25 +124,42 @@ FixtureFarm.low_priority_parent_model_for_naming = -> { _1.is_a?(TenantModel) }
|
|
100
124
|
|
101
125
|
### Attachment fixtures
|
102
126
|
|
103
|
-
Rather than [manually crafting attachment fixtures](https://guides.rubyonrails.org/v8.0/active_storage_overview.html#adding-attachments-to-fixtures), we can get the gem do the
|
127
|
+
Rather than [manually crafting attachment fixtures](https://guides.rubyonrails.org/v8.0/active_storage_overview.html#adding-attachments-to-fixtures), we can get the gem to do the work. Not only is this less boring, but it's also going to generate variant fixtures.
|
104
128
|
|
105
|
-
|
129
|
+
If we then check the generated blob files into git (along with the fixture files themselves), no attachment processing will be happening in tests or after `rails db:fixtures:load`.
|
106
130
|
|
107
|
-
|
108
|
-
|
109
|
-
|
131
|
+
We'll need a special storage service for the fixture blobs we want to keep versioned. For example:
|
132
|
+
|
133
|
+
```yml
|
134
|
+
# config/storage.yml
|
135
|
+
test_fixtures:
|
136
|
+
service: Disk
|
137
|
+
root: <%= Rails.root.join("test/fixtures/files/active_storage_blobs") %>
|
110
138
|
```
|
111
139
|
|
112
|
-
Now
|
140
|
+
Now a test like the one below is either going to fail if some product fixtures have no attachments, or, if run with `GENERATE_FIXTURES=1`, is going to generate those attachment fixtures, their variant fixtures if needed, along with all the blob files tucked away in a separate (from regular throw away storage) folder that can be checked in:
|
113
141
|
|
114
142
|
```ruby
|
143
|
+
if ENV["GENERATE_FIXTURES"]
|
144
|
+
setup do
|
145
|
+
@original_queue_adapter = Rails.configuration.active_job.queue_adapter
|
146
|
+
# This is so that variants get generated and blobs analyzed
|
147
|
+
Rails.configuration.active_job.queue_adapter = :inline
|
148
|
+
|
149
|
+
@original_storage_service = ActiveStorage::Blob.service
|
150
|
+
ActiveStorage::Blob.service = ActiveStorage::Blob.services.fetch(:test_fixtures)
|
151
|
+
end
|
152
|
+
|
153
|
+
teardown do
|
154
|
+
Rails.configuration.active_job.queue_adapter = @original_queue_adapter
|
155
|
+
ActiveStorage::Blob.service = @original_storage_service
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
115
159
|
test "product fixtures have images" do
|
116
160
|
offending_records = Product.where.missing(:images_attachments)
|
117
161
|
|
118
162
|
if ENV["GENERATE_FIXTURES"]
|
119
|
-
# Makes generation idempotent
|
120
|
-
`git restore --staged storage`
|
121
|
-
|
122
163
|
record_fixtures do |recorder|
|
123
164
|
ActiveStorage::Attachment.where(record_type: 'Product').destroy_all
|
124
165
|
|
@@ -128,13 +169,7 @@ test "product fixtures have images" do
|
|
128
169
|
filename: "#{product.fixture_name}.jpg",
|
129
170
|
content_type: "image/jpeg"
|
130
171
|
)
|
131
|
-
# This generates variants
|
132
|
-
perform_enqueued_jobs
|
133
172
|
end
|
134
|
-
|
135
|
-
recorder.stop!
|
136
|
-
|
137
|
-
`git add -f #{recorder.new_blob_file_paths.join(' ')}`
|
138
173
|
end
|
139
174
|
else
|
140
175
|
assert_empty offending_records.map(&:fixture_name),
|
data/bin/fixture_farm.rb
CHANGED
@@ -4,14 +4,24 @@
|
|
4
4
|
require_relative '../lib/fixture_farm/fixture_recorder'
|
5
5
|
|
6
6
|
def usage
|
7
|
-
puts 'Usage: bundle exec fixture_farm <record|status|stop> [
|
7
|
+
puts 'Usage: bundle exec fixture_farm <record|status|stop> [name_prefix|name_prefix:replaces_name]'
|
8
8
|
exit 1
|
9
9
|
end
|
10
10
|
|
11
11
|
case ARGV[0]
|
12
12
|
when 'record'
|
13
|
-
|
14
|
-
|
13
|
+
prefix_arg = ARGV[1]
|
14
|
+
|
15
|
+
# Parse hash syntax like "new_user:user_1" into {new_user: :user_1}
|
16
|
+
if prefix_arg&.include?(':')
|
17
|
+
parts = prefix_arg.split(':', 2)
|
18
|
+
parsed_prefix = { parts[0].to_sym => parts[1].to_sym }
|
19
|
+
else
|
20
|
+
parsed_prefix = prefix_arg
|
21
|
+
end
|
22
|
+
|
23
|
+
FixtureFarm::FixtureRecorder.start_recording_session!(parsed_prefix)
|
24
|
+
puts "Recording fixtures#{" with prefix #{prefix_arg}" unless prefix_arg.nil?}"
|
15
25
|
when 'status'
|
16
26
|
if FixtureFarm::FixtureRecorder.recording_session_in_progress?
|
17
27
|
puts 'Recording is on'
|
@@ -1,7 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module FixtureFarm
|
4
|
-
|
5
4
|
mattr_accessor :low_priority_parent_model_for_naming
|
6
5
|
|
7
6
|
class FixtureRecorder
|
@@ -16,7 +15,13 @@ module FixtureFarm
|
|
16
15
|
end
|
17
16
|
|
18
17
|
def initialize(fixture_name_prefix, new_models = [])
|
19
|
-
|
18
|
+
if fixture_name_prefix.is_a?(Hash)
|
19
|
+
@fixture_name_replacements = fixture_name_prefix
|
20
|
+
@fixture_name_prefix = nil
|
21
|
+
else
|
22
|
+
@fixture_name_prefix = fixture_name_prefix
|
23
|
+
@fixture_name_replacements = {}
|
24
|
+
end
|
20
25
|
@new_models = new_models
|
21
26
|
@deleted_models = {}
|
22
27
|
@initial_now = Time.zone.now
|
@@ -95,9 +100,11 @@ module FixtureFarm
|
|
95
100
|
end
|
96
101
|
end
|
97
102
|
|
98
|
-
yield self
|
103
|
+
result = yield self
|
99
104
|
|
100
105
|
stop! unless @stopped
|
106
|
+
|
107
|
+
result
|
101
108
|
ensure
|
102
109
|
ActiveSupport::Notifications.unsubscribe(@subscriber)
|
103
110
|
end
|
@@ -144,8 +151,10 @@ module FixtureFarm
|
|
144
151
|
|
145
152
|
blob.update!(key: new_key)
|
146
153
|
|
147
|
-
|
148
|
-
|
154
|
+
blobs_root_path = Pathname.new(ActiveStorage::Blob.service.root)
|
155
|
+
|
156
|
+
from_path = blobs_root_path.join(old_key[0..1], old_key[2..3], old_key)
|
157
|
+
to_dir = blobs_root_path.join(new_key[0..1], new_key[2..3])
|
149
158
|
to_path = to_dir.join(new_key)
|
150
159
|
|
151
160
|
`mkdir -p #{to_dir}`
|
@@ -366,12 +375,25 @@ module FixtureFarm
|
|
366
375
|
fixture_name(model_instance) || begin
|
367
376
|
existing_fixtures = existing_fixtures_for_model(model_instance)
|
368
377
|
|
369
|
-
|
378
|
+
base_name = [
|
370
379
|
first_belongs_to_fixture_name(model_instance).presence || @fixture_name_prefix,
|
371
380
|
"#{model_instance.class.name.underscore.split('/').last}_1"
|
372
381
|
].select(&:present?).join('_')
|
373
382
|
|
374
|
-
|
383
|
+
@fixture_name_replacements.each do |new_name, old_name|
|
384
|
+
# Only apply replacement if the base_name doesn't already start with new_name
|
385
|
+
# This prevents double-application of replacements
|
386
|
+
next if base_name.start_with?("#{new_name}_")
|
387
|
+
|
388
|
+
original_name = base_name
|
389
|
+
base_name = base_name.gsub(/\b#{Regexp.escape(old_name.to_s)}\b/, new_name.to_s)
|
390
|
+
|
391
|
+
# If no replacement occurred, use new_name as prefix
|
392
|
+
base_name = "#{new_name}_#{base_name}" if base_name == original_name
|
393
|
+
end
|
394
|
+
|
395
|
+
new_fixture_name = base_name
|
396
|
+
while @named_new_fixtures[new_fixture_name] || (existing_fixtures[new_fixture_name] && !@deleted_models[new_fixture_name])
|
375
397
|
new_fixture_name = new_fixture_name.sub(/_(\d+)$/, "_#{Regexp.last_match(1).to_i + 1}")
|
376
398
|
end
|
377
399
|
|
data/lib/fixture_farm/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fixture_farm
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- artemave
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-
|
11
|
+
date: 2025-08-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|