factory_bot-blueprint 0.3.0 → 0.5.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cbfd3f2bba8aa92e21a6e375970c77d48e6634cef9cf39085f5e2648f5415b37
4
- data.tar.gz: 55177d1b09287b9b0857614700410db2109333c05b4f5d624028ce15eaa06988
3
+ metadata.gz: e01f7a2b8a4f8b2940edd4c7793e941274356fe21fc294acb3afd27c1eacab73
4
+ data.tar.gz: b57c70a58ea87edbc8d9a66d6a87b16c63051d5d12eec86ce02c26b6ec1339bc
5
5
  SHA512:
6
- metadata.gz: b4a37fb4bfd61893df1a4301244fd0d3f1bf4c55d4ed3962e62bccfc541a94df9f6b5164fdfc5bfecacd8d6bc42094b21b55c46ae17c59ce0242f573be6ded35
7
- data.tar.gz: 78519c9aff90307fc68485847bd7c76bbe635ef1d08c154c596ea1b683f3c9dea4ad4f9e830356fb652f2ae6b29061f84fdb1a4fbb8a56cb280854602f1e64fb
6
+ metadata.gz: 3e07e0eb13aa6098f34e280b88eeaa4db272432965084da60bd135c481523fadae22edf1bd1678224376ed9ff89b646c3c859f31083e7f05b9b4443a0690e00d
7
+ data.tar.gz: df80db74e368bea0faa790160ac1d7597163ad45e460bbaa1979d00af5a408fede439efa01dd755387799286031a577459210a8a51662ee59e2f1a9d45d0d02f
@@ -2,7 +2,7 @@
2
2
 
3
3
  module FactoryBot
4
4
  module Blueprint
5
- # A declarative DSL for building {Factrey::Blueprint}.
5
+ # A declarative DSL for building {https://rubydoc.info/gems/factrey/Factrey/Blueprint Factrey::Blueprint}.
6
6
  # This DSL automatically recognizes factories defined in FactoryBot as types.
7
7
  class DSL < Factrey::DSL
8
8
  # Internals:
@@ -10,16 +10,38 @@ module FactoryBot
10
10
  # We would like to minimize these dependencies as much as possible.
11
11
 
12
12
  # @!visibility private
13
- def respond_to_missing?(type_name, _)
14
- FactoryBot.factories.registered? type_name
13
+ def respond_to_missing?(name, _)
14
+ _autocompleted_method_names(name).any? do |method_name|
15
+ self.class.method_defined?(method_name) || FactoryBot.factories.registered?(method_name)
16
+ end
17
+ end
18
+
19
+ def method_missing(name, ...)
20
+ _autocompleted_method_names(name).each do |method_name|
21
+ if self.class.method_defined?(method_name)
22
+ return __send__(method_name, ...)
23
+ elsif FactoryBot.factories.registered?(method_name)
24
+ factory = FactoryBot.factories.find(method_name)
25
+ self.class.add_type(self.class.type_from_factory_bot_factory(method_name, factory))
26
+ return __send__(method_name, ...)
27
+ end
28
+ end
29
+
30
+ raise NoMethodError,
31
+ "Undefined method `#{name}' for #{self} and cannot be resolved from FactoryBot factories"
15
32
  end
16
33
 
17
- def method_missing(type_name, ...)
18
- raise NoMethodError, "Unknown type #{type_name}" unless FactoryBot.factories.registered? type_name
34
+ private
35
+
36
+ def _autocompleted_method_names(name)
37
+ return enum_for(__method__, name) unless block_given?
19
38
 
20
- factory = FactoryBot.factories.find(type_name)
21
- self.class.add_type(self.class.type_from_factory_bot_factory(type_name, factory))
22
- __send__(type_name, ...)
39
+ @ancestors.reverse_each do |ancestor|
40
+ ancestor.type.compatible_types.each do |ancestor_type|
41
+ yield :"#{ancestor_type}_#{name}"
42
+ end
43
+ end
44
+ yield name
23
45
  end
24
46
 
25
47
  class << self
@@ -42,9 +64,9 @@ module FactoryBot
42
64
  Factrey::Blueprint::Type.new(type_name, compatible_types:, auto_references:, &FACTORY)
43
65
  end
44
66
 
45
- FACTORY = lambda { |type, context, *args, **kwargs|
46
- FactoryBot.__send__(context[:strategy], type.name, *args, **kwargs)
47
- }
67
+ FACTORY = lambda do |type, context, *args, **kwargs|
68
+ FactoryBot.__send__(context[:build_strategy], type.name, *args, **kwargs)
69
+ end
48
70
 
49
71
  private_constant :FACTORY
50
72
  end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FactoryBot
