rom-factory 0.10.2 → 0.12.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 +4 -4
- data/.devtools/templates/changelog.erb +3 -0
- data/.devtools/templates/release.erb +36 -0
- data/.github/FUNDING.yml +1 -0
- data/.github/ISSUE_TEMPLATE/{---bug-report.md → bug-report.md} +6 -10
- data/.github/ISSUE_TEMPLATE/config.yml +5 -0
- data/.github/SUPPORT.md +3 -0
- data/.github/workflows/ci.yml +17 -25
- data/.github/workflows/docsite.yml +6 -6
- data/.github/workflows/rubocop.yml +46 -0
- data/.github/workflows/sync_configs.yml +7 -13
- data/.repobot.yml +24 -0
- data/.rubocop.yml +135 -16
- data/CHANGELOG.md +64 -0
- data/CODEOWNERS +1 -0
- data/CONTRIBUTING.md +3 -3
- data/Gemfile +20 -19
- data/Gemfile.devtools +6 -5
- data/LICENSE +1 -1
- data/README.md +3 -3
- data/Rakefile +1 -1
- data/benchmarks/basic.rb +10 -10
- data/changelog.yml +35 -0
- data/docsite/source/index.html.md +162 -1
- data/lib/rom/factory/attribute_registry.rb +6 -2
- data/lib/rom/factory/attributes/association.rb +127 -29
- data/lib/rom/factory/attributes/callable.rb +1 -1
- data/lib/rom/factory/attributes/value.rb +1 -1
- data/lib/rom/factory/attributes.rb +4 -6
- data/lib/rom/factory/builder/persistable.rb +21 -6
- data/lib/rom/factory/builder.rb +17 -19
- data/lib/rom/factory/constants.rb +1 -1
- data/lib/rom/factory/dsl.rb +43 -25
- data/lib/rom/factory/factories.rb +13 -15
- data/lib/rom/factory/registry.rb +2 -2
- data/lib/rom/factory/sequences.rb +4 -3
- data/lib/rom/factory/tuple_evaluator.rb +92 -43
- data/lib/rom/factory/version.rb +1 -1
- data/lib/rom/factory.rb +8 -5
- data/lib/rom-factory.rb +1 -1
- data/project.yml +1 -0
- data/rom-factory.gemspec +9 -10
- metadata +40 -26
- data/.github/ISSUE_TEMPLATE/----please-don-t-ask-for-support-via-issues.md +0 -10
- data/.github/ISSUE_TEMPLATE/----please-don-t-report-feature-requests-via-issues.md +0 -10
- data/.github/ISSUE_TEMPLATE/---a-detailed-bug-report.md +0 -30
- data/.github/ISSUE_TEMPLATE/---feature-request.md +0 -18
- data/.github/workflows/custom/ci.yml +0 -26
- data/Appraisals +0 -9
- data/LICENSE.txt +0 -21
data/Gemfile
CHANGED
@@ -1,38 +1,39 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
source
|
3
|
+
source "https://rubygems.org"
|
4
4
|
|
5
5
|
gemspec
|
6
6
|
|
7
|
-
eval_gemfile
|
7
|
+
eval_gemfile "Gemfile.devtools"
|
8
8
|
|
9
|
-
gem
|
9
|
+
gem "faker", "~> 3.0"
|
10
10
|
|
11
|
-
gem
|
12
|
-
gem 'rspec', '~> 3.0'
|
11
|
+
gem "rspec", "~> 3.0"
|
13
12
|
|
14
|
-
|
15
|
-
gem
|
13
|
+
git "https://github.com/rom-rb/rom.git", branch: "release-5.3" do
|
14
|
+
gem "rom-core"
|
15
|
+
gem "rom-changeset"
|
16
|
+
gem "rom-repository"
|
17
|
+
gem "rom"
|
16
18
|
end
|
17
19
|
|
18
20
|
group :test do
|
19
|
-
gem
|
20
|
-
gem
|
21
|
-
gem
|
22
|
-
gem 'pry', '~> 0.12.0', '<= 0.13'
|
21
|
+
gem "pry"
|
22
|
+
gem "pry-byebug", "~> 3.8", platforms: :ruby
|
23
|
+
gem "rom-sql", github: "rom-rb/rom-sql", branch: "release-3.6"
|
23
24
|
|
24
|
-
gem
|
25
|
-
gem
|
25
|
+
gem "jdbc-postgres", platforms: :jruby
|
26
|
+
gem "pg", "~> 1.5", platforms: :ruby
|
26
27
|
end
|
27
28
|
|
28
29
|
group :tools do
|
29
|
-
gem
|
30
|
-
gem
|
30
|
+
gem "byebug", platform: :mri
|
31
|
+
gem "redcarpet" # for yard
|
31
32
|
end
|
32
33
|
|
33
34
|
group :benchmarks do
|
34
|
-
gem
|
35
|
-
gem
|
36
|
-
gem
|
37
|
-
gem
|
35
|
+
gem "activerecord"
|
36
|
+
gem "benchmark-ips"
|
37
|
+
gem "fabrication"
|
38
|
+
gem "factory_bot"
|
38
39
|
end
|
data/Gemfile.devtools
CHANGED
@@ -2,18 +2,19 @@
|
|
2
2
|
|
3
3
|
# this file is managed by rom-rb/devtools project
|
4
4
|
|
5
|
+
gem "rake", ">= 12.3.3"
|
6
|
+
|
5
7
|
git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
|
6
8
|
|
7
9
|
group :test do
|
8
|
-
|
9
|
-
gem "simplecov",
|
10
|
-
|
11
|
-
gem "codacy-coverage", require: false, platforms: :ruby
|
10
|
+
gem "simplecov", require: false, platforms: :ruby
|
11
|
+
gem "simplecov-cobertura", require: false, platforms: :ruby
|
12
|
+
gem "rexml", require: false
|
12
13
|
|
13
14
|
gem "warning" if RUBY_VERSION >= "2.4.0"
|
14
15
|
end
|
15
16
|
|
16
17
|
group :tools do
|
17
18
|
# this is the same version that we use on codacy
|
18
|
-
gem "rubocop", "
|
19
|
+
gem "rubocop", "1.26.1"
|
19
20
|
end
|
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -14,14 +14,14 @@
|
|
14
14
|
|
15
15
|
## Links
|
16
16
|
|
17
|
-
* [User documentation](
|
18
|
-
* [API documentation](
|
17
|
+
* [User documentation](https://rom-rb.org/learn/factory)
|
18
|
+
* [API documentation](https://rubydoc.info/gems/rom-factory)
|
19
19
|
|
20
20
|
## Supported Ruby versions
|
21
21
|
|
22
22
|
This library officially supports the following Ruby versions:
|
23
23
|
|
24
|
-
* MRI >= `2.
|
24
|
+
* MRI >= `2.5`
|
25
25
|
* jruby >= `9.2`
|
26
26
|
|
27
27
|
## License
|
data/Rakefile
CHANGED
data/benchmarks/basic.rb
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
3
|
+
require "rom-factory"
|
4
|
+
require "rom-core"
|
5
|
+
require "active_record"
|
6
|
+
require "factory_bot"
|
7
|
+
require "fabrication"
|
8
|
+
require "benchmark/ips"
|
9
9
|
|
10
|
-
DATABASE_URL =
|
10
|
+
DATABASE_URL = "postgres://localhost/rom_factory_bench"
|
11
11
|
|
12
12
|
rom = ROM.container(:sql, DATABASE_URL) do |conf|
|
13
13
|
conf.default.connection.create_table?(:users) do
|
@@ -50,15 +50,15 @@ Fabricator(:user) do
|
|
50
50
|
end
|
51
51
|
|
52
52
|
Benchmark.ips do |x|
|
53
|
-
x.report(
|
53
|
+
x.report("rom-factory persisted struct") do
|
54
54
|
factory[:user]
|
55
55
|
end
|
56
56
|
|
57
|
-
x.report(
|
57
|
+
x.report("factory_bot") do
|
58
58
|
FactoryBot.create(:user)
|
59
59
|
end
|
60
60
|
|
61
|
-
x.report(
|
61
|
+
x.report("fabrication") do
|
62
62
|
Fabricate(:user)
|
63
63
|
end
|
64
64
|
|
data/changelog.yml
CHANGED
@@ -1,4 +1,39 @@
|
|
1
1
|
---
|
2
|
+
- version: 0.12.0
|
3
|
+
date: 2024-01-19
|
4
|
+
added:
|
5
|
+
- Support for many-to-many and one-to-one-through associations (via #86) (@solnic)
|
6
|
+
- Support for UUID as PKs in associations (via #87) (@solnic)
|
7
|
+
fixed:
|
8
|
+
- Relations without PKs should work too (via #87) (@solnic)
|
9
|
+
- Relations with PK values generated on the Ruby side should work in SQlite too (via #87) (@solnic)
|
10
|
+
- version: 0.11.0
|
11
|
+
date: 2022-11-11
|
12
|
+
added:
|
13
|
+
- Support for one-to-one associations (@ianks)
|
14
|
+
- "[internal] cache for Faker constants (@flash-gordon)"
|
15
|
+
changed:
|
16
|
+
- |
|
17
|
+
[BREAKING] attributes are always passed as keywords (@alassek)
|
18
|
+
This may affect your code in places where attributes are passed as hashes.
|
19
|
+
Places like
|
20
|
+
|
21
|
+
```ruby
|
22
|
+
user_attributes = { name: 'Jane' }
|
23
|
+
Factory[:user, user_attributes]
|
24
|
+
|
25
|
+
```
|
26
|
+
|
27
|
+
must be updated to
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
user_attributes = { name: 'Jane' }
|
31
|
+
Factory[:user, **user_attributes]
|
32
|
+
```
|
33
|
+
- "Upgraded to the latest versions of dry-rb dependencies, compatible with rom 5.3 (@flash-gordon)"
|
34
|
+
- Support for Faker 1.x was dropped (@alassek)
|
35
|
+
fixed:
|
36
|
+
- Support for plural Faker generators (@wuarmin)
|
2
37
|
- version: 0.10.2
|
3
38
|
date: "2020-04-05"
|
4
39
|
fixed:
|
@@ -5,4 +5,165 @@ chapter: Factory
|
|
5
5
|
|
6
6
|
# rom-factory
|
7
7
|
|
8
|
-
|
8
|
+
`rom-factory` provides a simple API for creating and persisting `ROM::Struct`'s. If you already know FactoryBot you'll definitely understand the concept.
|
9
|
+
|
10
|
+
## Installation
|
11
|
+
|
12
|
+
First of all you need to define a ROM Container for Factory. For example if you are using `rspec`, you can add these lines to `spec_helper.rb`. Also you need to require here all files with Factories.
|
13
|
+
|
14
|
+
```ruby
|
15
|
+
Factory = ROM::Factory.configure do |config|
|
16
|
+
config.rom = my_rom_container
|
17
|
+
end
|
18
|
+
|
19
|
+
Dir[File.dirname(__FILE__) + '/support/factories/*.rb'].each { |file| require file }
|
20
|
+
```
|
21
|
+
|
22
|
+
## Usage
|
23
|
+
|
24
|
+
### Define factory
|
25
|
+
|
26
|
+
```ruby
|
27
|
+
# 'spec/support/factories/users.rb'
|
28
|
+
|
29
|
+
Factory.define(:user) do |f|
|
30
|
+
f.name 'John'
|
31
|
+
f.age 42
|
32
|
+
end
|
33
|
+
```
|
34
|
+
#### Specify relations
|
35
|
+
|
36
|
+
You can specify ROM relation if you want. It'll be pluralized factory name by default.
|
37
|
+
|
38
|
+
```ruby
|
39
|
+
Factory.define(:user, relation: :people) do |f|
|
40
|
+
f.name 'John'
|
41
|
+
f.age 42
|
42
|
+
end
|
43
|
+
```
|
44
|
+
|
45
|
+
#### Specify namespace for your structs
|
46
|
+
|
47
|
+
Struct `User` will be found in `MyApp::Entities` namespace
|
48
|
+
|
49
|
+
```ruby
|
50
|
+
Factory.define(:user, struct_namespace: MyApp::Entities) do |f|
|
51
|
+
# ...
|
52
|
+
end
|
53
|
+
```
|
54
|
+
|
55
|
+
#### Sequences
|
56
|
+
|
57
|
+
You can use sequences for uniq fields
|
58
|
+
|
59
|
+
```ruby
|
60
|
+
Factory.define(:user) do |f|
|
61
|
+
f.name 'John'
|
62
|
+
f.sequence(:email) { |n| "john#{n}@example.com" }
|
63
|
+
end
|
64
|
+
```
|
65
|
+
|
66
|
+
#### Timestamps
|
67
|
+
|
68
|
+
```ruby
|
69
|
+
Factory.define(:user) do |f|
|
70
|
+
f.name 'John'
|
71
|
+
f.timestamps
|
72
|
+
# same as
|
73
|
+
# f.created_at { Time.now }
|
74
|
+
# f.updated_at { Time.now }
|
75
|
+
end
|
76
|
+
```
|
77
|
+
|
78
|
+
#### Associations
|
79
|
+
|
80
|
+
* belongs_to
|
81
|
+
|
82
|
+
```ruby
|
83
|
+
Factory.define(:group) do |f|
|
84
|
+
f.name 'Admins'
|
85
|
+
end
|
86
|
+
|
87
|
+
Factory.define(:user) do |f|
|
88
|
+
f.name 'John'
|
89
|
+
f.association(:group)
|
90
|
+
end
|
91
|
+
```
|
92
|
+
|
93
|
+
* has_many
|
94
|
+
|
95
|
+
```ruby
|
96
|
+
Factory.define(:group) do |f|
|
97
|
+
f.name 'Admins'
|
98
|
+
f.association(:user, count: 2)
|
99
|
+
end
|
100
|
+
|
101
|
+
Factory.define(:user) do |f|
|
102
|
+
f.name 'John'
|
103
|
+
end
|
104
|
+
```
|
105
|
+
|
106
|
+
#### Extend already existing factory
|
107
|
+
|
108
|
+
```ruby
|
109
|
+
Factory.define(:user) do |f|
|
110
|
+
f.name 'John'
|
111
|
+
f.admin false
|
112
|
+
end
|
113
|
+
|
114
|
+
Factory.define(admin: :user) do |f|
|
115
|
+
f.admin true
|
116
|
+
end
|
117
|
+
|
118
|
+
# Factory.structs[:admin]
|
119
|
+
```
|
120
|
+
|
121
|
+
#### Traits
|
122
|
+
|
123
|
+
```ruby
|
124
|
+
Factory.define(:user) do |f|
|
125
|
+
f.name 'John'
|
126
|
+
f.admin false
|
127
|
+
|
128
|
+
f.trait :with_age do |t|
|
129
|
+
t.age 42
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
# Factory.structs[:user, :with_age]
|
134
|
+
```
|
135
|
+
|
136
|
+
#### Build-in [Faker](https://github.com/faker-ruby/faker) objects
|
137
|
+
|
138
|
+
```ruby
|
139
|
+
Factory.define(:user) do |f|
|
140
|
+
f.email { fake(:internet, :email) }
|
141
|
+
end
|
142
|
+
```
|
143
|
+
|
144
|
+
#### Dependent attributes
|
145
|
+
|
146
|
+
Attributes can be based on the values of other attributes:
|
147
|
+
|
148
|
+
```ruby
|
149
|
+
Factory.define(:user) do |f|
|
150
|
+
f.full_name { fake(:name) }
|
151
|
+
# Dependent attributes are inferred from the block parameter names:
|
152
|
+
f.login { |full_name| full_name.downcase.gsub(/\s+/, '_') }
|
153
|
+
# Works with sequences too:
|
154
|
+
f.sequence(:email) { |n, login| "#{login}-#{n}@example.com" }
|
155
|
+
end
|
156
|
+
```
|
157
|
+
|
158
|
+
### Build and persist objects
|
159
|
+
|
160
|
+
```ruby
|
161
|
+
# Create in-memory object
|
162
|
+
Factory.structs[:user]
|
163
|
+
|
164
|
+
# Persist struct in database
|
165
|
+
Factory[:user]
|
166
|
+
|
167
|
+
# Override attributes
|
168
|
+
Factory[:user, age: 24]
|
169
|
+
```
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "tsort"
|
4
4
|
|
5
5
|
module ROM
|
6
6
|
module Factory
|
@@ -47,7 +47,11 @@ module ROM
|
|
47
47
|
|
48
48
|
# @api private
|
49
49
|
def associations
|
50
|
-
self.class.new(elements.select { |e| e.
|
50
|
+
self.class.new(elements.select { |e| e.is_a?(Attributes::Association::Core) })
|
51
|
+
end
|
52
|
+
|
53
|
+
def reject(&block)
|
54
|
+
self.class.new(elements.reject(&block))
|
51
55
|
end
|
52
56
|
|
53
57
|
private
|
@@ -3,12 +3,12 @@
|
|
3
3
|
module ROM::Factory
|
4
4
|
module Attributes
|
5
5
|
# @api private
|
6
|
+
# rubocop:disable Style/OptionalArguments
|
6
7
|
module Association
|
7
8
|
class << self
|
8
|
-
def new(assoc, builder, *
|
9
|
-
const_get(assoc.definition.type).new(assoc, builder, *
|
9
|
+
def new(assoc, builder, *traits, **options)
|
10
|
+
const_get(assoc.definition.type).new(assoc, builder, *traits, **options)
|
10
11
|
end
|
11
|
-
ruby2_keywords(:new) if respond_to?(:ruby2_keywords, true)
|
12
12
|
end
|
13
13
|
|
14
14
|
# @api private
|
@@ -23,6 +23,11 @@ module ROM::Factory
|
|
23
23
|
@options = options
|
24
24
|
end
|
25
25
|
|
26
|
+
# @api private
|
27
|
+
def through?
|
28
|
+
false
|
29
|
+
end
|
30
|
+
|
26
31
|
# @api private
|
27
32
|
def builder
|
28
33
|
@__builder__ ||= @builder_proc.call
|
@@ -42,28 +47,62 @@ module ROM::Factory
|
|
42
47
|
def value?
|
43
48
|
false
|
44
49
|
end
|
50
|
+
|
51
|
+
# @api private
|
52
|
+
def factories
|
53
|
+
builder.factories
|
54
|
+
end
|
55
|
+
|
56
|
+
# @api private
|
57
|
+
def foreign_key
|
58
|
+
assoc.foreign_key
|
59
|
+
end
|
60
|
+
|
61
|
+
# @api private
|
62
|
+
def count
|
63
|
+
options.fetch(:count, 1)
|
64
|
+
end
|
45
65
|
end
|
46
66
|
|
47
67
|
# @api private
|
48
68
|
class ManyToOne < Core
|
49
69
|
# @api private
|
70
|
+
# rubocop:disable Metrics/AbcSize
|
50
71
|
def call(attrs, persist: true)
|
51
|
-
if attrs.key?(name) &&
|
72
|
+
return if attrs.key?(name) && attrs[name].nil?
|
73
|
+
|
74
|
+
assoc_data = attrs.fetch(name, EMPTY_HASH)
|
75
|
+
|
76
|
+
if assoc_data.is_a?(Hash) && assoc_data[assoc.target.primary_key] && !attrs[foreign_key]
|
52
77
|
assoc.associate(attrs, attrs[name])
|
53
|
-
elsif
|
54
|
-
|
55
|
-
|
78
|
+
elsif assoc_data.is_a?(ROM::Struct)
|
79
|
+
assoc.associate(attrs, assoc_data)
|
80
|
+
else
|
81
|
+
parent = if persist && !attrs[foreign_key]
|
82
|
+
builder.persistable.create(*parent_traits, **assoc_data)
|
56
83
|
else
|
57
|
-
builder.struct(
|
84
|
+
builder.struct(
|
85
|
+
*parent_traits,
|
86
|
+
**assoc_data.merge(assoc.target.primary_key => attrs[foreign_key])
|
87
|
+
)
|
58
88
|
end
|
59
|
-
|
60
|
-
|
89
|
+
|
90
|
+
tuple = {name => parent}
|
91
|
+
|
92
|
+
assoc.associate(tuple, parent)
|
61
93
|
end
|
62
94
|
end
|
95
|
+
# rubocop:enable Metrics/AbcSize
|
63
96
|
|
64
|
-
|
65
|
-
|
66
|
-
|
97
|
+
private
|
98
|
+
|
99
|
+
def parent_traits
|
100
|
+
@parent_traits ||=
|
101
|
+
if assoc.target.associations.key?(assoc.source.name)
|
102
|
+
traits + [assoc.target.associations[assoc.source.name].key => false]
|
103
|
+
else
|
104
|
+
traits
|
105
|
+
end
|
67
106
|
end
|
68
107
|
end
|
69
108
|
|
@@ -78,24 +117,19 @@ module ROM::Factory
|
|
78
117
|
association_hash = assoc.associate(attrs, parent)
|
79
118
|
|
80
119
|
if persist
|
81
|
-
builder.persistable.create(*traits, association_hash)
|
120
|
+
builder.persistable.create(*traits, **association_hash)
|
82
121
|
else
|
83
|
-
builder.struct(*traits, attrs
|
122
|
+
builder.struct(*traits, **attrs, **association_hash)
|
84
123
|
end
|
85
124
|
end
|
86
125
|
|
87
|
-
{
|
126
|
+
{name => structs}
|
88
127
|
end
|
89
128
|
|
90
129
|
# @api private
|
91
130
|
def dependency?(rel)
|
92
131
|
assoc.source == rel
|
93
132
|
end
|
94
|
-
|
95
|
-
# @api private
|
96
|
-
def count
|
97
|
-
options.fetch(:count)
|
98
|
-
end
|
99
133
|
end
|
100
134
|
|
101
135
|
# @api private
|
@@ -103,29 +137,93 @@ module ROM::Factory
|
|
103
137
|
# @api private
|
104
138
|
def call(attrs = EMPTY_HASH, parent, persist: true)
|
105
139
|
# do not associate if count is 0
|
106
|
-
return {
|
140
|
+
return {name => nil} if count.zero?
|
107
141
|
|
108
142
|
return if attrs.key?(name)
|
109
143
|
|
110
144
|
association_hash = assoc.associate(attrs, parent)
|
111
145
|
|
112
146
|
struct = if persist
|
113
|
-
builder.persistable.create(*traits, association_hash)
|
147
|
+
builder.persistable.create(*traits, **association_hash)
|
114
148
|
else
|
115
149
|
belongs_to_name = Dry::Core::Inflector.singularize(assoc.source_alias)
|
116
|
-
belongs_to_associations = {
|
150
|
+
belongs_to_associations = {belongs_to_name.to_sym => parent}
|
117
151
|
final_attrs = attrs.merge(association_hash).merge(belongs_to_associations)
|
118
|
-
builder.struct(*traits, final_attrs)
|
152
|
+
builder.struct(*traits, **final_attrs)
|
119
153
|
end
|
120
154
|
|
121
|
-
{
|
155
|
+
{name => struct}
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
class ManyToMany < Core
|
160
|
+
def call(attrs = EMPTY_HASH, parent, persist: true)
|
161
|
+
return if attrs.key?(name)
|
162
|
+
|
163
|
+
structs = count.times.map do
|
164
|
+
if persist && attrs[tpk]
|
165
|
+
attrs
|
166
|
+
elsif persist
|
167
|
+
builder.persistable.create(*traits, **attrs)
|
168
|
+
else
|
169
|
+
builder.struct(*traits, **attrs)
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
# Delegate to through factory if it exists
|
174
|
+
if persist
|
175
|
+
if through_factory?
|
176
|
+
structs.each do |child|
|
177
|
+
through_attrs = {
|
178
|
+
Dry::Core::Inflector.singularize(assoc.source.name.key).to_sym => parent,
|
179
|
+
assoc.through.assoc_name => child
|
180
|
+
}
|
181
|
+
|
182
|
+
factories[through_factory_name, **through_attrs]
|
183
|
+
end
|
184
|
+
else
|
185
|
+
assoc.persist([parent], structs)
|
186
|
+
end
|
187
|
+
|
188
|
+
{name => result(structs)}
|
189
|
+
else
|
190
|
+
result(structs)
|
191
|
+
end
|
122
192
|
end
|
123
193
|
|
124
|
-
|
125
|
-
|
126
|
-
|
194
|
+
def result(structs)
|
195
|
+
{name => structs}
|
196
|
+
end
|
197
|
+
|
198
|
+
def dependency?(rel)
|
199
|
+
assoc.source == rel
|
200
|
+
end
|
201
|
+
|
202
|
+
def through?
|
203
|
+
true
|
204
|
+
end
|
205
|
+
|
206
|
+
def through_factory?
|
207
|
+
factories.registry.key?(through_factory_name)
|
208
|
+
end
|
209
|
+
|
210
|
+
def through_factory_name
|
211
|
+
ROM::Inflector.singularize(assoc.definition.through.source).to_sym
|
212
|
+
end
|
213
|
+
|
214
|
+
private
|
215
|
+
|
216
|
+
def tpk
|
217
|
+
assoc.target.primary_key
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
class OneToOneThrough < ManyToMany
|
222
|
+
def result(structs)
|
223
|
+
{name => structs[0]}
|
127
224
|
end
|
128
225
|
end
|
129
226
|
end
|
130
227
|
end
|
228
|
+
# rubocop:enable Style/OptionalArguments
|
131
229
|
end
|
@@ -1,14 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'dry/core/constants'
|
4
|
-
|
5
3
|
module ROM
|
6
4
|
module Factory
|
7
5
|
include Dry::Core::Constants
|
8
6
|
end
|
9
7
|
end
|
10
8
|
|
11
|
-
require
|
12
|
-
require
|
13
|
-
require
|
14
|
-
require
|
9
|
+
require "rom/factory/attributes/value"
|
10
|
+
require "rom/factory/attributes/callable"
|
11
|
+
require "rom/factory/attributes/sequence"
|
12
|
+
require "rom/factory/attributes/association"
|