rom-factory 0.10.2 → 0.11.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/.action_hero.yml +21 -0
- 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 +14 -23
- data/.github/workflows/docsite.yml +5 -4
- data/.github/workflows/rubocop.yml +46 -0
- data/.github/workflows/sync_configs.yml +17 -17
- data/.rubocop.yml +135 -16
- data/CHANGELOG.md +44 -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 +23 -0
- data/docsite/source/index.html.md +162 -1
- data/lib/rom/factory/attribute_registry.rb +2 -2
- data/lib/rom/factory/attributes/association.rb +52 -12
- 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 +3 -5
- data/lib/rom/factory/builder.rb +8 -18
- data/lib/rom/factory/constants.rb +1 -1
- data/lib/rom/factory/dsl.rb +36 -24
- data/lib/rom/factory/factories.rb +13 -15
- data/lib/rom/factory/registry.rb +2 -2
- data/lib/rom/factory/sequences.rb +1 -1
- data/lib/rom/factory/tuple_evaluator.rb +18 -22
- 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 +38 -24
- 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", "~> 2.8"
|
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", "~> 0.12.0", "<= 0.13"
|
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", "~> 0.21", 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,27 @@
|
|
1
1
|
---
|
2
|
+
- version: 0.11.0
|
3
|
+
date: 2022-11-11
|
4
|
+
added:
|
5
|
+
- Support for one-to-one associations (@ianks)
|
6
|
+
- "[internal] cache for Faker constants (@flash-gordon)"
|
7
|
+
changed:
|
8
|
+
- |
|
9
|
+
[BREAKING] attributes are always passed as keywords (@alassek)
|
10
|
+
This may affect your code in places where attributes are passed as hashes.
|
11
|
+
Places like
|
12
|
+
```ruby
|
13
|
+
user_attributes = { name: 'Jane' }
|
14
|
+
Factory[:user, user_attributes]
|
15
|
+
```
|
16
|
+
must be updated to
|
17
|
+
```ruby
|
18
|
+
user_attributes = { name: 'Jane' }
|
19
|
+
Factory[:user, **user_attributes]
|
20
|
+
```
|
21
|
+
- "Upgraded to the latest versions of dry-rb dependencies, compatible with rom 5.3 (@flash-gordon)"
|
22
|
+
- Support for Faker 1.x was dropped (@alassek)
|
23
|
+
fixed:
|
24
|
+
- Support for plural Faker generators (@wuarmin)
|
2
25
|
- version: 0.10.2
|
3
26
|
date: "2020-04-05"
|
4
27
|
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 find 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(:user)
|
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,7 @@ 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
51
|
end
|
52
52
|
|
53
53
|
private
|
@@ -5,10 +5,9 @@ module ROM::Factory
|
|
5
5
|
# @api private
|
6
6
|
module Association
|
7
7
|
class << self
|
8
|
-
def new(assoc, builder, *
|
9
|
-
const_get(assoc.definition.type).new(assoc, builder, *
|
8
|
+
def new(assoc, builder, *traits, **options)
|
9
|
+
const_get(assoc.definition.type).new(assoc, builder, *traits, **options)
|
10
10
|
end
|
11
|
-
ruby2_keywords(:new) if respond_to?(:ruby2_keywords, true)
|
12
11
|
end
|
13
12
|
|
14
13
|
# @api private
|
@@ -23,6 +22,11 @@ module ROM::Factory
|
|
23
22
|
@options = options
|
24
23
|
end
|
25
24
|
|
25
|
+
# @api private
|
26
|
+
def through?
|
27
|
+
false
|
28
|
+
end
|
29
|
+
|
26
30
|
# @api private
|
27
31
|
def builder
|
28
32
|
@__builder__ ||= @builder_proc.call
|
@@ -56,7 +60,7 @@ module ROM::Factory
|
|
56
60
|
else
|
57
61
|
builder.struct(*traits)
|
58
62
|
end
|
59
|
-
tuple = {
|
63
|
+
tuple = {name => struct}
|
60
64
|
assoc.associate(tuple, struct)
|
61
65
|
end
|
62
66
|
end
|
@@ -78,13 +82,13 @@ module ROM::Factory
|
|
78
82
|
association_hash = assoc.associate(attrs, parent)
|
79
83
|
|
80
84
|
if persist
|
81
|
-
builder.persistable.create(*traits, association_hash)
|
85
|
+
builder.persistable.create(*traits, **association_hash)
|
82
86
|
else
|
83
|
-
builder.struct(*traits, attrs
|
87
|
+
builder.struct(*traits, **attrs, **association_hash)
|
84
88
|
end
|
85
89
|
end
|
86
90
|
|
87
|
-
{
|
91
|
+
{name => structs}
|
88
92
|
end
|
89
93
|
|
90
94
|
# @api private
|
@@ -103,22 +107,22 @@ module ROM::Factory
|
|
103
107
|
# @api private
|
104
108
|
def call(attrs = EMPTY_HASH, parent, persist: true)
|
105
109
|
# do not associate if count is 0
|
106
|
-
return {
|
110
|
+
return {name => nil} if count.zero?
|
107
111
|
|
108
112
|
return if attrs.key?(name)
|
109
113
|
|
110
114
|
association_hash = assoc.associate(attrs, parent)
|
111
115
|
|
112
116
|
struct = if persist
|
113
|
-
builder.persistable.create(*traits, association_hash)
|
117
|
+
builder.persistable.create(*traits, **association_hash)
|
114
118
|
else
|
115
119
|
belongs_to_name = Dry::Core::Inflector.singularize(assoc.source_alias)
|
116
|
-
belongs_to_associations = {
|
120
|
+
belongs_to_associations = {belongs_to_name.to_sym => parent}
|
117
121
|
final_attrs = attrs.merge(association_hash).merge(belongs_to_associations)
|
118
|
-
builder.struct(*traits, final_attrs)
|
122
|
+
builder.struct(*traits, **final_attrs)
|
119
123
|
end
|
120
124
|
|
121
|
-
{
|
125
|
+
{name => struct}
|
122
126
|
end
|
123
127
|
|
124
128
|
# @api private
|
@@ -126,6 +130,42 @@ module ROM::Factory
|
|
126
130
|
options.fetch(:count, 1)
|
127
131
|
end
|
128
132
|
end
|
133
|
+
|
134
|
+
class OneToOneThrough < Core
|
135
|
+
def call(attrs = EMPTY_HASH, parent, persist: true)
|
136
|
+
return if attrs.key?(name)
|
137
|
+
|
138
|
+
struct = if persist && attrs[tpk]
|
139
|
+
attrs
|
140
|
+
elsif persist
|
141
|
+
builder.persistable.create(*traits, **attrs)
|
142
|
+
else
|
143
|
+
builder.struct(*traits, **attrs)
|
144
|
+
end
|
145
|
+
|
146
|
+
assoc.persist([parent], struct) if persist
|
147
|
+
|
148
|
+
{name => struct}
|
149
|
+
end
|
150
|
+
|
151
|
+
def dependency?(rel)
|
152
|
+
assoc.source == rel
|
153
|
+
end
|
154
|
+
|
155
|
+
def through?
|
156
|
+
true
|
157
|
+
end
|
158
|
+
|
159
|
+
private
|
160
|
+
|
161
|
+
def count
|
162
|
+
options.fetch(:count, 1)
|
163
|
+
end
|
164
|
+
|
165
|
+
def tpk
|
166
|
+
assoc.target.primary_key
|
167
|
+
end
|
168
|
+
end
|
129
169
|
end
|
130
170
|
end
|
131
171
|
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"
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "delegate"
|
4
4
|
|
5
5
|
module ROM
|
6
6
|
module Factory
|
@@ -21,10 +21,8 @@ module ROM
|
|
21
21
|
end
|
22
22
|
|
23
23
|
# @api private
|
24
|
-
def create(*
|
25
|
-
traits, attrs
|
26
|
-
|
27
|
-
tuple = tuple(*traits, attrs)
|
24
|
+
def create(*traits, **attrs)
|
25
|
+
tuple = tuple(*traits, **attrs)
|
28
26
|
validate_keys(traits, attrs)
|
29
27
|
persisted = persist(tuple)
|
30
28
|
|
data/lib/rom/factory/builder.rb
CHANGED
@@ -1,11 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require 'rom/factory/tuple_evaluator'
|
8
|
-
require 'rom/factory/builder/persistable'
|
3
|
+
require "rom/struct"
|
4
|
+
require "rom/initializer"
|
5
|
+
require "rom/factory/tuple_evaluator"
|
6
|
+
require "rom/factory/builder/persistable"
|
9
7
|
|
10
8
|
module ROM::Factory
|
11
9
|
# @api private
|
@@ -31,18 +29,15 @@ module ROM::Factory
|
|
31
29
|
option :struct_namespace, reader: false
|
32
30
|
|
33
31
|
# @api private
|
34
|
-
def tuple(*
|
35
|
-
traits, attrs = extract_tuple(args)
|
36
|
-
|
32
|
+
def tuple(*traits, **attrs)
|
37
33
|
tuple_evaluator.defaults(traits, attrs)
|
38
34
|
end
|
39
35
|
|
40
36
|
# @api private
|
41
|
-
def struct(*
|
42
|
-
traits, attrs = extract_tuple(args)
|
37
|
+
def struct(*traits, **attrs)
|
43
38
|
validate_keys(traits, attrs, allow_associations: true)
|
44
39
|
|
45
|
-
tuple_evaluator.struct(*
|
40
|
+
tuple_evaluator.struct(*traits, **attrs)
|
46
41
|
end
|
47
42
|
alias_method :create, :struct
|
48
43
|
|
@@ -75,18 +70,13 @@ module ROM::Factory
|
|
75
70
|
tuple_evaluator.relation
|
76
71
|
end
|
77
72
|
|
78
|
-
# @api private
|
79
|
-
def extract_tuple(args)
|
80
|
-
tuple_evaluator.extract_tuple(args)
|
81
|
-
end
|
82
|
-
|
83
73
|
# @api private
|
84
74
|
def validate_keys(traits, tuple, allow_associations: false)
|
85
75
|
schema_keys = relation.schema.attributes.map(&:name)
|
86
76
|
assoc_keys = tuple_evaluator.assoc_names(traits)
|
87
77
|
unknown_keys = tuple.keys - schema_keys - assoc_keys
|
88
78
|
|
89
|
-
unknown_keys
|
79
|
+
unknown_keys -= relation.schema.associations.to_h.keys if allow_associations
|
90
80
|
|
91
81
|
raise UnknownFactoryAttributes, unknown_keys unless unknown_keys.empty?
|
92
82
|
end
|