4
+ module Blueprint
5
+ # This module provides a shortcut to FactoryBot::Blueprint.
6
+ # @example
7
+ # # Configure the same way as FactoryBot::Syntax::Methods
8
+ # RSpec.configure do |config|
9
+ # config.include FactoryBot::Syntax::Methods
10
+ # config.include FactoryBot::Blueprint::Methods
11
+ # end
12
+ #
13
+ # # You can use `bp` in your spec files
14
+ # RSpec.describe "something" do
15
+ # before do
16
+ # bp.create do
17
+ # blog do
18
+ # article(title: "Article 1")
19
+ # article(title: "Article 2")
20
+ # article(title: "Article 3") do
21
+ # comment(name: "John")
22
+ # comment(name: "Doe")
23
+ # end
24
+ # end
25
+ # end
26
+ # end
27
+ # end
28
+ module Methods
29
+ # @return [Class<FactoryBot::Blueprint>]
30
+ def bp = FactoryBot::Blueprint
31
+ end
32
+ end
33
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module FactoryBot
4
4
  module Blueprint
5
- VERSION = "0.3.0"
5
+ VERSION = "0.5.0"
6
6
  end
7
7
  end
@@ -4,21 +4,25 @@ require "factrey"
4
4
  require "factory_bot"
5
5
  require_relative "blueprint/version"
6
6
  require_relative "blueprint/dsl"
7
+ require_relative "blueprint/methods"
7
8
 
8
9
  module FactoryBot
9
10
  # A FactoryBot extension for building structured objects using a declarative DSL.
10
- # First we can build (or extend) a creation plan for a set of objects as <code>Blueprint</code>,
11
+ # First we can build (or extend) a creation plan for a set of objects as
12
+ # {https://rubydoc.info/gems/factrey/Factrey/Blueprint Factrey::Blueprint},
11
13
  # and then we can create actual objects from it.
12
14
  #
13
- # <code>Blueprint</code>s can be built using a declarative DSL provided by a core library called {Factrey}.
15
+ # <code>Blueprint</code>s can be built using a declarative DSL provided by a core library called <code>Factrey</code>.
14
16
  # Each node declaration in the DSL code is automatically correspond to the FactoryBot's factory. For example,
15
17
  # a declaration <code>user(name: 'John')</code> corresponds to <code>FactoryBot.create(:user, name: 'John')</code>.
16
18
  module Blueprint
17
19
  class << self
18
- # Entry point to build or extend a {Factrey::Blueprint}.
20
+ # Entry point to build or extend a {https://rubydoc.info/gems/factrey/Factrey/Blueprint Factrey::Blueprint}.
19
21
  # @param blueprint [Factrey::Blueprint, nil] to extend an existing blueprint
20
- # @param ext [Object] an external object that can be accessed using {DSL#ext} in the DSL
21
- # @yield Write Blueprint DSL code here. See {Factrey::DSL} methods for DSL details
22
+ # @param ext [Object] an external object that can be accessed using <code>DSL#ext</code> in the DSL
23
+ # @yield
24
+ # Write Blueprint DSL code here. See {https://rubydoc.info/gems/factrey/Factrey/DSL Factrey::DSL} documents for
25
+ # more details
22
26
  # @return [Factrey::Blueprint] the built or extended blueprint
23
27
  # @example
24
28
  # # In this example, we have three factories in FactoryBot:
@@ -40,41 +44,51 @@ module FactoryBot
40
44
  # end
41
45
  # end
42
46
  #
43
- # # Create a set of objects in FactoryBot (with `build` strategy) from the blueprint:
44
- # result, objects = FactoryBot::Blueprint.build(bp)
47
+ # # Create a set of objects in FactoryBot (with `build` build strategy) from the blueprint:
48
+ # objects = FactoryBot::Blueprint.build(bp)
45
49
  #
46
50
  # # This behaves as:
47
51
  # objects = {}
48
52
  # objects[:blog] = blog = FactoryBot.build(:blog)
49
- # objects[gen_random_sym] = FactoryBot.build(:article, title: "Article 1", blog:)
50
- # objects[gen_random_sym] = FactoryBot.build(:article, title: "Article 2", blog:)
51
- # objects[gen_random_sym] = article3 = FactoryBot.build(:article, title: "Article 3", blog:)
52
- # objects[gen_random_sym] = FactoryBot.build(:comment, name: "John", article: article3)
53
- # objects[gen_random_sym] = FactoryBot.build(:comment, name: "Doe", article: article3)
54
- # result = blog
53
+ # objects[random_anon_sym] = FactoryBot.build(:article, title: "Article 1", blog:)
54
+ # objects[random_anon_sym] = FactoryBot.build(:article, title: "Article 2", blog:)
55
+ # objects[random_anon_sym] = article3 = FactoryBot.build(:article, title: "Article 3", blog:)
56
+ # objects[random_anon_sym] = FactoryBot.build(:comment, name: "John", article: article3)
57
+ # objects[random_anon_sym] = FactoryBot.build(:comment, name: "Doe", article: article3)
58
+ # objects[Factrey::Blueprint::Node::RESULT_NAME] = blog
55
59
  def plan(blueprint = nil, ext: nil, &) = Factrey.blueprint(blueprint, ext:, dsl: DSL, &)
