satisfactory 0.0.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/LICENCE +2 -0
- data/Rakefile +0 -2
- data/bin/console +13 -0
- data/bin/rubocop +27 -0
- data/bin/setup +8 -0
- data/bin/yard +27 -0
- data/bin/yardoc +27 -0
- data/bin/yri +27 -0
- data/lib/satisfactory/collection.rb +61 -0
- data/lib/satisfactory/loader.rb +43 -0
- data/lib/satisfactory/record.rb +208 -0
- data/lib/satisfactory/root.rb +47 -0
- data/lib/satisfactory/upstream_record_finder.rb +30 -0
- data/lib/satisfactory/version.rb +1 -3
- data/lib/satisfactory.rb +21 -5
- data/satisfactory.gemspec +39 -0
- metadata +72 -11
- data/.rubocop.yml +0 -13
- data/Gemfile +0 -10
- data/sig/satisfactory.rbs +0 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4bb15c794b5397907577dbe90ac97815f6636d7c0268db9c553a91a2b51b1a56
|
4
|
+
data.tar.gz: 84336045dedaea44be72e4bd3a108624af18986b8d7cc7b5a07381b3910620c0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e018c58477288a2eac77a10889d31ba5a3c20b4c4c280d248789693d2c115849f88e42b7a759d471e8eadd4d46a079cb5496910248bb99a3f158bc420fb62d9b
|
7
|
+
data.tar.gz: bd5b099abce2a3d5b051a4c0e3343710d1305db4aa00a7b5c7e6a4c8614f84570afec990f86fe1d0c41228d803fd3db5bd61f1faaef9b2302e94e8fc4640573a
|
data/LICENCE
ADDED
data/Rakefile
CHANGED
data/bin/console
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require "bundler/setup"
|
3
|
+
require "satisfactory"
|
4
|
+
|
5
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
6
|
+
# with your gem easier. You can also use a different console, if you like.
|
7
|
+
|
8
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
9
|
+
# require "pry"
|
10
|
+
# Pry.start
|
11
|
+
|
12
|
+
require "irb"
|
13
|
+
IRB.start(__FILE__)
|
data/bin/rubocop
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'rubocop' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
|
12
|
+
|
13
|
+
bundle_binstub = File.expand_path("bundle", __dir__)
|
14
|
+
|
15
|
+
if File.file?(bundle_binstub)
|
16
|
+
if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
|
17
|
+
load(bundle_binstub)
|
18
|
+
else
|
19
|
+
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
20
|
+
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
require "rubygems"
|
25
|
+
require "bundler/setup"
|
26
|
+
|
27
|
+
load Gem.bin_path("rubocop", "rubocop")
|
data/bin/setup
ADDED
data/bin/yard
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'yard' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
|
12
|
+
|
13
|
+
bundle_binstub = File.expand_path("bundle", __dir__)
|
14
|
+
|
15
|
+
if File.file?(bundle_binstub)
|
16
|
+
if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
|
17
|
+
load(bundle_binstub)
|
18
|
+
else
|
19
|
+
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
20
|
+
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
require "rubygems"
|
25
|
+
require "bundler/setup"
|
26
|
+
|
27
|
+
load Gem.bin_path("yard", "yard")
|
data/bin/yardoc
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'yardoc' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
|
12
|
+
|
13
|
+
bundle_binstub = File.expand_path("bundle", __dir__)
|
14
|
+
|
15
|
+
if File.file?(bundle_binstub)
|
16
|
+
if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
|
17
|
+
load(bundle_binstub)
|
18
|
+
else
|
19
|
+
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
20
|
+
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
require "rubygems"
|
25
|
+
require "bundler/setup"
|
26
|
+
|
27
|
+
load Gem.bin_path("yard", "yardoc")
|
data/bin/yri
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'yri' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
|
12
|
+
|
13
|
+
bundle_binstub = File.expand_path("bundle", __dir__)
|
14
|
+
|
15
|
+
if File.file?(bundle_binstub)
|
16
|
+
if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
|
17
|
+
load(bundle_binstub)
|
18
|
+
else
|
19
|
+
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
20
|
+
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
require "rubygems"
|
25
|
+
require "bundler/setup"
|
26
|
+
|
27
|
+
load Gem.bin_path("yard", "yri")
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require_relative "upstream_record_finder"
|
2
|
+
|
3
|
+
module Satisfactory
|
4
|
+
# Represents a collection of homogenous records.
|
5
|
+
class Collection < Array
|
6
|
+
# @api private
|
7
|
+
def initialize(*args, upstream:, **kwargs, &block)
|
8
|
+
super(*args, **kwargs, &block)
|
9
|
+
@upstream = upstream
|
10
|
+
end
|
11
|
+
|
12
|
+
# @api private
|
13
|
+
attr_reader :upstream
|
14
|
+
|
15
|
+
# @!method and
|
16
|
+
# Delegates to the upstream record.
|
17
|
+
# @return (see Satisfactory::Record#and)
|
18
|
+
# @see Satisfactory::Record#and
|
19
|
+
# @!method create
|
20
|
+
# Delegates to the upstream record.
|
21
|
+
# @return (see Satisfactory::Record#create)
|
22
|
+
# @see Satisfactory::Record#create
|
23
|
+
# @!method to_plan
|
24
|
+
# Delegates to the upstream record.
|
25
|
+
# @return (see Satisfactory::Record#to_plan)
|
26
|
+
# @see Satisfactory::Record#to_plan
|
27
|
+
delegate :and, :create, :to_plan, to: :upstream
|
28
|
+
|
29
|
+
# Calls {#with} on each entry in the collection.
|
30
|
+
#
|
31
|
+
# @return [Satisfactory::Collection]
|
32
|
+
def with(...)
|
33
|
+
self.class.new(map { |entry| entry.with(...) }, upstream:)
|
34
|
+
end
|
35
|
+
alias each_with with
|
36
|
+
|
37
|
+
# Calls {#which_is} on each entry in the collection.
|
38
|
+
#
|
39
|
+
# @param (see Satisfactory::Record#which_is)
|
40
|
+
# @return [Satisfactory::Collection]
|
41
|
+
def which_are(...)
|
42
|
+
self.class.new(map { |entry| entry.which_is(...) }, upstream:)
|
43
|
+
end
|
44
|
+
alias which_is which_are
|
45
|
+
|
46
|
+
# (see Satisfactory::Record#and_same)
|
47
|
+
def and_same(upstream_type)
|
48
|
+
Satisfactory::UpstreamRecordFinder.new(upstream:).find(upstream_type)
|
49
|
+
end
|
50
|
+
|
51
|
+
# @api private
|
52
|
+
def build
|
53
|
+
flat_map(&:build)
|
54
|
+
end
|
55
|
+
|
56
|
+
# @api private
|
57
|
+
def build_plan
|
58
|
+
flat_map(&:build_plan)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require "factory_bot_rails"
|
2
|
+
|
3
|
+
module Satisfactory
|
4
|
+
# Loads factory configurations from FactoryBot.
|
5
|
+
#
|
6
|
+
# @api private
|
7
|
+
class Loader
|
8
|
+
class << self
|
9
|
+
# Skips factories that don't have a model that inherits from ApplicationRecord.
|
10
|
+
#
|
11
|
+
# @return [{Symbol => Hash}] a hash of factory configurations by factory name
|
12
|
+
def factory_configurations # rubocop:disable Metrics/AbcSize
|
13
|
+
FactoryBot.factories.each.with_object({}) do |(factory, model), configurations|
|
14
|
+
next unless (model = factory.build_class)
|
15
|
+
next unless model < ApplicationRecord
|
16
|
+
|
17
|
+
associations = associations_for(model)
|
18
|
+
parent_factory = factory.send(:parent)
|
19
|
+
|
20
|
+
configurations[factory.name] = {
|
21
|
+
associations: associations.transform_values { |a| a.map(&:name) },
|
22
|
+
model:,
|
23
|
+
name: factory.name,
|
24
|
+
parent: (parent_factory.name unless parent_factory.is_a?(FactoryBot::NullFactory)),
|
25
|
+
traits: factory.defined_traits.map(&:name),
|
26
|
+
}
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def associations_for(model)
|
33
|
+
all = model.reflect_on_all_associations.reject(&:polymorphic?)
|
34
|
+
plural = model.reflect_on_all_associations(:has_many).reject(&:polymorphic?)
|
35
|
+
|
36
|
+
{
|
37
|
+
plural:,
|
38
|
+
singular: all - plural,
|
39
|
+
}
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,208 @@
|
|
1
|
+
require_relative "collection"
|
2
|
+
require_relative "upstream_record_finder"
|
3
|
+
|
4
|
+
module Satisfactory
|
5
|
+
# Represents a usage of a type.
|
6
|
+
#
|
7
|
+
# @todo This whole class needs a tidy up
|
8
|
+
class Record # rubocop:disable Metrics/ClassLength
|
9
|
+
# @api private
|
10
|
+
# @param type [Symbol] The type of record to create. Must be a known factory.
|
11
|
+
# @param factory_name [Symbol] The name of the factory to use (if different).
|
12
|
+
# @param upstream [Satisfactory::Record, Satisfactory::Collection, Satisfactory::Root] The upstream record-ish.
|
13
|
+
# @param attributes [Hash] The attributes to use when creating the record.
|
14
|
+
def initialize(type:, factory_name: nil, upstream: nil, attributes: {})
|
15
|
+
@factory_name = factory_name || type
|
16
|
+
|
17
|
+
config = Satisfactory.factory_configurations[type]
|
18
|
+
raise ArgumentError, "Unknown factory #{type}" unless config
|
19
|
+
|
20
|
+
@type = config[:parent] || type
|
21
|
+
@type_config = Satisfactory.factory_configurations[@type]
|
22
|
+
@traits = []
|
23
|
+
@upstream = upstream
|
24
|
+
|
25
|
+
@attributes = attributes
|
26
|
+
|
27
|
+
@associations = type_config.dig(:associations, :plural).each.with_object({}) do |name, hash|
|
28
|
+
hash[name] = Satisfactory::Collection.new(upstream: self)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# @api private
|
33
|
+
attr_accessor :type, :type_config, :traits, :upstream, :factory_name, :attributes
|
34
|
+
|
35
|
+
# Add an associated record to this record's build plan.
|
36
|
+
#
|
37
|
+
# @param count [Integer] The number of records to create.
|
38
|
+
# @param downstream_type [Symbol] The type of record to create.
|
39
|
+
# @param force [Boolean] Whether to force the creation of the record.
|
40
|
+
# For internal use only. Use {#and} instead.
|
41
|
+
# @param attributes [Hash] The attributes to use when creating the record.
|
42
|
+
# @return [Satisfactory::Record, Satisfactory::Collection]
|
43
|
+
def with(count = nil, downstream_type, force: false, **attributes) # rubocop:disable Style/OptionalArguments, Metrics/AbcSize, Metrics/MethodLength, Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
|
44
|
+
if singular?(downstream_type)
|
45
|
+
if count && count > 1 # rubocop:disable Style/IfUnlessModifier
|
46
|
+
raise ArgumentError, "Cannot create multiple of singular associations (e.g. belongs_to)"
|
47
|
+
end
|
48
|
+
|
49
|
+
add_singular_association(downstream_type, factory_name: downstream_type, force:, attributes:)
|
50
|
+
elsif plural?(downstream_type) && (singular = singular_from_plural(downstream_type))
|
51
|
+
add_plural_association(downstream_type, factory_name: singular, count:, force:, attributes:)
|
52
|
+
elsif (config = Satisfactory.factory_configurations[downstream_type])
|
53
|
+
singular = config[:parent] || downstream_type
|
54
|
+
plural = plural_from_singular(singular)
|
55
|
+
add_singular_for_plural_association(plural, singular:, factory_name: downstream_type, force:, attributes:)
|
56
|
+
elsif (config = Satisfactory.factory_configurations[downstream_type.to_s.singularize])
|
57
|
+
unless (parent = config[:parent])
|
58
|
+
raise ArgumentError, "Cannot create multiple of singular associations (e.g. belongs_to)"
|
59
|
+
end
|
60
|
+
|
61
|
+
plural = plural_from_singular(parent)
|
62
|
+
add_plural_association(plural, factory_name: downstream_type.to_s.singularize, count:, force:, attributes:)
|
63
|
+
else
|
64
|
+
raise ArgumentError, "Unknown association #{type}->#{downstream_type}"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# Add a sibling record to the parent record's build plan.
|
69
|
+
# e.g. adding a second user to a project.
|
70
|
+
#
|
71
|
+
# @param count [Integer] The number of records to create.
|
72
|
+
# @param downstream_type [Symbol] The type of record to create.
|
73
|
+
# @param attributes [Hash] The attributes to use when creating the record.
|
74
|
+
# @return (see #with)
|
75
|
+
def and(count = nil, downstream_type, **attributes) # rubocop:disable Style/OptionalArguments
|
76
|
+
upstream.with(count, downstream_type, force: true, **attributes)
|
77
|
+
end
|
78
|
+
|
79
|
+
# Apply one or more traits to this record's build plan.
|
80
|
+
#
|
81
|
+
# @param *traits [Symbol, ...] The traits to apply.
|
82
|
+
def which_is(*traits)
|
83
|
+
traits.each { |trait| self.traits << trait }
|
84
|
+
self
|
85
|
+
end
|
86
|
+
|
87
|
+
# Locate the nearest ancestor of the given type.
|
88
|
+
#
|
89
|
+
# @param upstream_type [Symbol] The type of ancestor to find.
|
90
|
+
# @return [Satisfactory::Record, Satisfactory::Collection, Satisfactory::Root]
|
91
|
+
def and_same(upstream_type)
|
92
|
+
Satisfactory::UpstreamRecordFinder.new(upstream:).find(upstream_type)
|
93
|
+
end
|
94
|
+
|
95
|
+
# @api private
|
96
|
+
def modify
|
97
|
+
yield(self).upstream
|
98
|
+
end
|
99
|
+
|
100
|
+
# Trigger the creation of this tree's build plan.
|
101
|
+
#
|
102
|
+
# @return (see Satisfactory::Root#create)
|
103
|
+
# @todo Check if we still need the upstream check.
|
104
|
+
def create
|
105
|
+
if upstream
|
106
|
+
upstream.create
|
107
|
+
else
|
108
|
+
create_self
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
# Construct this tree's build plan.
|
113
|
+
#
|
114
|
+
# @return [Hash]
|
115
|
+
def to_plan
|
116
|
+
if upstream
|
117
|
+
upstream.to_plan
|
118
|
+
else
|
119
|
+
build_plan
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
# @api private
|
124
|
+
def build_plan
|
125
|
+
{
|
126
|
+
traits:,
|
127
|
+
}.merge(associations_plan).compact_blank
|
128
|
+
end
|
129
|
+
|
130
|
+
# @api private
|
131
|
+
# @return (see #reify)
|
132
|
+
def build
|
133
|
+
reify(:build)
|
134
|
+
end
|
135
|
+
|
136
|
+
# @api private
|
137
|
+
# @return (see #reify)
|
138
|
+
def create_self
|
139
|
+
reify(:create)
|
140
|
+
end
|
141
|
+
|
142
|
+
private
|
143
|
+
|
144
|
+
attr_reader :associations
|
145
|
+
|
146
|
+
# @return [ApplicationRecord]
|
147
|
+
def reify(method)
|
148
|
+
FactoryBot.public_send(method, factory_name, *traits, attributes.merge(associations.transform_values(&:build)))
|
149
|
+
end
|
150
|
+
|
151
|
+
def associations_plan
|
152
|
+
associations.transform_values(&:build_plan).compact_blank
|
153
|
+
end
|
154
|
+
|
155
|
+
def plural?(association_name)
|
156
|
+
type_config.dig(:associations, :plural).include?(association_name)
|
157
|
+
end
|
158
|
+
|
159
|
+
def singular?(association_name)
|
160
|
+
type_config.dig(:associations, :singular).include?(association_name)
|
161
|
+
end
|
162
|
+
|
163
|
+
def plural_from_singular(singular_association_name)
|
164
|
+
type_config.dig(:associations, :plural).find do |name|
|
165
|
+
singular_association_name.to_s == name.to_s.singularize
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
def singular_from_plural(plural_association_name)
|
170
|
+
Satisfactory.factory_configurations.keys.find do |name|
|
171
|
+
plural_association_name.to_s == name.to_s.pluralize
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
def add_singular_association(name, factory_name:, force: false, attributes: {})
|
176
|
+
if force || associations[name].blank?
|
177
|
+
associations[name] = self.class.new(type: name, factory_name:, upstream: self, attributes:)
|
178
|
+
else
|
179
|
+
associations[name]
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
def add_plural_association(name, factory_name:, count: nil, force: false, attributes: {})
|
184
|
+
count ||= 1
|
185
|
+
singular_name = name.to_s.singularize.to_sym
|
186
|
+
|
187
|
+
Satisfactory::Collection.new(upstream: self).tap do |new_associations|
|
188
|
+
count.times do
|
189
|
+
new_associations << self.class.new(type: singular_name, factory_name:, upstream: self, attributes:)
|
190
|
+
end
|
191
|
+
|
192
|
+
if force
|
193
|
+
associations[name] << new_associations
|
194
|
+
else
|
195
|
+
associations[name] = new_associations
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
def add_singular_for_plural_association(name, singular:, factory_name:, force: false, attributes: {})
|
201
|
+
if force || associations[name].empty?
|
202
|
+
associations[name] << self.class.new(type: singular, factory_name:, upstream: self, attributes:)
|
203
|
+
end
|
204
|
+
|
205
|
+
associations[name].last
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require_relative "record"
|
2
|
+
|
3
|
+
module Satisfactory
|
4
|
+
# The root of the factory graph.
|
5
|
+
# This is where you begin creating records.
|
6
|
+
class Root
|
7
|
+
# @api private
|
8
|
+
def initialize
|
9
|
+
@root_records = Hash.new { |h, k| h[k] = [] }
|
10
|
+
end
|
11
|
+
|
12
|
+
# Add a top-level record to the root.
|
13
|
+
# This is your entry point into the factory graph, and
|
14
|
+
# the way to begin creating records.
|
15
|
+
def add(factory_name, **attributes)
|
16
|
+
raise FactoryNotDefinedError, factory_name unless Satisfactory.factory_configurations.key?(factory_name)
|
17
|
+
|
18
|
+
Satisfactory::Record.new(
|
19
|
+
type: factory_name,
|
20
|
+
upstream: self,
|
21
|
+
attributes:,
|
22
|
+
).tap { |r| @root_records[factory_name] << r }
|
23
|
+
end
|
24
|
+
|
25
|
+
# @api private
|
26
|
+
# @return [Hash<Symbol, Array<ApplicationRecord>>]
|
27
|
+
def create
|
28
|
+
@root_records.transform_values do |records|
|
29
|
+
records.map(&:create_self)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# @api private
|
34
|
+
# @return [Hash<Symbol, Array<Hash>>]
|
35
|
+
def to_plan
|
36
|
+
@root_records.transform_values do |records|
|
37
|
+
records.map(&:build_plan)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# @api private
|
42
|
+
# @return [nil]
|
43
|
+
def upstream
|
44
|
+
nil
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Satisfactory
|
2
|
+
# Finds the upstream record of a given type.
|
3
|
+
#
|
4
|
+
# @api private
|
5
|
+
class UpstreamRecordFinder
|
6
|
+
def initialize(upstream:)
|
7
|
+
@upstream = upstream
|
8
|
+
end
|
9
|
+
|
10
|
+
attr_accessor :upstream
|
11
|
+
|
12
|
+
def find(type)
|
13
|
+
raise MissingUpstreamRecordError, type if upstream.nil?
|
14
|
+
|
15
|
+
if type == upstream.type
|
16
|
+
self
|
17
|
+
else
|
18
|
+
self.upstream = upstream.upstream
|
19
|
+
find(type)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def with(*args, **kwargs)
|
24
|
+
upstream.with(*args, force: true, **kwargs)
|
25
|
+
end
|
26
|
+
|
27
|
+
# @api private
|
28
|
+
class MissingUpstreamRecordError < StandardError; end
|
29
|
+
end
|
30
|
+
end
|
data/lib/satisfactory/version.rb
CHANGED
data/lib/satisfactory.rb
CHANGED
@@ -1,8 +1,24 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require_relative "satisfactory/version"
|
1
|
+
require_relative "satisfactory/loader"
|
2
|
+
require_relative "satisfactory/root"
|
4
3
|
|
4
|
+
# Satisfactory is a factory library for Ruby,
|
5
|
+
# helping you to navigate your factory associations.
|
6
|
+
#
|
7
|
+
# Currently implemented atop FactoryBot, but
|
8
|
+
# could be extended to support other factory libraries.
|
9
|
+
#
|
10
|
+
# @since 0.2.0
|
5
11
|
module Satisfactory
|
6
|
-
|
7
|
-
|
12
|
+
# @!attribute [r] factory_configurations
|
13
|
+
class << self
|
14
|
+
def root
|
15
|
+
Root.new
|
16
|
+
end
|
17
|
+
|
18
|
+
# @api private
|
19
|
+
# @return (see Loader.factory_configurations)
|
20
|
+
def factory_configurations
|
21
|
+
@factory_configurations ||= Loader.factory_configurations
|
22
|
+
end
|
23
|
+
end
|
8
24
|
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require_relative "lib/satisfactory/version"
|
2
|
+
|
3
|
+
Gem::Specification.new do |spec|
|
4
|
+
spec.name = "satisfactory"
|
5
|
+
spec.version = Satisfactory::VERSION
|
6
|
+
spec.authors = ["Elliot Crosby-McCullough"]
|
7
|
+
spec.email = ["elliot.cm@gmail.com"]
|
8
|
+
|
9
|
+
spec.summary = "A DSL for navigating your factories and building test data"
|
10
|
+
spec.homepage = "https://github.com/SmartCasual/satisfactory"
|
11
|
+
spec.license = "CC-BY-NC-SA-4.0"
|
12
|
+
|
13
|
+
spec.metadata["changelog_uri"] = "#{spec.homepage}/blob/v#{spec.version}/CHANGELOG.md"
|
14
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
15
|
+
spec.metadata["source_code_uri"] = spec.homepage
|
16
|
+
|
17
|
+
spec.metadata["rubygems_mfa_required"] = "true"
|
18
|
+
spec.required_ruby_version = ">= 3.1.0"
|
19
|
+
|
20
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) {
|
21
|
+
Dir[
|
22
|
+
"{bin,lib}/**/*",
|
23
|
+
"CHANGELOG.md",
|
24
|
+
"LICENCE",
|
25
|
+
"Rakefile",
|
26
|
+
"README.md",
|
27
|
+
"satisfactory.gemspec",
|
28
|
+
]
|
29
|
+
}
|
30
|
+
|
31
|
+
spec.bindir = "bin"
|
32
|
+
spec.executables = spec.files.grep(%r{\Abin/}) { |f| File.basename(f) }
|
33
|
+
spec.require_paths = ["lib"]
|
34
|
+
|
35
|
+
spec.add_dependency "factory_bot_rails", "~> 6.2"
|
36
|
+
|
37
|
+
spec.add_development_dependency "rubocop", "~> 1.40"
|
38
|
+
spec.add_development_dependency "yard", "~> 0.9"
|
39
|
+
end
|
metadata
CHANGED
@@ -1,35 +1,96 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: satisfactory
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Elliot Crosby-McCullough
|
8
8
|
autorequire:
|
9
|
-
bindir:
|
9
|
+
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-12-
|
12
|
-
dependencies:
|
11
|
+
date: 2022-12-19 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: factory_bot_rails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '6.2'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '6.2'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rubocop
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.40'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.40'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: yard
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0.9'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0.9'
|
13
55
|
description:
|
14
56
|
email:
|
15
57
|
- elliot.cm@gmail.com
|
16
|
-
executables:
|
58
|
+
executables:
|
59
|
+
- console
|
60
|
+
- rubocop
|
61
|
+
- setup
|
62
|
+
- yard
|
63
|
+
- yardoc
|
64
|
+
- yri
|
17
65
|
extensions: []
|
18
66
|
extra_rdoc_files: []
|
19
67
|
files:
|
20
|
-
- ".rubocop.yml"
|
21
68
|
- CHANGELOG.md
|
22
|
-
-
|
69
|
+
- LICENCE
|
23
70
|
- README.md
|
24
71
|
- Rakefile
|
72
|
+
- bin/console
|
73
|
+
- bin/rubocop
|
74
|
+
- bin/setup
|
75
|
+
- bin/yard
|
76
|
+
- bin/yardoc
|
77
|
+
- bin/yri
|
25
78
|
- lib/satisfactory.rb
|
79
|
+
- lib/satisfactory/collection.rb
|
80
|
+
- lib/satisfactory/loader.rb
|
81
|
+
- lib/satisfactory/record.rb
|
82
|
+
- lib/satisfactory/root.rb
|
83
|
+
- lib/satisfactory/upstream_record_finder.rb
|
26
84
|
- lib/satisfactory/version.rb
|
27
|
-
-
|
85
|
+
- satisfactory.gemspec
|
28
86
|
homepage: https://github.com/SmartCasual/satisfactory
|
29
|
-
licenses:
|
87
|
+
licenses:
|
88
|
+
- CC-BY-NC-SA-4.0
|
30
89
|
metadata:
|
90
|
+
changelog_uri: https://github.com/SmartCasual/satisfactory/blob/v0.2.0/CHANGELOG.md
|
31
91
|
homepage_uri: https://github.com/SmartCasual/satisfactory
|
32
92
|
source_code_uri: https://github.com/SmartCasual/satisfactory
|
93
|
+
rubygems_mfa_required: 'true'
|
33
94
|
post_install_message:
|
34
95
|
rdoc_options: []
|
35
96
|
require_paths:
|
@@ -38,7 +99,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
38
99
|
requirements:
|
39
100
|
- - ">="
|
40
101
|
- !ruby/object:Gem::Version
|
41
|
-
version:
|
102
|
+
version: 3.1.0
|
42
103
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
43
104
|
requirements:
|
44
105
|
- - ">="
|
@@ -48,5 +109,5 @@ requirements: []
|
|
48
109
|
rubygems_version: 3.3.7
|
49
110
|
signing_key:
|
50
111
|
specification_version: 4
|
51
|
-
summary:
|
112
|
+
summary: A DSL for navigating your factories and building test data
|
52
113
|
test_files: []
|
data/.rubocop.yml
DELETED
data/Gemfile
DELETED
data/sig/satisfactory.rbs
DELETED