fixture_record 0.1.2.pre.rc → 1.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 +15 -15
- data/lib/fixture_record/association_traversal.rb +1 -1
- data/lib/fixture_record/belongs_to_updation.rb +1 -1
- data/lib/fixture_record/cache.rb +3 -3
- data/lib/fixture_record/data.rb +6 -2
- data/lib/fixture_record/filterable_attributes.rb +1 -1
- data/lib/fixture_record/naming.rb +1 -1
- data/lib/fixture_record/sanitizable.rb +1 -1
- data/lib/fixture_record/version.rb +1 -1
- data/lib/fixture_record.rb +17 -6
- data/lib/generators/fixture_record/install/install_generator.rb +1 -11
- data/lib/generators/fixture_record/install/templates/initializer.rb +20 -13
- metadata +2 -3
- data/lib/fixture_record/configuration.rb +0 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 725ff327350c904ec886ba1833e976a798e47d564aac8539dec6f2614d86f298
|
4
|
+
data.tar.gz: d820511bb21ee20a76c5e12109030e56bde60e3eab69c100248285d59dbb9047
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 14a8530fe32a301bdc5bc4182da67fd8751823d0d43f3d9cd708e23a4c2d99c9b292f77c47043d1ddb79b4eb75f0326382f59425b37d3986e5143328a8ebd046
|
7
|
+
data.tar.gz: 90bf683053f43a2e0f7f73acb7b6a260ac2ae6748fbffb197fefc7c6fb5cdf1c7d0e6822baa558cdba82f4fbc7a7ab587882d841566a5833d5bcfb10fe379c80
|
data/README.md
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
# FixtureRecord
|
2
|
-
When it comes to testing, ActiveRecrod::Fixtures provide a huge performance benefit over FactoryBot but at the expense of setting up the necessary test data. For complex associations and relationships, a large amount of time might be spent simply trying to setup the data. FixtureRecord provides a `
|
2
|
+
When it comes to testing, ActiveRecrod::Fixtures provide a huge performance benefit over FactoryBot but at the expense of setting up the necessary test data. For complex associations and relationships, a large amount of time might be spent simply trying to setup the data. FixtureRecord provides a `to_fixture_record` method that accepts a chain of associations as an argument that allows you to quickly turn a large collection of existing records into test fixtures.
|
3
3
|
|
4
4
|
## Usage
|
5
|
-
`
|
5
|
+
`to_fixture_record` is a method that will turn the record into a test fixture. By default, the name of the fixture record will be `param_key` of the record's class and the record's id joined with `_`.
|
6
6
|
|
7
7
|
```ruby
|
8
8
|
user = User.find(1)
|
9
|
-
user.
|
9
|
+
user.to_fixture_record
|
10
10
|
|
11
11
|
# creates test/fixtures/users.yml if it does not exists
|
12
12
|
```
|
@@ -41,7 +41,7 @@ Let's say an edge case bug has been found with a particular post and it's relate
|
|
41
41
|
|
42
42
|
```ruby
|
43
43
|
edge_case_post = Post.find ...
|
44
|
-
edge_case_post.
|
44
|
+
edge_case_post.to_fixture_record(:author, comments: :user)
|
45
45
|
```
|
46
46
|
This would create a test fixture for the post, its author, all the comments on the post and their respective users. This will also change the `belongs_to` relationships in the yaml files to reflect their respective fixture counterparts. For example, if `Post#12` author is `User#49`,
|
47
47
|
and the post has `Comment#27` the fixture records might look like:
|
@@ -63,7 +63,7 @@ comment_27:
|
|
63
63
|
commentable: post_12 (Post)
|
64
64
|
```
|
65
65
|
|
66
|
-
Note that these changes to the `belongs_to` associations is only applicable to records that are part of the associations that are being passed into `
|
66
|
+
Note that these changes to the `belongs_to` associations is only applicable to records that are part of the associations that are being passed into `to_fixture_record`. So taking the same example as above, `edge_case_post.to_fixture_record` would yield the following:
|
67
67
|
```yaml
|
68
68
|
post_12:
|
69
69
|
author_id: 49
|
@@ -71,8 +71,8 @@ post_12:
|
|
71
71
|
|
72
72
|
Currently, `FixtureRecord` will also not attempt to already existing fixtures to newly created data.
|
73
73
|
```ruby
|
74
|
-
User.find(49).
|
75
|
-
Post.find(12).
|
74
|
+
User.find(49).to_fixture_record
|
75
|
+
Post.find(12).to_fixture_record
|
76
76
|
```
|
77
77
|
The above would yield fixtures that are not associated to one another.
|
78
78
|
```yaml
|
@@ -97,19 +97,19 @@ end
|
|
97
97
|
```
|
98
98
|
Because of through association infilling the following 3 lines will produce identical results:
|
99
99
|
```ruby
|
100
|
-
user.
|
100
|
+
user.to_fixture_record(posts: [comments: :users])
|
101
101
|
|
102
|
-
user.
|
102
|
+
user.to_fixture_record(:posts, :post_comments, :commenting_users)
|
103
103
|
|
104
104
|
user.to_test_fixutre(:commenting_users)
|
105
105
|
```
|
106
106
|
The reason the third example will infill the other associations is because those associations are required to create a clear path between the originating record and the final records. Without those intermediary associations, the `:commenting_users` would be orphaned from the `user` record.
|
107
107
|
|
108
108
|
### FixtureRecord::Naming
|
109
|
-
There might be instances where a record was used for a particular test fixture and you want to use this same record again for a different test case but want to keep the data isolated. `FixtureRecord::Naming` (automatically included with FixtureRecord) provides`fixture_record_prefix` and `fixture_record_suffix`. These values are propagated to the associated records when calling `
|
109
|
+
There might be instances where a record was used for a particular test fixture and you want to use this same record again for a different test case but want to keep the data isolated. `FixtureRecord::Naming` (automatically included with FixtureRecord) provides`fixture_record_prefix` and `fixture_record_suffix`. These values are propagated to the associated records when calling `to_fixture_record`.
|
110
110
|
```ruby
|
111
111
|
user.test_fixture_prefix = :foo
|
112
|
-
user.
|
112
|
+
user.to_fixture_record(:posts)
|
113
113
|
|
114
114
|
# users.yml
|
115
115
|
|
@@ -158,7 +158,7 @@ end
|
|
158
158
|
FixtureRecord.configure do |config|
|
159
159
|
...
|
160
160
|
|
161
|
-
config.
|
161
|
+
config.sanitize_column_regex /created_at$|updated_at$/, with: :simple_timestamp
|
162
162
|
|
163
163
|
...
|
164
164
|
end
|
@@ -186,13 +186,13 @@ end
|
|
186
186
|
FixtureRecord.registry.register_sanitizer MyReverseSanitizer, :reverse
|
187
187
|
```
|
188
188
|
### Assiging the Sanitizer to a Pattern
|
189
|
-
In the fixture record initializer, use `#
|
189
|
+
In the fixture record initializer, use `#sanitize_column_regex` to assign the registered sanitizer to a regex pattern. In the following example code, any column that matches `email` would be sent through the reverse sanitizer, this would include `email`, `user_email`, `primary_email`, etc.
|
190
190
|
```ruby
|
191
191
|
# fixture_record/initializer.rb
|
192
192
|
FixtureRecord.configure do |config|
|
193
193
|
...
|
194
194
|
|
195
|
-
config.
|
195
|
+
config.sanitize_column_regex /email/, with: :reverse
|
196
196
|
|
197
197
|
...
|
198
198
|
end
|
@@ -200,7 +200,7 @@ end
|
|
200
200
|
|
201
201
|
The pattern that is used for comparison is inclusive of the class name as well. So if you need a sanitizer to be scoped to a specific class you can use the class name in the regex pattern. Taking the example above:
|
202
202
|
```ruby
|
203
|
-
config.
|
203
|
+
config.sanitize_column_regex /User.email/, with: :reverse
|
204
204
|
```
|
205
205
|
Now columns on other classes that include `email` in their name won't be passed to the sanitizer. Also keep in mind the mechanism being used here is basic regex pattern matching, so `User.primary_email` wouldn't match in this case and would not be sent to the sanitizer.
|
206
206
|
|
@@ -52,7 +52,7 @@ module FixtureRecord
|
|
52
52
|
built_records.each do |record|
|
53
53
|
record.fixture_record_prefix = @source_record.fixture_record_prefix
|
54
54
|
record.fixture_record_suffix = @source_record.fixture_record_suffix
|
55
|
-
record.
|
55
|
+
record.to_fixture_record(*@next_associations)
|
56
56
|
end
|
57
57
|
end
|
58
58
|
|
@@ -2,7 +2,7 @@ module FixtureRecord
|
|
2
2
|
module BelongsToUpdation
|
3
3
|
extend ActiveSupport::Concern
|
4
4
|
|
5
|
-
def
|
5
|
+
def update_belongs_to_fixture_record_associations
|
6
6
|
self.class.reflect_on_all_associations(:belongs_to).each do |assoc|
|
7
7
|
klass_name = assoc.options[:polymorphic] ? send(assoc.foreign_type) : assoc.class_name
|
8
8
|
next unless klass_name.nil? || FixtureRecord.cache.contains_class?(klass_name)
|
data/lib/fixture_record/cache.rb
CHANGED
@@ -24,9 +24,9 @@ module FixtureRecord
|
|
24
24
|
|
25
25
|
def prepare!
|
26
26
|
self.values
|
27
|
-
.each(&:
|
28
|
-
.each(&:
|
29
|
-
.each(&:
|
27
|
+
.each(&:filter_attributes_for_fxiture_record)
|
28
|
+
.each(&:sanitize_attributes_for_fxiture_record)
|
29
|
+
.each(&:update_belongs_to_fixture_record_associations)
|
30
30
|
end
|
31
31
|
end
|
32
32
|
end
|
data/lib/fixture_record/data.rb
CHANGED
@@ -14,14 +14,18 @@ class FixtureRecord::Data < Hash
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def write!
|
17
|
-
FileUtils.mkdir_p(
|
17
|
+
FileUtils.mkdir_p(FixtureRecord.base_path)
|
18
18
|
self.each do |klass, data|
|
19
19
|
File.open(fixture_path_for(klass), 'w') { |f| f.write data.to_yaml }
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
23
|
def fixture_path_for(klass)
|
24
|
-
|
24
|
+
if FixtureRecord.base_path.is_a?(String)
|
25
|
+
[FixtureRecord.base_path, klass.table_name + '.yml'].join('/')
|
26
|
+
else
|
27
|
+
FixtureRecord.base_path.join(klass.table_name + '.yml')
|
28
|
+
end
|
25
29
|
end
|
26
30
|
|
27
31
|
def merge_record(record)
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module FixtureRecord::Sanitizable
|
2
2
|
extend ActiveSupport::Concern
|
3
3
|
|
4
|
-
def
|
4
|
+
def sanitize_attributes_for_fxiture_record
|
5
5
|
_fixture_record_attributes.each do |attr, value|
|
6
6
|
registry_key = [self.class.name, attr.to_s].join('.')
|
7
7
|
_fixture_record_attributes[attr] = sanitize_value_for_test_fixture(registry_key, value)
|
data/lib/fixture_record.rb
CHANGED
@@ -7,7 +7,6 @@ require "fixture_record/association_traversal"
|
|
7
7
|
require "fixture_record/filterable_attributes"
|
8
8
|
require "fixture_record/belongs_to_updation"
|
9
9
|
require "fixture_record/sanitizable"
|
10
|
-
require "fixture_record/configuration"
|
11
10
|
|
12
11
|
module FixtureRecord
|
13
12
|
extend ActiveSupport::Concern
|
@@ -15,7 +14,9 @@ module FixtureRecord
|
|
15
14
|
:cache,
|
16
15
|
:data
|
17
16
|
|
18
|
-
mattr_accessor :
|
17
|
+
mattr_accessor :name_handler, default: FixtureRecord::Naming::Base.new
|
18
|
+
mattr_accessor :sanitizers, default: []
|
19
|
+
mattr_accessor :base_path, default: -> { Rails.root.join('test/fixtures') }
|
19
20
|
|
20
21
|
included do
|
21
22
|
attr_accessor :_fixture_record_attributes
|
@@ -29,7 +30,7 @@ module FixtureRecord
|
|
29
30
|
|
30
31
|
Sanitizer = FixtureRecord::Sanitizable::Base
|
31
32
|
|
32
|
-
def
|
33
|
+
def to_fixture_record(*associations)
|
33
34
|
FixtureRecord.lock!(self)
|
34
35
|
FixtureRecord.cache[self.test_fixture_name] ||= self
|
35
36
|
traverse_fixture_record_associations(*associations)
|
@@ -41,13 +42,23 @@ module FixtureRecord
|
|
41
42
|
|
42
43
|
class << self
|
43
44
|
def configure
|
44
|
-
yield
|
45
|
+
yield self
|
45
46
|
end
|
46
47
|
|
47
|
-
def
|
48
|
-
@@
|
48
|
+
def base_path
|
49
|
+
@@base_path.is_a?(String) ? @@base_path : @@base_path.call
|
49
50
|
end
|
50
51
|
|
52
|
+
def name_handler=(proc_or_klass)
|
53
|
+
@@name_handler = proc_or_klass.is_a?(Class) ? proc_or_klass.new : proc_or_klass
|
54
|
+
end
|
55
|
+
|
56
|
+
def sanitize_column_regex(col_regex, with:)
|
57
|
+
registry_name_or_klass = with
|
58
|
+
klass = registry_name_or_klass.is_a?(Symbol) ? FixtureRecord.registry[registry_name_or_klass] : registry_name_or_klass
|
59
|
+
klass_instance = klass.is_a?(Class) ? klass.new : klass
|
60
|
+
FixtureRecord.registry.sanitize_pattern col_regex, with: klass_instance
|
61
|
+
end
|
51
62
|
|
52
63
|
def lock!(owner)
|
53
64
|
return if locked?
|
@@ -5,17 +5,7 @@ module FixtureRecord::Generators
|
|
5
5
|
source_root File.expand_path("templates", __dir__)
|
6
6
|
|
7
7
|
def create_initializer
|
8
|
-
|
9
|
-
<<-TXT
|
10
|
-
# By default, fixture_record will only inject itself in the development environment.
|
11
|
-
# If you want it available in `test` or `production` (or other environments), please add
|
12
|
-
# this require line to those environment ruby files. Alternatively, if you want it to
|
13
|
-
# always be loaded, you can relocate the generated `fixture_record/initializer.rb` to
|
14
|
-
# `app/config/initializers/fixture_record.rb` or require this file in `config/application.rb`.
|
15
|
-
require Rails.root.join('fixture_record', 'initializer.rb')\n
|
16
|
-
TXT
|
17
|
-
end
|
18
|
-
template "initializer.rb", Rails.root.join("fixture_record/initializer.rb")
|
8
|
+
template "initializer.rb", Rails.root.join("config/initializers/fixture_record.rb")
|
19
9
|
end
|
20
10
|
end
|
21
11
|
end
|
@@ -1,16 +1,23 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
if Rails.env.development?
|
2
|
+
FixtureRecord.configure do |config|
|
3
|
+
# To customize how fixtures are named, provide a class the responds to #call or a Proc.
|
4
|
+
# The name handler object will receive the record and should return a String
|
5
|
+
# config.name_handler = FixtureRecord::Naming::Base
|
5
6
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
# would sanitize the phone_number field for a User but not the phone_number field for a Customer.
|
11
|
-
# If there are other timestamp columns being used throughout your application, you can added them to this list.
|
12
|
-
config.sanitize_pattern /created_at$|updated_at$/, with: :simple_timestamp
|
7
|
+
# base_path represents the base folder that FixureRecord will search for existing yml files
|
8
|
+
# to merge new fixture data with and it serves as the path for where FixtureRecord will output the
|
9
|
+
# new yml files as needed. To override, provide a String, Pathname object, or Proc/ambda to be evaluated at runtime
|
10
|
+
# config.base_path = -> { Rails.root.join('test/fixtures') }
|
13
11
|
|
14
|
-
|
15
|
-
|
12
|
+
# Create and register custom sanitizers to format, sanitiize, obfuscate, etc. the data before it is
|
13
|
+
# turned into a test fixture. Regex patterns are used to determine if a column should be passed to a
|
14
|
+
# sanitizer. The regex pattern that is tested is Classname.column_name - so if a sanitizer needs to be
|
15
|
+
# scoped to a specific class only, simply add the classname to the pattern, for example /User.phone_number/
|
16
|
+
# would sanitize the phone_number field for a User but not the phone_number field for a Customer.
|
17
|
+
# If there are other timestamp columns being used throughout your application, you can added them to this list.
|
18
|
+
config.sanitize_column_regex /created_at$|updated_at$/, with: :simple_timestamp
|
19
|
+
|
20
|
+
# Inject FixtureRecord concern into ActiveRecord
|
21
|
+
ActiveRecord::Base.include(FixtureRecord)
|
22
|
+
end
|
16
23
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fixture_record
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: '1.0'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brad Schrag
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-04-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -39,7 +39,6 @@ files:
|
|
39
39
|
- lib/fixture_record/association_traversal.rb
|
40
40
|
- lib/fixture_record/belongs_to_updation.rb
|
41
41
|
- lib/fixture_record/cache.rb
|
42
|
-
- lib/fixture_record/configuration.rb
|
43
42
|
- lib/fixture_record/data.rb
|
44
43
|
- lib/fixture_record/filterable_attributes.rb
|
45
44
|
- lib/fixture_record/naming.rb
|
@@ -1,14 +0,0 @@
|
|
1
|
-
module FixtureRecord
|
2
|
-
class Configuration
|
3
|
-
def name_records_with(proc_or_klass)
|
4
|
-
FixtureRecord.naming = proc_or_klass.is_a?(Class) ? proc_or_klass.new : proc_or_klass
|
5
|
-
end
|
6
|
-
|
7
|
-
def sanitize_pattern(pattern, with:)
|
8
|
-
registry_name_or_klass = with
|
9
|
-
klass = registry_name_or_klass.is_a?(Symbol) ? FixtureRecord.registry[registry_name_or_klass] : registry_name_or_klass
|
10
|
-
klass_instance = klass.is_a?(Class) ? klass.new : klass
|
11
|
-
FixtureRecord.registry.sanitize_pattern pattern, with: klass_instance
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|