factory_bot-blueprint 0.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 +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +10 -0
- data/lib/factory_bot/blueprint/dsl.rb +53 -0
- data/lib/factory_bot/blueprint/version.rb +7 -0
- data/lib/factory_bot/blueprint.rb +80 -0
- metadata +83 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 89384db0522f5262709df19f70d39b08af7c7eadd26e252560590e536a83d817
|
4
|
+
data.tar.gz: 2be455b31165be74a8a2fd2f6008d6424287c9aeefbef4b4499d2b061d70d374
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c1b9a4ccf44e9dcef033bcbe83180f3f34b5650f53f033e73d5bb2c157ada4b8fdf10a98e0ec963c585f689c913252cdf5c270be018af4eb72c101f5c1af696a
|
7
|
+
data.tar.gz: 7b16fa3b35e416ae46f7e9db4bebec026a387cb2556ad670e96e6c6c5d2de3168403a39340d50436d19b05d22cc943a1dc78cecef8c4dcec3f7a1f93c5e831be
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2024 yubrot
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
# `factory_bot-blueprint` gem
|
2
|
+
|
3
|
+
This is a part of [FactoryBot::Blueprint](https://github.com/yubrot/factory_bot-blueprint) library.
|
4
|
+
|
5
|
+
FactoryBot::Blueprint is a FactoryBot extension for building structured objects using a declarative DSL.
|
6
|
+
On the DSL, the factories defined in FactoryBot can be used without any additional configuration.
|
7
|
+
|
8
|
+
## License
|
9
|
+
|
10
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module FactoryBot
|
4
|
+
module Blueprint
|
5
|
+
# A declarative DSL for building {Factrey::Blueprint}.
|
6
|
+
# This DSL automatically recognizes factories defined in FactoryBot as types.
|
7
|
+
class DSL < Factrey::DSL
|
8
|
+
# Internals:
|
9
|
+
# Here we rely on some of FactoryBot's internal APIs.
|
10
|
+
# We would like to minimize these dependencies as much as possible.
|
11
|
+
|
12
|
+
# @!visibility private
|
13
|
+
def respond_to_missing?(type_name, _)
|
14
|
+
FactoryBot.factories.registered? type_name
|
15
|
+
end
|
16
|
+
|
17
|
+
def method_missing(type_name, ...)
|
18
|
+
raise NoMethodError, "Unknown type #{type_name}" unless FactoryBot.factories.registered? type_name
|
19
|
+
|
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, ...)
|
23
|
+
end
|
24
|
+
|
25
|
+
class << self
|
26
|
+
# @!visibility private
|
27
|
+
def type_from_factory_bot_factory(type_name, factory)
|
28
|
+
# NOTE: We consider aliases to be incompatible with each other
|
29
|
+
compatible_types = []
|
30
|
+
auto_references = {}
|
31
|
+
|
32
|
+
while factory.is_a?(FactoryBot::Factory)
|
33
|
+
compatible_types << factory.name
|
34
|
+
# Here, we use reverse_each to prioritize the upper association
|
35
|
+
factory.with_traits(factory.defined_traits.map(&:name)).associations.reverse_each do |assoc|
|
36
|
+
auto_references[Array(assoc.factory)[0].to_sym] = assoc.name
|
37
|
+
end
|
38
|
+
|
39
|
+
factory = factory.__send__(:parent)
|
40
|
+
end
|
41
|
+
|
42
|
+
Factrey::Blueprint::Type.new(type_name, compatible_types:, auto_references:, &FACTORY)
|
43
|
+
end
|
44
|
+
|
45
|
+
FACTORY = lambda { |type, context, *args, **kwargs|
|
46
|
+
FactoryBot.__send__(context[:strategy], type.name, *args, **kwargs)
|
47
|
+
}
|
48
|
+
|
49
|
+
private_constant :FACTORY
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "factrey"
|
4
|
+
require "factory_bot"
|
5
|
+
require_relative "blueprint/version"
|
6
|
+
require_relative "blueprint/dsl"
|
7
|
+
|
8
|
+
module FactoryBot
|
9
|
+
# 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
|
+
# and then we can create actual objects from it.
|
12
|
+
#
|
13
|
+
# <code>Blueprint</code>s can be built using a declarative DSL provided by a core library called {Factrey}.
|
14
|
+
# Each node declaration in the DSL code is automatically correspond to the FactoryBot's factory. For example,
|
15
|
+
# a declaration <code>user(name: 'John')</code> corresponds to <code>FactoryBot.create(:user, name: 'John')</code>.
|
16
|
+
module Blueprint
|
17
|
+
class << self
|
18
|
+
# Entry point to build or extend a {Factrey::Blueprint}.
|
19
|
+
# @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
|
+
# @return [Factrey::Blueprint] the built or extended blueprint
|
23
|
+
# @example
|
24
|
+
# # In this example, we have three factories in FactoryBot:
|
25
|
+
# FactoryBot.define do
|
26
|
+
# factory(:blog)
|
27
|
+
# factory(:article) { association :blog }
|
28
|
+
# factory(:comment) { association :article }
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
# bp =
|
32
|
+
# FactoryBot::Blueprint.plan do
|
33
|
+
# let.blog do
|
34
|
+
# article(title: "Article 1")
|
35
|
+
# article(title: "Article 2")
|
36
|
+
# article(title: "Article 3") do
|
37
|
+
# comment(name: "John")
|
38
|
+
# comment(name: "Doe")
|
39
|
+
# end
|
40
|
+
# end
|
41
|
+
# end
|
42
|
+
#
|
43
|
+
# # Create a set of objects in FactoryBot (with `build` strategy) from the blueprint:
|
44
|
+
# instance = FactoryBot::Blueprint.build(bp)
|
45
|
+
#
|
46
|
+
# # This behaves as:
|
47
|
+
# instance = {}
|
48
|
+
# instance[:blog] = blog = FactoryBot.build(:blog)
|
49
|
+
# instance[gen_random_sym] = FactoryBot.build(:article, title: "Article 1", blog:)
|
50
|
+
# instance[gen_random_sym] = FactoryBot.build(:article, title: "Article 2", blog:)
|
51
|
+
# instance[gen_random_sym] = article3 = FactoryBot.build(:article, title: "Article 3", blog:)
|
52
|
+
# instance[gen_random_sym] = FactoryBot.build(:comment, name: "John", article: article3)
|
53
|
+
# instance[gen_random_sym] = FactoryBot.build(:comment, name: "Doe", article: article3)
|
54
|
+
def plan(blueprint = nil, ext: nil, &) = Factrey.blueprint(blueprint, ext:, dsl: DSL, &)
|
55
|
+
|
56
|
+
# Create a set of objects by <code>build</code> strategy in FactoryBot.
|
57
|
+
# See {.plan} for more details.
|
58
|
+
# @param blueprint [Factrey::Blueprint, nil]
|
59
|
+
# @param ext [Object] an external object that can be accessed using {DSL#ext} in the DSL
|
60
|
+
# @yield Write Blueprint DSL code here
|
61
|
+
# @return [Hash{Symbol => Object}]
|
62
|
+
def build(blueprint = nil, ext: nil, &) = instantiate(:build, blueprint, ext:, &)
|
63
|
+
|
64
|
+
# Create a set of objects by <code>create</code> strategy in FactoryBot.
|
65
|
+
# See {.plan} for more details.
|
66
|
+
# @param blueprint [Factrey::Blueprint, nil]
|
67
|
+
# @param ext [Object] an external object that can be accessed using {DSL#ext} in the DSL
|
68
|
+
# @yield Write Blueprint DSL code here
|
69
|
+
# @return [Hash{Symbol => Object}]
|
70
|
+
def create(blueprint = nil, ext: nil, &) = instantiate(:create, blueprint, ext:, &)
|
71
|
+
|
72
|
+
# @!visibility private
|
73
|
+
def instantiate(strategy, blueprint = nil, ext: nil, &)
|
74
|
+
raise ArgumentError, "Unsupported strategy: #{strategy}" unless %i[create build].include?(strategy)
|
75
|
+
|
76
|
+
plan(blueprint, ext:, &).instantiate(strategy:)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
metadata
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: factory_bot-blueprint
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- yubrot
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-07-22 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: factory_bot
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '6.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '6.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: factrey
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.1.0
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.1.0
|
41
|
+
description: |
|
42
|
+
FactoryBot::Blueprint is a FactoryBot extension for building structured objects using a declarative DSL.
|
43
|
+
On the DSL, the factories defined in FactoryBot can be used without any additional configuration.
|
44
|
+
email:
|
45
|
+
- yubrot@gmail.com
|
46
|
+
executables: []
|
47
|
+
extensions: []
|
48
|
+
extra_rdoc_files: []
|
49
|
+
files:
|
50
|
+
- LICENSE.txt
|
51
|
+
- README.md
|
52
|
+
- lib/factory_bot/blueprint.rb
|
53
|
+
- lib/factory_bot/blueprint/dsl.rb
|
54
|
+
- lib/factory_bot/blueprint/version.rb
|
55
|
+
homepage: https://github.com/yubrot/factory_bot-blueprint
|
56
|
+
licenses:
|
57
|
+
- MIT
|
58
|
+
metadata:
|
59
|
+
homepage_uri: https://github.com/yubrot/factory_bot-blueprint
|
60
|
+
source_code_uri: https://github.com/yubrot/factory_bot-blueprint
|
61
|
+
changelog_uri: https://github.com/yubrot/factory_bot-blueprint/blob/main/CHANGELOG.md
|
62
|
+
rubygems_mfa_required: 'true'
|
63
|
+
post_install_message:
|
64
|
+
rdoc_options: []
|
65
|
+
require_paths:
|
66
|
+
- lib
|
67
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
68
|
+
requirements:
|
69
|
+
- - ">="
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: 3.1.0
|
72
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - ">="
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
requirements: []
|
78
|
+
rubygems_version: 3.5.11
|
79
|
+
signing_key:
|
80
|
+
specification_version: 4
|
81
|
+
summary: FactoryBot extension for building structured objects using a declarative
|
82
|
+
DSL
|
83
|
+
test_files: []
|