fixture_record 0.1.2.pre.rc → 1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|