hanami-model 1.0.0 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|