fixture_farm 0.1.5 → 0.2.0
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 +35 -2
- data/bin/fixture_farm.rb +1 -2
- data/lib/fixture_farm/fixture_recorder.rb +50 -12
- data/lib/fixture_farm/test_helper.rb +1 -1
- data/lib/fixture_farm/version.rb +1 -1
- metadata +7 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 72792ee8f5bca838e5fda1e5ec3088e4c97ec40e740b732734cc0529304afdf4
|
4
|
+
data.tar.gz: c14d543f77631a323abbcee6ce81d1d52afbb04785a2ba82d611f29ebd6e39b8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: af76dc042d9d51ede677265a6da0cf0203d2934db1bd7b2d218569519df5cdf34a5b1951ce958b90efa2955df5dae6e3fda25a059df2cad31969cece715743c7
|
7
|
+
data.tar.gz: 1ddc003eade3440055aa754290ffea23cca62c0c71c72c3e38e2a4f783255828ad2860400415e33aa1f7f97b4a7e0b7e14a7d969f8e7544aaf39bbd7ecd9c899
|
data/README.md
CHANGED
@@ -65,7 +65,7 @@ To record in tests, wrap some code in `record_new_fixtures` block. For example:
|
|
65
65
|
include FixtureFarm::TestHelper
|
66
66
|
|
67
67
|
test 'some stuff does the right thing' do
|
68
|
-
record_new_fixtures
|
68
|
+
record_new_fixtures do |stop_recording|
|
69
69
|
user = User.create!(name: 'Bob')
|
70
70
|
post = user.posts.create!(title: 'Stuff')
|
71
71
|
|
@@ -82,7 +82,7 @@ Running this test generates user and post fixtures. Now you can rewrite this tes
|
|
82
82
|
|
83
83
|
```ruby
|
84
84
|
test 'some stuff does the right thing' do
|
85
|
-
user = users('
|
85
|
+
user = users('user_1')
|
86
86
|
|
87
87
|
assert_difference 'user.published_posts.size' do
|
88
88
|
user.posts.first.publish!
|
@@ -90,5 +90,38 @@ test 'some stuff does the right thing' do
|
|
90
90
|
end
|
91
91
|
```
|
92
92
|
|
93
|
+
`record_new_fixtures` accepts optional name prefix, that applies to all new fixture names.
|
94
|
+
|
95
|
+
A more robust approach is to have dedicated fixture tests that normally fail, but can be optionally run in "record mode" (think VCR).
|
96
|
+
|
97
|
+
For example, let's say we have `Author` model that `has_many :posts` and we require authors to have at least one post. Here's the test to enforce `authors` fixtures to comply with this rule:
|
98
|
+
|
99
|
+
```ruby
|
100
|
+
test 'authors fixtures must have at least one post' do
|
101
|
+
offending_records = Author.where.missing(:posts)
|
102
|
+
|
103
|
+
assert_empty offending_records
|
104
|
+
end
|
105
|
+
```
|
106
|
+
|
107
|
+
Now let's the option to automatically record missing fixtures:
|
108
|
+
|
109
|
+
```ruby
|
110
|
+
test 'authors fixtures must have at least one post' do
|
111
|
+
offending_records = Author.where.missing(:posts)
|
112
|
+
|
113
|
+
if ENV['RECORD_FIXTURES']
|
114
|
+
record_new_fixtures do
|
115
|
+
offending_records.each do |author|
|
116
|
+
author.posts.create!(text: 'some text')
|
117
|
+
end
|
118
|
+
end
|
119
|
+
else
|
120
|
+
assert_empty offending_records
|
121
|
+
end
|
122
|
+
end
|
123
|
+
```
|
124
|
+
|
125
|
+
|
93
126
|
## License
|
94
127
|
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/bin/fixture_farm.rb
CHANGED
@@ -10,9 +10,8 @@ end
|
|
10
10
|
|
11
11
|
case ARGV[0]
|
12
12
|
when 'record'
|
13
|
-
usage unless ARGV[1]
|
14
13
|
FixtureFarm::FixtureRecorder.start_recording_session!(ARGV[1])
|
15
|
-
puts
|
14
|
+
puts 'Recording fixtures' + ARGV[1].nil? ? '' : " with prefix #{ARGV[1]}"
|
16
15
|
when 'status'
|
17
16
|
puts "Recording is #{FixtureFarm::FixtureRecorder.recording_session_in_progress? ? 'on' : 'off'}"
|
18
17
|
when 'stop'
|
@@ -1,6 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module FixtureFarm
|
4
|
+
mattr_accessor :parent_models_to_ignore_when_naming_fixtures
|
5
|
+
|
4
6
|
class FixtureRecorder
|
5
7
|
STORE_PATH = Rails.root.join('tmp', 'fixture_farm_store.json')
|
6
8
|
|
@@ -8,6 +10,7 @@ module FixtureFarm
|
|
8
10
|
@fixture_name_prefix = fixture_name_prefix
|
9
11
|
@new_models = new_models
|
10
12
|
@initial_now = Time.zone.now
|
13
|
+
@ignore_while_tree_walking = Set.new
|
11
14
|
end
|
12
15
|
|
13
16
|
def self.resume_recording_session
|
@@ -92,15 +95,41 @@ module FixtureFarm
|
|
92
95
|
end
|
93
96
|
|
94
97
|
def named_new_fixtures
|
95
|
-
@
|
96
|
-
|
98
|
+
@named_new_fixtures ||= begin
|
99
|
+
(@new_models - @ignore_while_tree_walking.to_a).uniq(&:id).each_with_object({}) do |model_instance, named_new_fixtures|
|
100
|
+
@ignore_while_tree_walking.add(model_instance)
|
97
101
|
|
98
|
-
|
99
|
-
|
100
|
-
|
102
|
+
new_fixture_name = [
|
103
|
+
@fixture_name_prefix,
|
104
|
+
first_belongs_to_fixture_name(model_instance),
|
105
|
+
"#{model_instance.class.name.underscore.split('/').last}_1"
|
106
|
+
].select(&:present?).join('_')
|
107
|
+
|
108
|
+
while named_new_fixtures[new_fixture_name]
|
109
|
+
new_fixture_name = new_fixture_name.sub(/_(\d+)$/, "_#{Regexp.last_match(1).to_i + 1}")
|
110
|
+
end
|
111
|
+
|
112
|
+
named_new_fixtures[new_fixture_name] = model_instance
|
113
|
+
|
114
|
+
@ignore_while_tree_walking.delete(model_instance)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def first_belongs_to_fixture_name(model_instance)
|
120
|
+
model_instance.class.reflect_on_all_associations.filter(&:belongs_to?).each do |association|
|
121
|
+
associated_model_instance = find_associated_model_instance(model_instance, association)
|
101
122
|
|
102
|
-
|
123
|
+
next unless associated_model_instance
|
124
|
+
|
125
|
+
next if FixtureFarm.parent_models_to_ignore_when_naming_fixtures.any? { _1.call(associated_model_instance) }
|
126
|
+
|
127
|
+
if (associated_model_instance_fixture_name = fixture_name(associated_model_instance))
|
128
|
+
return associated_model_instance_fixture_name
|
129
|
+
end
|
103
130
|
end
|
131
|
+
|
132
|
+
nil
|
104
133
|
end
|
105
134
|
|
106
135
|
def update_fixture_files(named_new_fixtures)
|
@@ -113,13 +142,11 @@ module FixtureFarm
|
|
113
142
|
end
|
114
143
|
|
115
144
|
if belongs_to_association
|
116
|
-
associated_model_instance =
|
145
|
+
associated_model_instance = find_associated_model_instance(model_instance, belongs_to_association)
|
117
146
|
|
118
|
-
|
119
|
-
fixture_model.id == associated_model_instance.id
|
120
|
-
end&.first || associated_model_instance.fixture_name
|
147
|
+
next unless associated_model_instance
|
121
148
|
|
122
|
-
[belongs_to_association.name.to_s,
|
149
|
+
[belongs_to_association.name.to_s, fixture_name(associated_model_instance)]
|
123
150
|
elsif model_instance.column_for_attribute(k).type
|
124
151
|
[k, serialize_attributes(v)]
|
125
152
|
end
|
@@ -145,7 +172,7 @@ module FixtureFarm
|
|
145
172
|
# Clear default_scope before finding associated model record.
|
146
173
|
# This, in particular, turns off ActsAsTenant, that otherwise
|
147
174
|
# might return no record if the tenant has changed by this point.
|
148
|
-
def
|
175
|
+
def find_associated_model_instance(model_instance, association)
|
149
176
|
associated_model_class = if association.polymorphic?
|
150
177
|
model_instance.public_send(association.foreign_type).safe_constantize
|
151
178
|
else
|
@@ -154,6 +181,11 @@ module FixtureFarm
|
|
154
181
|
|
155
182
|
id = model_instance.public_send(association.foreign_key)
|
156
183
|
associated_model_class.unscoped.find(id)
|
184
|
+
rescue ActiveRecord::RecordNotFound
|
185
|
+
# In case of `belongs_to optional: true`, the associated record
|
186
|
+
# may have already been deleted by the time we record fixtures.
|
187
|
+
# We don't want to fail in this case.
|
188
|
+
nil
|
157
189
|
end
|
158
190
|
|
159
191
|
def serialize_attributes(value)
|
@@ -231,5 +263,11 @@ module FixtureFarm
|
|
231
263
|
end
|
232
264
|
end.except(:value_rest)
|
233
265
|
end
|
266
|
+
|
267
|
+
def fixture_name(model_instance)
|
268
|
+
named_new_fixtures.find do |_, fixture_model|
|
269
|
+
fixture_model.id == model_instance.id
|
270
|
+
end&.first || model_instance.fixture_name
|
271
|
+
end
|
234
272
|
end
|
235
273
|
end
|
@@ -4,7 +4,7 @@ require "fixture_farm/fixture_recorder"
|
|
4
4
|
|
5
5
|
module FixtureFarm
|
6
6
|
module TestHelper
|
7
|
-
def record_new_fixtures(fixture_name_prefix, &block)
|
7
|
+
def record_new_fixtures(fixture_name_prefix = nil, &block)
|
8
8
|
FixtureRecorder.new(fixture_name_prefix).record_new_fixtures(&block)
|
9
9
|
end
|
10
10
|
end
|
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: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- artemave
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2025-03-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -24,7 +24,7 @@ dependencies:
|
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '6.2'
|
27
|
-
description:
|
27
|
+
description:
|
28
28
|
email:
|
29
29
|
- mr@artem.rocks
|
30
30
|
executables:
|
@@ -52,7 +52,7 @@ licenses:
|
|
52
52
|
metadata:
|
53
53
|
homepage_uri: https://github.com/featurist/fixture_farm
|
54
54
|
source_code_uri: https://github.com/featurist/fixture_farm.git
|
55
|
-
post_install_message:
|
55
|
+
post_install_message:
|
56
56
|
rdoc_options: []
|
57
57
|
require_paths:
|
58
58
|
- lib
|
@@ -67,8 +67,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
69
|
requirements: []
|
70
|
-
rubygems_version: 3.
|
71
|
-
signing_key:
|
70
|
+
rubygems_version: 3.5.22
|
71
|
+
signing_key:
|
72
72
|
specification_version: 4
|
73
73
|
summary: Generate rails fixutures while browsing
|
74
74
|
test_files: []
|