hanami-model 1.0.0 → 1.0.1
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/CHANGELOG.md +6 -0
- data/hanami-model.gemspec +5 -5
- data/lib/hanami/entity.rb +2 -3
- data/lib/hanami/entity/schema.rb +3 -3
- data/lib/hanami/model.rb +1 -1
- data/lib/hanami/model/plugins/mapping.rb +2 -2
- data/lib/hanami/model/plugins/schema.rb +2 -2
- data/lib/hanami/model/plugins/timestamps.rb +2 -2
- data/lib/hanami/model/relation_name.rb +2 -2
- data/lib/hanami/model/sql/entity/schema.rb +16 -0
- data/lib/hanami/model/sql/types.rb +37 -23
- data/lib/hanami/model/sql/types/schema/coercions.rb +4 -1
- data/lib/hanami/model/version.rb +1 -1
- data/lib/hanami/repository.rb +16 -7
- metadata +13 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bb1fca18a6f84f606883ffab656334c1b8e619f6
|
4
|
+
data.tar.gz: 8d2884fbd3bfda01dc6390b4271280cfffe1abc2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4af0a977d17c5cab779ba6b7fefc91b5e94ffa927324439ed99d45fd468000289f564f151c48e1926e2e603052967077517e055735dbe719152a021ccb2c7282
|
7
|
+
data.tar.gz: f4c30f92ab810dde2c9678d8352bec0787e2c446235e70a078e7a419913bf2fc59d8d0fdcd30727be296085b74f7dc89f300bb57cca463437cf94805ce2b2800
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,12 @@
|
|
1
1
|
# Hanami::Model
|
2
2
|
A persistence layer for Hanami
|
3
3
|
|
4
|
+
## v1.0.1 - 2017-06-23
|
5
|
+
### Fixed
|
6
|
+
- [Kai Kuchenbecker & Marcello Rocha & Luca Guidi] Ensure `Hanami::Entity#initialize` to not serialize (into `Hash`) other entities passed as an argument
|
7
|
+
- [Luca Guidi] Let `Hanami::Repository.relation=` to accept strings as an argument
|
8
|
+
- [Nikita Shilnikov] Prevent stack-overflow when `Hanami::Repository#update` is called thousand times
|
9
|
+
|
4
10
|
## v1.0.0 - 2017-04-06
|
5
11
|
|
6
12
|
## v1.0.0.rc1 - 2017-03-31
|
data/hanami-model.gemspec
CHANGED
@@ -21,12 +21,12 @@ Gem::Specification.new do |spec|
|
|
21
21
|
spec.required_ruby_version = '>= 2.3.0'
|
22
22
|
|
23
23
|
spec.add_runtime_dependency 'hanami-utils', '~> 1.0'
|
24
|
-
spec.add_runtime_dependency 'rom-sql', '~> 1.
|
24
|
+
spec.add_runtime_dependency 'rom-sql', '~> 1.3'
|
25
25
|
spec.add_runtime_dependency 'rom-repository', '~> 1.3'
|
26
|
-
spec.add_runtime_dependency 'dry-types', '~> 0.
|
26
|
+
spec.add_runtime_dependency 'dry-types', '~> 0.10'
|
27
27
|
spec.add_runtime_dependency 'concurrent-ruby', '~> 1.0'
|
28
28
|
|
29
|
-
spec.add_development_dependency 'bundler',
|
30
|
-
spec.add_development_dependency '
|
31
|
-
spec.add_development_dependency '
|
29
|
+
spec.add_development_dependency 'bundler', '~> 1.6'
|
30
|
+
spec.add_development_dependency 'rake', '~> 11'
|
31
|
+
spec.add_development_dependency 'rspec', '~> 3.5'
|
32
32
|
end
|
data/lib/hanami/entity.rb
CHANGED
@@ -19,8 +19,7 @@ module Hanami
|
|
19
19
|
# @example With Hanami::Entity
|
20
20
|
# require 'hanami/model'
|
21
21
|
#
|
22
|
-
# class Person
|
23
|
-
# include Hanami::Entity
|
22
|
+
# class Person < Hanami::Entity
|
24
23
|
# end
|
25
24
|
#
|
26
25
|
# If we expand the code above in **pure Ruby**, it would be:
|
@@ -183,7 +182,7 @@ module Hanami
|
|
183
182
|
#
|
184
183
|
# @since 0.1.0
|
185
184
|
def to_h
|
186
|
-
|
185
|
+
Utils::Hash.deep_dup(attributes)
|
187
186
|
end
|
188
187
|
|
189
188
|
# @since 0.7.0
|
data/lib/hanami/entity/schema.rb
CHANGED
@@ -73,7 +73,7 @@ module Hanami
|
|
73
73
|
if attributes.nil?
|
74
74
|
{}
|
75
75
|
else
|
76
|
-
attributes.dup
|
76
|
+
Utils::Hash.deep_symbolize(attributes.to_hash.dup)
|
77
77
|
end
|
78
78
|
end
|
79
79
|
|
@@ -221,9 +221,9 @@ module Hanami
|
|
221
221
|
# @since 0.7.0
|
222
222
|
# @api private
|
223
223
|
def call(attributes)
|
224
|
-
Utils::Hash.
|
224
|
+
Utils::Hash.deep_symbolize(
|
225
225
|
schema.call(attributes)
|
226
|
-
)
|
226
|
+
)
|
227
227
|
end
|
228
228
|
|
229
229
|
# @since 0.7.0
|
data/lib/hanami/model.rb
CHANGED
@@ -37,8 +37,8 @@ module Hanami
|
|
37
37
|
# @since 0.7.0
|
38
38
|
# @api private
|
39
39
|
def build(relation, options = {})
|
40
|
-
|
41
|
-
super(relation, options.merge(input:
|
40
|
+
wrapped_input = InputWithMapping.new(relation, options.fetch(:input) { input })
|
41
|
+
super(relation, options.merge(input: wrapped_input))
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
@@ -37,8 +37,8 @@ module Hanami
|
|
37
37
|
# @since 0.7.0
|
38
38
|
# @api private
|
39
39
|
def build(relation, options = {})
|
40
|
-
|
41
|
-
super(relation, options.merge(input:
|
40
|
+
wrapped_input = InputWithSchema.new(relation, options.fetch(:input) { input })
|
41
|
+
super(relation, options.merge(input: wrapped_input))
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
@@ -100,8 +100,8 @@ module Hanami
|
|
100
100
|
InputWithUpdateTimestamp
|
101
101
|
end
|
102
102
|
|
103
|
-
|
104
|
-
super(relation, options.merge(input:
|
103
|
+
wrapped_input = plugin.new(relation, options.fetch(:input) { input })
|
104
|
+
super(relation, options.merge(input: wrapped_input))
|
105
105
|
end
|
106
106
|
end
|
107
107
|
|
@@ -12,12 +12,12 @@ module Hanami
|
|
12
12
|
# @api private
|
13
13
|
class RelationName < EntityName
|
14
14
|
# @param name [Class,String] the class or its name
|
15
|
-
# @return [
|
15
|
+
# @return [String] the relation name
|
16
16
|
#
|
17
17
|
# @since 0.7.0
|
18
18
|
# @api private
|
19
19
|
def self.new(name)
|
20
|
-
Utils::String.new(super).underscore.pluralize
|
20
|
+
Utils::String.new(super).underscore.pluralize
|
21
21
|
end
|
22
22
|
end
|
23
23
|
end
|
@@ -38,6 +38,22 @@ module Hanami
|
|
38
38
|
freeze
|
39
39
|
end
|
40
40
|
|
41
|
+
# Process attributes
|
42
|
+
#
|
43
|
+
# @param attributes [#to_hash] the attributes hash
|
44
|
+
#
|
45
|
+
# @raise [TypeError] if the process fails
|
46
|
+
#
|
47
|
+
# @since 1.0.1
|
48
|
+
# @api private
|
49
|
+
def call(attributes)
|
50
|
+
schema.call(attributes)
|
51
|
+
end
|
52
|
+
|
53
|
+
# @since 1.0.1
|
54
|
+
# @api private
|
55
|
+
alias [] call
|
56
|
+
|
41
57
|
# Check if the attribute is known
|
42
58
|
#
|
43
59
|
# @param name [Symbol] the attribute name
|
@@ -29,31 +29,31 @@ module Hanami
|
|
29
29
|
Time = Types::Strict::Nil | Types::Time.constructor(Coercions.method(:time))
|
30
30
|
|
31
31
|
Array = Types::Strict::Nil | Types::Array.constructor(Coercions.method(:array))
|
32
|
-
Hash = Types::Strict::Nil | Types::
|
32
|
+
Hash = Types::Strict::Nil | Types::Hash.constructor(Coercions.method(:hash))
|
33
33
|
|
34
34
|
# @since 0.7.0
|
35
35
|
# @api private
|
36
36
|
MAPPING = {
|
37
|
-
Types::String.
|
38
|
-
Types::Int.
|
39
|
-
Types::Float.
|
40
|
-
Types::Decimal.
|
41
|
-
Types::Bool.
|
42
|
-
Types::Date.
|
43
|
-
Types::DateTime.
|
44
|
-
Types::Time.
|
45
|
-
Types::Array.
|
46
|
-
Types::Hash.
|
47
|
-
Types::String.optional.
|
48
|
-
Types::Int.optional.
|
49
|
-
Types::Float.optional.
|
50
|
-
Types::Decimal.optional.
|
51
|
-
Types::Bool.optional.
|
52
|
-
Types::Date.optional.
|
53
|
-
Types::DateTime.optional.
|
54
|
-
Types::Time.optional.
|
55
|
-
Types::Array.optional.
|
56
|
-
Types::Hash.optional.
|
37
|
+
Types::String.pristine => Schema::String,
|
38
|
+
Types::Int.pristine => Schema::Int,
|
39
|
+
Types::Float.pristine => Schema::Float,
|
40
|
+
Types::Decimal.pristine => Schema::Decimal,
|
41
|
+
Types::Bool.pristine => Schema::Bool,
|
42
|
+
Types::Date.pristine => Schema::Date,
|
43
|
+
Types::DateTime.pristine => Schema::DateTime,
|
44
|
+
Types::Time.pristine => Schema::Time,
|
45
|
+
Types::Array.pristine => Schema::Array,
|
46
|
+
Types::Hash.pristine => Schema::Hash,
|
47
|
+
Types::String.optional.pristine => Schema::String,
|
48
|
+
Types::Int.optional.pristine => Schema::Int,
|
49
|
+
Types::Float.optional.pristine => Schema::Float,
|
50
|
+
Types::Decimal.optional.pristine => Schema::Decimal,
|
51
|
+
Types::Bool.optional.pristine => Schema::Bool,
|
52
|
+
Types::Date.optional.pristine => Schema::Date,
|
53
|
+
Types::DateTime.optional.pristine => Schema::DateTime,
|
54
|
+
Types::Time.optional.pristine => Schema::Time,
|
55
|
+
Types::Array.optional.pristine => Schema::Array,
|
56
|
+
Types::Hash.optional.pristine => Schema::Hash
|
57
57
|
}.freeze
|
58
58
|
|
59
59
|
# Convert given type into coercible
|
@@ -62,8 +62,22 @@ module Hanami
|
|
62
62
|
# @api private
|
63
63
|
def self.coercible(attribute)
|
64
64
|
return attribute if attribute.constrained?
|
65
|
-
|
66
|
-
|
65
|
+
|
66
|
+
type = attribute.type
|
67
|
+
unwrapped = type.optional? ? type.right : type
|
68
|
+
|
69
|
+
# NOTE: In the future rom-sql should be able to always return Ruby
|
70
|
+
# types instead of Sequel types. When that will happen we can get
|
71
|
+
# rid of this logic in the block and to fallback to:
|
72
|
+
#
|
73
|
+
# MAPPING.fetch(unwrapped.pristine, attribute)
|
74
|
+
MAPPING.fetch(unwrapped.pristine) do
|
75
|
+
if defined?(ROM::SQL::Types::PG::JSONB) && unwrapped.pristine == ROM::SQL::Types::PG::JSONB
|
76
|
+
Schema::Hash
|
77
|
+
else
|
78
|
+
attribute
|
79
|
+
end
|
80
|
+
end
|
67
81
|
end
|
68
82
|
|
69
83
|
# Coercer for SQL associations target
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'hanami/utils/string'
|
2
|
+
require 'hanami/utils/hash'
|
2
3
|
|
3
4
|
module Hanami
|
4
5
|
module Model
|
@@ -184,7 +185,9 @@ module Hanami
|
|
184
185
|
when ::Hash
|
185
186
|
arg
|
186
187
|
when ->(a) { a.respond_to?(:to_hash) }
|
187
|
-
::
|
188
|
+
Utils::Hash.deep_symbolize(
|
189
|
+
::Kernel.Hash(arg)
|
190
|
+
)
|
188
191
|
else
|
189
192
|
raise ArgumentError.new("invalid value for Hash(): #{arg.inspect}")
|
190
193
|
end
|
data/lib/hanami/model/version.rb
CHANGED
data/lib/hanami/repository.rb
CHANGED
@@ -6,6 +6,7 @@ require 'hanami/model/associations/dsl'
|
|
6
6
|
require 'hanami/model/association'
|
7
7
|
require 'hanami/utils/class'
|
8
8
|
require 'hanami/utils/class_attribute'
|
9
|
+
require 'hanami/utils/io'
|
9
10
|
|
10
11
|
module Hanami
|
11
12
|
# Mediates between the entities and the persistence layer, by offering an API
|
@@ -19,8 +20,7 @@ module Hanami
|
|
19
20
|
# @example
|
20
21
|
# require 'hanami/model'
|
21
22
|
#
|
22
|
-
# class Article
|
23
|
-
# include Hanami::Entity
|
23
|
+
# class Article < Hanami::Entity
|
24
24
|
# end
|
25
25
|
#
|
26
26
|
# # valid
|
@@ -107,7 +107,7 @@ module Hanami
|
|
107
107
|
# @see Hanami::Entity
|
108
108
|
# @see http://martinfowler.com/eaaCatalog/repository.html
|
109
109
|
# @see http://en.wikipedia.org/wiki/Dependency_inversion_principle
|
110
|
-
class Repository < ROM::Repository::Root
|
110
|
+
class Repository < ROM::Repository::Root # rubocop:disable Metrics/ClassLength
|
111
111
|
# Plugins for database commands
|
112
112
|
#
|
113
113
|
# @since 0.7.0
|
@@ -282,13 +282,22 @@ module Hanami
|
|
282
282
|
include Utils::ClassAttribute
|
283
283
|
auto_struct true
|
284
284
|
|
285
|
-
|
285
|
+
@associations = nil
|
286
|
+
@mapping = nil
|
287
|
+
@schema = nil
|
286
288
|
|
289
|
+
class_attribute :entity
|
287
290
|
class_attribute :entity_name
|
288
|
-
self.entity_name = Model::EntityName.new(name)
|
289
|
-
|
290
291
|
class_attribute :relation
|
291
|
-
|
292
|
+
|
293
|
+
Hanami::Utils::IO.silence_warnings do
|
294
|
+
def self.relation=(name)
|
295
|
+
@relation = name.to_sym
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
299
|
+
self.entity_name = Model::EntityName.new(name)
|
300
|
+
self.relation = Model::RelationName.new(name)
|
292
301
|
|
293
302
|
commands :create, update: :by_pk, delete: :by_pk, mapper: Model::MappedRelation.mapper_name, use: COMMAND_PLUGINS
|
294
303
|
prepend Commands
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hanami-model
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Luca Guidi
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-06-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: hanami-utils
|
@@ -30,14 +30,14 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '1.
|
33
|
+
version: '1.3'
|
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: '1.
|
40
|
+
version: '1.3'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rom-repository
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -58,14 +58,14 @@ dependencies:
|
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '0.
|
61
|
+
version: '0.10'
|
62
62
|
type: :runtime
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '0.
|
68
|
+
version: '0.10'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: concurrent-ruby
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -95,33 +95,33 @@ dependencies:
|
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '1.6'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
|
-
name:
|
98
|
+
name: rake
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
101
|
- - "~>"
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version: '
|
103
|
+
version: '11'
|
104
104
|
type: :development
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
108
|
- - "~>"
|
109
109
|
- !ruby/object:Gem::Version
|
110
|
-
version: '
|
110
|
+
version: '11'
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
|
-
name:
|
112
|
+
name: rspec
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
114
114
|
requirements:
|
115
115
|
- - "~>"
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version: '
|
117
|
+
version: '3.5'
|
118
118
|
type: :development
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
121
|
requirements:
|
122
122
|
- - "~>"
|
123
123
|
- !ruby/object:Gem::Version
|
124
|
-
version: '
|
124
|
+
version: '3.5'
|
125
125
|
description: A persistence framework with entities and repositories
|
126
126
|
email:
|
127
127
|
- me@lucaguidi.com
|
@@ -192,7 +192,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
192
192
|
version: '0'
|
193
193
|
requirements: []
|
194
194
|
rubyforge_project:
|
195
|
-
rubygems_version: 2.6.
|
195
|
+
rubygems_version: 2.6.12
|
196
196
|
signing_key:
|
197
197
|
specification_version: 4
|
198
198
|
summary: A persistence layer for Hanami
|