56
60
 
57
- # Create a set of objects and compute the result by <code>build</code> strategy in FactoryBot.
61
+ # Create a set of objects by <code>build</code> build strategy in FactoryBot.
58
62
  # See {.plan} for more details.
59
63
  # @param blueprint [Factrey::Blueprint, nil]
60
- # @param ext [Object] an external object that can be accessed using {DSL#ext} in the DSL
64
+ # @param ext [Object] an external object that can be accessed using <code>DSL#ext</code> in the DSL
61
65
  # @yield Write Blueprint DSL code here
62
- # @return [(Object, {Symbol => Object})] the result and the created objects
66
+ # @return [Hash{Symbol => Object}] the created objects
63
67
  def build(blueprint = nil, ext: nil, &) = instantiate(:build, blueprint, ext:, &)
64
68
 
65
- # Create a set of objects and compute the result by <code>create</code> strategy in FactoryBot.
69
+ # Create a set of objects by <code>build_stubbed</code> build strategy in FactoryBot.
66
70
  # See {.plan} for more details.
67
71
  # @param blueprint [Factrey::Blueprint, nil]
68
- # @param ext [Object] an external object that can be accessed using {DSL#ext} in the DSL
72
+ # @param ext [Object] an external object that can be accessed using <code>DSL#ext</code> in the DSL
69
73
  # @yield Write Blueprint DSL code here
70
- # @return [(Object, {Symbol => Object})] the result and the created objects
74
+ # @return [Hash{Symbol => Object}] the created objects
75
+ def build_stubbed(blueprint = nil, ext: nil, &) = instantiate(:build_stubbed, blueprint, ext:, &)
76
+
77
+ # Create a set of objects by <code>create</code> build strategy in FactoryBot.
78
+ # See {.plan} for more details.
79
+ # @param blueprint [Factrey::Blueprint, nil]
80
+ # @param ext [Object] an external object that can be accessed using <code>DSL#ext</code> in the DSL
81
+ # @yield Write Blueprint DSL code here
82
+ # @return [Hash{Symbol => Object}] the created objects
71
83
  def create(blueprint = nil, ext: nil, &) = instantiate(:create, blueprint, ext:, &)
72
84
 
73
85
  # @!visibility private
74
- def instantiate(strategy, blueprint = nil, ext: nil, &)
75
- raise ArgumentError, "Unsupported strategy: #{strategy}" unless %i[create build].include?(strategy)
86
+ def instantiate(build_strategy, blueprint = nil, ext: nil, &)
87
+ unless %i[create build build_stubbed].include?(build_strategy)
88
+ raise ArgumentError, "Unsupported build strategy: #{build_strategy}"
89
+ end
76
90
 
77
- plan(blueprint, ext:, &).instantiate(strategy:)
91
+ plan(blueprint, ext:, &).instantiate(build_strategy:)
78
92
  end
79
93
  end
80
94
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: factory_bot-blueprint
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - yubrot
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-07-30 00:00:00.000000000 Z
11
+ date: 2024-11-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: factory_bot
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 0.3.0
33
+ version: 0.5.0
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 0.3.0
40
+ version: 0.5.0
41
41
  description: |
42
42
  FactoryBot::Blueprint is a FactoryBot extension for building structured objects using a declarative DSL.
43
43
  On the DSL, the factories defined in FactoryBot can be used without any additional configuration.
@@ -51,6 +51,7 @@ files:
51
51
  - README.md
52
52
  - lib/factory_bot/blueprint.rb
53
53
  - lib/factory_bot/blueprint/dsl.rb
54
+ - lib/factory_bot/blueprint/methods.rb
54
55
  - lib/factory_bot/blueprint/version.rb
55
56
  homepage: https://github.com/yubrot/factory_bot-blueprint
56
57
  licenses:
@@ -68,14 +69,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
68
69
  requirements:
69
70
  - - ">="
70
71
  - !ruby/object:Gem::Version
71
- version: 3.1.0
72
+ version: 3.2.0
72
73
  required_rubygems_version: !ruby/object:Gem::Requirement
73
74
  requirements:
74
75
  - - ">="
75
76
  - !ruby/object:Gem::Version
76
77
  version: '0'
77
78
  requirements: []
78
- rubygems_version: 3.5.11
79
+ rubygems_version: 3.5.22
79
80
  signing_key:
80
81
  specification_version: 4
81
82
  summary: FactoryBot extension for building structured objects using a declarative