factory_bot-with 0.1.0 → 0.2.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/CHANGELOG.md +9 -0
- data/README.md +13 -0
- data/lib/factory_bot/with/assoc_info.rb +4 -2
- data/lib/factory_bot/with/methods.rb +1 -8
- data/lib/factory_bot/with/version.rb +1 -1
- data/lib/factory_bot/with.rb +69 -26
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: abe0a558801602a366eb21e5aacf753e8cb3fb75a2e45b6df492308c4244d85f
|
4
|
+
data.tar.gz: 514e5d0190f7dfa9cd0744062217a99c2ba5964be8f2bcf2fa64864044a84465
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8243dd0f2ea730d9266964806a48934856254b2ecd1f73bf839f19198e2540061c373a8778413ddcfcc5a68aface18cd3debfa9ae0b5f8b1f8416a1ed2459d98
|
7
|
+
data.tar.gz: 78031d8c55fef101fb7cf9c5511beeae3374813faa62f5925deb3ed70a80872e01baf1c127192d694f1a7546f10e1156534408a91fb61e8e39d5e6830b4d320a
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,14 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [0.2.1] - 2024-11-29
|
4
|
+
|
5
|
+
- Fixed: Adjusted priority of factory names autocompletion
|
6
|
+
|
7
|
+
## [0.2.0] - 2024-11-29
|
8
|
+
|
9
|
+
- Fixed: Fixed an incorrect factory resolution problem after factory names autocompletion
|
10
|
+
- Added: Smarter interpretation of positional arguments passed to factory methods
|
11
|
+
|
3
12
|
## [0.1.0] - 2024-11-27
|
4
13
|
|
5
14
|
- Initial release
|
data/README.md
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
# FactoryBot::With
|
2
2
|
|
3
|
+
[](https://badge.fury.io/rb/factory_bot-with)
|
4
|
+
[](https://github.com/yubrot/factory_bot-with/actions/workflows/main.yml)
|
5
|
+
|
3
6
|
FactoryBot::With is a FactoryBot extension that wraps `FactoryBot::Syntax::Methods` to make it a little easier to use.
|
4
7
|
|
5
8
|
For example, with these factories:
|
@@ -68,6 +71,16 @@ build_stubbed.foo(...)
|
|
68
71
|
create_list.foo(10, ...)
|
69
72
|
```
|
70
73
|
|
74
|
+
### Smarter interpretation of positional arguments
|
75
|
+
|
76
|
+
FactoryBot::With adjusts the behavior of factory methods to accept `Hash`, `Array`, and falsy values (`false` or `nil`) as positional arguments.
|
77
|
+
|
78
|
+
```ruby
|
79
|
+
create.foo({ title: "Recipe" }, is_new && %i[latest hot])
|
80
|
+
#=> create(:foo, :latest, :hot, title: "Recipe") if is_new
|
81
|
+
# create(:foo, title: "Recipe") otherwise
|
82
|
+
```
|
83
|
+
|
71
84
|
### `with`, `with_pair`, and `with_list` operator
|
72
85
|
|
73
86
|
FactoryBot::With provides a new operator `with` (and its family).
|
@@ -46,8 +46,6 @@ module FactoryBot
|
|
46
46
|
# @param partial_factory_name [Symbol]
|
47
47
|
# @return [Symbol]
|
48
48
|
def autocomplete_fully_qualified_factory_name(ancestors, partial_factory_name)
|
49
|
-
return partial_factory_name if exists?(partial_factory_name)
|
50
|
-
|
51
49
|
ancestors.each do |(ancestor_assoc_info, _)|
|
52
50
|
ancestor_assoc_info.factory_names.each do |ancestor_factory_name|
|
53
51
|
factory_name = :"#{ancestor_factory_name}_#{partial_factory_name}"
|
@@ -55,6 +53,10 @@ module FactoryBot
|
|
55
53
|
end
|
56
54
|
end
|
57
55
|
|
56
|
+
# Attempt to resolve with the autocompleted names, then attempt to resolve with the original name.
|
57
|
+
# If we want to avoid autocompletion, we should be able to simply use a factory such as build or create.
|
58
|
+
return partial_factory_name if exists?(partial_factory_name)
|
59
|
+
|
58
60
|
raise ArgumentError, "FactoryBot factory #{partial_factory_name} is not defined"
|
59
61
|
end
|
60
62
|
|
@@ -18,14 +18,7 @@ module FactoryBot
|
|
18
18
|
define_method(method_name) do |factory = nil, *args, **kwargs, &block|
|
19
19
|
return Proxy.new(self, __method__) unless factory
|
20
20
|
|
21
|
-
|
22
|
-
if factory.is_a? With
|
23
|
-
factory.merge(With.new(variation, factory.factory_name, *args, **kwargs, &block))
|
24
|
-
else
|
25
|
-
With.new(variation, factory, *args, **kwargs, &block)
|
26
|
-
end
|
27
|
-
|
28
|
-
with.instantiate(build_strategy)
|
21
|
+
With.build(variation, factory, *args, **kwargs, &block).instantiate(build_strategy)
|
29
22
|
end
|
30
23
|
end
|
31
24
|
end
|
data/lib/factory_bot/with.rb
CHANGED
@@ -15,25 +15,32 @@ module FactoryBot
|
|
15
15
|
attr_reader :factory_name
|
16
16
|
# @return [Array<With>]
|
17
17
|
attr_reader :withes
|
18
|
-
# @return [Array<
|
19
|
-
attr_reader :
|
18
|
+
# @return [Array<Numeric, Symbol>] Numeric is also treated as a trait for convenience
|
19
|
+
attr_reader :traits
|
20
20
|
# @return [{Symbol => Object}]
|
21
|
-
attr_reader :
|
21
|
+
attr_reader :attrs
|
22
22
|
# @return [Proc, nil]
|
23
23
|
attr_reader :block
|
24
24
|
|
25
25
|
# @!visibility private
|
26
|
-
def initialize(variation, factory_name,
|
26
|
+
def initialize(variation, factory_name, withes: [], traits: [], attrs: {}, &block)
|
27
|
+
raise ArgumentError unless %i[unit pair list].include? variation
|
28
|
+
raise TypeError unless factory_name.is_a? Symbol
|
29
|
+
raise TypeError unless withes.is_a?(Array) && withes.all? { _1.is_a? self.class }
|
30
|
+
raise TypeError unless traits.is_a?(Array) && traits.all? { _1.is_a?(Symbol) || _1.is_a?(Numeric) }
|
31
|
+
raise TypeError unless attrs.is_a?(Hash) && attrs.keys.all? { _1.is_a? Symbol }
|
32
|
+
|
27
33
|
@variation = variation
|
28
34
|
@factory_name = factory_name
|
29
|
-
@withes
|
30
|
-
@
|
35
|
+
@withes = withes
|
36
|
+
@traits = traits
|
37
|
+
@attrs = attrs
|
31
38
|
@block = block
|
32
39
|
end
|
33
40
|
|
34
41
|
# @!visibility private
|
35
42
|
# @return [Boolean]
|
36
|
-
def plain? = withes.empty? &&
|
43
|
+
def plain? = withes.empty? && traits.empty? && attrs.empty? && block.nil?
|
37
44
|
|
38
45
|
# @!visibility private
|
39
46
|
# @param other [With]
|
@@ -49,8 +56,9 @@ module FactoryBot
|
|
49
56
|
self.class.new(
|
50
57
|
variation,
|
51
58
|
factory_name,
|
52
|
-
|
53
|
-
|
59
|
+
withes: [*withes, *other.withes],
|
60
|
+
traits: [*traits, *other.traits],
|
61
|
+
attrs: { **attrs, **other.attrs },
|
54
62
|
&self.class.merge_block(block, other.block)
|
55
63
|
)
|
56
64
|
end
|
@@ -63,20 +71,20 @@ module FactoryBot
|
|
63
71
|
return self if build_strategy == :with
|
64
72
|
|
65
73
|
factory_bot_method = Methods::VARIATIONS[variation][build_strategy]
|
66
|
-
factory_name,
|
74
|
+
factory_name, attrs =
|
67
75
|
if ancestors
|
68
|
-
|
76
|
+
attrs = @attrs.dup
|
69
77
|
factory_name = AssocInfo.autocomplete_fully_qualified_factory_name(ancestors, @factory_name)
|
70
|
-
AssocInfo.get(factory_name).perform_automatic_association_resolution(ancestors,
|
71
|
-
[factory_name,
|
78
|
+
AssocInfo.get(factory_name).perform_automatic_association_resolution(ancestors, attrs)
|
79
|
+
[factory_name, attrs]
|
72
80
|
else
|
73
|
-
[@factory_name, @
|
81
|
+
[@factory_name, @attrs]
|
74
82
|
end
|
75
|
-
result = FactoryBot.__send__(factory_bot_method, factory_name, *
|
83
|
+
result = FactoryBot.__send__(factory_bot_method, factory_name, *traits, **attrs, &block)
|
76
84
|
|
77
85
|
unless withes.empty?
|
78
86
|
parents = variation == :unit ? [result] : result
|
79
|
-
assoc_info = AssocInfo.get(
|
87
|
+
assoc_info = AssocInfo.get(factory_name)
|
80
88
|
parents.each do |parent|
|
81
89
|
ancestors_for_children = [[assoc_info, parent], *ancestors || []]
|
82
90
|
withes.each { _1.instantiate(build_strategy, ancestors_for_children) }
|
@@ -86,17 +94,52 @@ module FactoryBot
|
|
86
94
|
result
|
87
95
|
end
|
88
96
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
97
|
+
class << self
|
98
|
+
# @!visibility private
|
99
|
+
# @param variation [:unit, :pair, :list]
|
100
|
+
# @param factory [Symbol, With]
|
101
|
+
# @param args [Array<Object>]
|
102
|
+
# @param kwargs [{Symbol => Object}]
|
103
|
+
def build(variation, factory, *, **, &)
|
104
|
+
return factory.merge(build(variation, factory.factory_name, *, **, &)) if factory.is_a? self
|
105
|
+
|
106
|
+
with = new(variation, factory, &)
|
107
|
+
insert_args!(with, *)
|
108
|
+
with.attrs.merge!(**)
|
109
|
+
with
|
110
|
+
end
|
96
111
|
|
97
|
-
|
98
|
-
|
99
|
-
|
112
|
+
def insert_args!(with, *args)
|
113
|
+
args.each do |arg|
|
114
|
+
case arg
|
115
|
+
when self
|
116
|
+
with.withes << arg
|
117
|
+
when Symbol, Numeric
|
118
|
+
with.traits << arg
|
119
|
+
when Array
|
120
|
+
insert_args!(with, *arg)
|
121
|
+
when Hash
|
122
|
+
with.attrs.merge!(arg)
|
123
|
+
when false, nil
|
124
|
+
# Ignored. This behavior is useful for conditional arguments like `is_premium && :premium`
|
125
|
+
else
|
126
|
+
raise ArgumentError, "Unsupported type for factory argument: #{arg}"
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
# @!visibility private
|
132
|
+
# @param first [Proc, nil]
|
133
|
+
# @param second [Proc, nil]
|
134
|
+
# @return [Proc, nil]
|
135
|
+
def merge_block(first, second)
|
136
|
+
return first unless second
|
137
|
+
return second unless first
|
138
|
+
|
139
|
+
lambda do |*args|
|
140
|
+
first.call(*args)
|
141
|
+
second.call(*args)
|
142
|
+
end
|
100
143
|
end
|
101
144
|
end
|
102
145
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: factory_bot-with
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- yubrot
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-11-
|
11
|
+
date: 2024-11-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: factory_bot
|
@@ -67,7 +67,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
69
|
requirements: []
|
70
|
-
rubygems_version: 3.5.
|
70
|
+
rubygems_version: 3.5.22
|
71
71
|
signing_key:
|
72
72
|
specification_version: 4
|
73
73
|
summary: FactoryBot extension that wraps FactoryBot::Syntax::Methods to make it a
|