diva 0.3.2 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 68d766412779aaedc71ea2ab874be3861238afff5b896d4d4bdab9e50e2c5103
4
- data.tar.gz: 7ca9cc8bec5f1b284fe51b078501831572519263feab02619b641ee7498543bd
3
+ metadata.gz: 65b2025d22ea687dfa98ca063ca511630ce75a4928e0e6be9581f7b6f2216ce2
4
+ data.tar.gz: 6b514157b95438022b2b28ab72b0af436489e3f8edf8e8c12bca80e1298a1b69
5
5
  SHA512:
6
- metadata.gz: 77ca8065a2a25a922bebdf0fe297242363f17e4277f411f4f72ece8ed0b61e26893452c6683d7815a55c96e5944f58e86436d77d38952fc9bf30c97c24e2c815
7
- data.tar.gz: 77627879b34087e1a4877125c54c489b0b799d768fee187bffff8f237e337cce67981ccae60eaa7481b964bbe841fd02bbed68740ab5f972f60c7aa7b7ac6517
6
+ metadata.gz: ea64c7762bc79c8c4eba0f9ac41fd3622a3af663c2a9f2057175695da9ba0f9226b4dbb71133e91c288dfc2799cdfae6d075fb84dab1905cc19ec2b7081b7045
7
+ data.tar.gz: af41fb3db4368b08f71af3cc1886ae44553865d4797f6402278ec1a6a812e2095e94ec752785734592c09f757f58fcde3198e185efc49a494260692dd2afb45f
@@ -18,11 +18,11 @@ Gem::Specification.new do |spec|
18
18
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
19
  spec.require_paths = ["lib"]
20
20
 
21
- spec.add_development_dependency "bundler", "~> 1.12"
22
- spec.add_development_dependency "rake", "~> 10.0"
23
- spec.add_development_dependency "minitest", "~> 5.0"
24
- spec.add_development_dependency "pry"
25
- spec.add_development_dependency "simplecov"
21
+ spec.add_development_dependency "bundler", '>= 1.16.1', '< 2.1'
22
+ spec.add_development_dependency "rake", '>= 12.3.2', '< 13.0'
23
+ spec.add_development_dependency "minitest", '>= 5.11.3', '< 5.12'
24
+ spec.add_development_dependency "pry", '>= 0.12.2', '< 1.0'
25
+ spec.add_development_dependency "simplecov", '>= 0.16.1', '< 1.0'
26
26
 
27
- spec.add_dependency "addressable", ">= 2.5", "< 2.6"
27
+ spec.add_dependency "addressable", ">= 2.5.2", "< 2.7"
28
28
  end
@@ -27,6 +27,13 @@ module Diva
27
27
  required
28
28
  end
29
29
 
30
+ def schema
31
+ {
32
+ name: @name.to_s,
33
+ constraint: @type.schema
34
+ }
35
+ end
36
+
30
37
  def to_sym
31
38
  name
32
39
  end
@@ -3,7 +3,6 @@
3
3
  いろんなリソースの基底クラス
4
4
  =end
5
5
 
6
- require 'diva/combinator'
7
6
  require 'diva/model_extend'
8
7
  require 'diva/uri'
9
8
  require 'diva/spec'
@@ -12,7 +11,6 @@ require 'securerandom'
12
11
 
13
12
  class Diva::Model
14
13
  include Comparable
15
- include Diva::Combinable
16
14
  extend Diva::ModelExtend
17
15
 
18
16
  def initialize(args)
@@ -145,6 +143,16 @@ class Diva::Model
145
143
  end
146
144
  end
147
145
 
146
+ def dig(key, *args)
147
+ return nil unless key.respond_to?(:to_sym)
148
+ value = fetch(key)
149
+ if value.nil? || args.empty?
150
+ value
151
+ else
152
+ value.dig(*args)
153
+ end
154
+ end
155
+
148
156
  private
149
157
  # URIがデフォルトで使うpath要素
150
158
  def path
@@ -57,6 +57,17 @@ module Diva::ModelExtend
57
57
  alias :keys :fields
58
58
  deprecate :keys, "fields", 2018, 02
59
59
 
60
+ def schema
61
+ {
62
+ fields: fields.map(&:schema),
63
+ uri: uri
64
+ }
65
+ end
66
+
67
+ def uri
68
+ @uri ||= Diva::URI("diva://object.type/#{slug || SecureRandom.uuid}")
69
+ end
70
+
60
71
  #
61
72
  # プライベートクラスメソッド
62
73
  #
@@ -28,6 +28,7 @@ Diva::Modelのサブクラスであれば、それを制約とすることがで
28
28
 
29
29
  =end
30
30
  require "time"
31
+ require 'diva/uri'
31
32
 
32
33
  module Diva::Type
33
34
  extend self
@@ -41,14 +42,18 @@ module Diva::Type
41
42
  end
42
43
 
43
44
  def optional(type)
44
- OptionalType.new(type)
45
+ UnionType.new(NULL, type)
46
+ end
47
+
48
+ def union(*types)
49
+ UnionType.new(*types)
45
50
  end
46
51
 
47
52
  # 全てのType共通のスーパークラス
48
53
  class MetaType
49
54
  attr_reader :name
50
55
 
51
- def initialize(name, *rest, &cast)
56
+ def initialize(name, *, &cast)
52
57
  @name = name.to_sym
53
58
  if cast
54
59
  define_singleton_method :cast, &cast
@@ -73,9 +78,26 @@ module Diva::Type
73
78
  end
74
79
 
75
80
  class AtomicType < MetaType
81
+ def initialize(name, recommended_class, *rest, &cast)
82
+ super(name, *rest, &cast)
83
+ @recommended_classes = Array(recommended_class)
84
+ end
85
+
86
+ def recommendation_point(value)
87
+ _, point = @recommended_classes.map.with_index{|k, i| [k, i] }.find{|k, _| value.is_a?(k) }
88
+ point
89
+ end
90
+
91
+ def schema
92
+ @schema ||= {type: uri}.freeze
93
+ end
94
+
95
+ def uri
96
+ @uri ||= Diva::URI("diva://atomic.type/#{name}")
97
+ end
76
98
  end
77
99
 
78
- INT = AtomicType.new(:int) do |v|
100
+ INT = AtomicType.new(:int, [Integer]) do |v|
79
101
  case v
80
102
  when Integer
81
103
  v
@@ -89,7 +111,7 @@ module Diva::Type
89
111
  raise Diva::InvalidTypeError, "The value is not a `#{name}'."
90
112
  end
91
113
  end
92
- FLOAT = AtomicType.new(:float) do |v|
114
+ FLOAT = AtomicType.new(:float, [Float]) do |v|
93
115
  case v
94
116
  when Float
95
117
  v
@@ -99,7 +121,7 @@ module Diva::Type
99
121
  raise Diva::InvalidTypeError, "The value is not a `#{name}'."
100
122
  end
101
123
  end
102
- BOOL = AtomicType.new(:bool) do |v|
124
+ BOOL = AtomicType.new(:bool, [TrueClass, FalseClass]) do |v|
103
125
  case v
104
126
  when TrueClass, FalseClass
105
127
  v
@@ -111,7 +133,7 @@ module Diva::Type
111
133
  raise Diva::InvalidTypeError, "The value is not a `#{name}'."
112
134
  end
113
135
  end
114
- STRING = AtomicType.new(:string) do |v|
136
+ STRING = AtomicType.new(:string, String) do |v|
115
137
  case v
116
138
  when Diva::Model, Enumerable
117
139
  raise Diva::InvalidTypeError, "The value is not a `#{name}'."
@@ -124,7 +146,7 @@ module Diva::Type
124
146
  cast(value).iso8601
125
147
  end
126
148
  end
127
- TIME = TimeType.new(:time) do |v|
149
+ TIME = TimeType.new(:time, [Time, String]) do |v|
128
150
  case v
129
151
  when Time
130
152
  v
@@ -136,7 +158,7 @@ module Diva::Type
136
158
  raise Diva::InvalidTypeError, "The value is not a `#{name}'."
137
159
  end
138
160
  end
139
- URI = AtomicType.new(:uri) do |v|
161
+ URI = AtomicType.new(:uri, [Diva::URI, Addressable::URI, ::URI::Generic]) do |v|
140
162
  case v
141
163
  when Diva::URI, Addressable::URI, ::URI::Generic
142
164
  v
@@ -146,6 +168,13 @@ module Diva::Type
146
168
  raise Diva::InvalidTypeError, "The value is not a `#{name}'."
147
169
  end
148
170
  end
171
+ NULL = AtomicType.new(:null, NilClass) do |v|
172
+ if v.nil?
173
+ v
174
+ else
175
+ raise Diva::InvalidTypeError, "The value is not a `#{name}'."
176
+ end
177
+ end
149
178
 
150
179
  class ModelType < MetaType
151
180
  attr_reader :model
@@ -154,6 +183,10 @@ module Diva::Type
154
183
  @model = model
155
184
  end
156
185
 
186
+ def recommendation_point(v)
187
+ v.is_a?(model) && 0
188
+ end
189
+
157
190
  def cast(value)
158
191
  case value
159
192
  when model
@@ -165,9 +198,17 @@ module Diva::Type
165
198
  end
166
199
  end
167
200
 
201
+ def schema
202
+ @schema ||= {type: uri}.freeze
203
+ end
204
+
168
205
  def to_s
169
206
  "#{model} #{name}"
170
207
  end
208
+
209
+ def uri
210
+ model.uri
211
+ end
171
212
  end
172
213
 
173
214
  class ArrayType < MetaType
@@ -177,6 +218,10 @@ module Diva::Type
177
218
  @type = type
178
219
  end
179
220
 
221
+ def recommendation_point(values)
222
+ values.is_a?(Enumerable) && values.all?{|v| @type.recommendation_point(v) } && 0
223
+ end
224
+
180
225
  def cast(value)
181
226
  raise Diva::InvalidTypeError, "The value is not a `#{name}'." unless value.is_a?(Enumerable)
182
227
  value.to_a.map(&@type.method(:cast))
@@ -189,35 +234,55 @@ module Diva::Type
189
234
  def to_s
190
235
  "Array of #{@type.to_s}"
191
236
  end
237
+
238
+ def schema
239
+ @schema ||= { array: @type.schema }.freeze
240
+ end
192
241
  end
193
242
 
194
- class OptionalType < MetaType
195
- def initialize(type)
196
- super("optional_#{type.name}")
197
- @type = type
243
+ class UnionType < MetaType
244
+ def initialize(*types)
245
+ @types = types.flatten.map(&Diva.method(:Type)).freeze
246
+ super("union_#{@types.map(&:name).join('_')}")
247
+ end
248
+
249
+ def recommendation_point(v)
250
+ @types.map{|t| t.recommendation_point(v) }.compact.min
198
251
  end
199
252
 
200
253
  def cast(value)
201
- if value.nil?
202
- value
203
- else
204
- @type.cast(value)
205
- end
254
+ recommended_type_of(value).cast(value)
206
255
  end
207
256
 
208
257
  def dump_for_json(value)
209
- if value.nil?
210
- value
211
- else
212
- @type.dump_for_json(value)
213
- end
258
+ recommended_type_of(value).dump_for_json(value)
214
259
  end
215
260
 
216
261
  def to_s
217
- "#{@type.to_s}|nil"
262
+ @types.map(&:name).join('|').freeze
263
+ end
264
+
265
+ def schema
266
+ @schema ||= { union: @types.map(&:schema) }.freeze
218
267
  end
219
- end
220
268
 
269
+ def recommended_type_of(value)
270
+ @types.map{|t|
271
+ [t, t.recommendation_point(value)]
272
+ }.select{|_,p| p }.sort_by{|_,p| p }.each{|t,_|
273
+ return t
274
+ }
275
+ @types.each do |type|
276
+ begin
277
+ type.cast(value)
278
+ return type
279
+ rescue Diva::InvalidTypeError
280
+ # try next
281
+ end
282
+ end
283
+ raise Diva::InvalidTypeError, "The value is not #{self}"
284
+ end
285
+ end
221
286
  end
222
287
 
223
288
  module Diva
@@ -237,10 +302,16 @@ module Diva
237
302
  Diva::Type::TIME
238
303
  when :uri
239
304
  Diva::Type::URI
305
+ when :null
306
+ Diva::Type::NULL
240
307
  when ->x{x.class == Class && x.ancestors.include?(Diva::Model) }
241
308
  Diva::Type.model_of(type)
242
309
  when Array
243
- Diva::Type.array_of(type.first)
310
+ if type.size >= 2
311
+ Diva::Type.union(*type)
312
+ else
313
+ Diva::Type.array_of(type.first)
314
+ end
244
315
  else
245
316
  fail "Invalid type #{type.inspect} (#{type.class})."
246
317
  end
@@ -32,6 +32,7 @@ require 'addressable/uri'
32
32
 
33
33
  class Diva::URI
34
34
  def initialize(uri)
35
+ @uri = @uri_string = @uri_hash = nil
35
36
  case uri.freeze
36
37
  when URI, Addressable::URI
37
38
  @uri = uri
@@ -96,8 +97,8 @@ class Diva::URI
96
97
  super
97
98
  end
98
99
 
99
- def respond_to?(method)
100
- super or to_uri.respond_to?(method)
100
+ def respond_to_missing?(method, include_private)
101
+ to_uri.respond_to?(method, include_private)
101
102
  end
102
103
 
103
104
  def method_missing(method, *rest, &block)
@@ -1,3 +1,3 @@
1
1
  module Diva
2
- VERSION = "0.3.2"
2
+ VERSION = "1.0.0"
3
3
  end
metadata CHANGED
@@ -1,105 +1,135 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: diva
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Toshiaki Asai
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-04-29 00:00:00.000000000 Z
11
+ date: 2019-06-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 1.16.1
20
+ - - "<"
18
21
  - !ruby/object:Gem::Version
19
- version: '1.12'
22
+ version: '2.1'
20
23
  type: :development
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
23
26
  requirements:
24
- - - "~>"
27
+ - - ">="
25
28
  - !ruby/object:Gem::Version
26
- version: '1.12'
29
+ version: 1.16.1
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '2.1'
27
33
  - !ruby/object:Gem::Dependency
28
34
  name: rake
29
35
  requirement: !ruby/object:Gem::Requirement
30
36
  requirements:
31
- - - "~>"
37
+ - - ">="
32
38
  - !ruby/object:Gem::Version
33
- version: '10.0'
39
+ version: 12.3.2
40
+ - - "<"
41
+ - !ruby/object:Gem::Version
42
+ version: '13.0'
34
43
  type: :development
35
44
  prerelease: false
36
45
  version_requirements: !ruby/object:Gem::Requirement
37
46
  requirements:
38
- - - "~>"
47
+ - - ">="
39
48
  - !ruby/object:Gem::Version
40
- version: '10.0'
49
+ version: 12.3.2
50
+ - - "<"
51
+ - !ruby/object:Gem::Version
52
+ version: '13.0'
41
53
  - !ruby/object:Gem::Dependency
42
54
  name: minitest
43
55
  requirement: !ruby/object:Gem::Requirement
44
56
  requirements:
45
- - - "~>"
57
+ - - ">="
46
58
  - !ruby/object:Gem::Version
47
- version: '5.0'
59
+ version: 5.11.3
60
+ - - "<"
61
+ - !ruby/object:Gem::Version
62
+ version: '5.12'
48
63
  type: :development
49
64
  prerelease: false
50
65
  version_requirements: !ruby/object:Gem::Requirement
51
66
  requirements:
52
- - - "~>"
67
+ - - ">="
53
68
  - !ruby/object:Gem::Version
54
- version: '5.0'
69
+ version: 5.11.3
70
+ - - "<"
71
+ - !ruby/object:Gem::Version
72
+ version: '5.12'
55
73
  - !ruby/object:Gem::Dependency
56
74
  name: pry
57
75
  requirement: !ruby/object:Gem::Requirement
58
76
  requirements:
59
77
  - - ">="
60
78
  - !ruby/object:Gem::Version
61
- version: '0'
79
+ version: 0.12.2
80
+ - - "<"
81
+ - !ruby/object:Gem::Version
82
+ version: '1.0'
62
83
  type: :development
63
84
  prerelease: false
64
85
  version_requirements: !ruby/object:Gem::Requirement
65
86
  requirements:
66
87
  - - ">="
67
88
  - !ruby/object:Gem::Version
68
- version: '0'
89
+ version: 0.12.2
90
+ - - "<"
91
+ - !ruby/object:Gem::Version
92
+ version: '1.0'
69
93
  - !ruby/object:Gem::Dependency
70
94
  name: simplecov
71
95
  requirement: !ruby/object:Gem::Requirement
72
96
  requirements:
73
97
  - - ">="
74
98
  - !ruby/object:Gem::Version
75
- version: '0'
99
+ version: 0.16.1
100
+ - - "<"
101
+ - !ruby/object:Gem::Version
102
+ version: '1.0'
76
103
  type: :development
77
104
  prerelease: false
78
105
  version_requirements: !ruby/object:Gem::Requirement
79
106
  requirements:
80
107
  - - ">="
81
108
  - !ruby/object:Gem::Version
82
- version: '0'
109
+ version: 0.16.1
110
+ - - "<"
111
+ - !ruby/object:Gem::Version
112
+ version: '1.0'
83
113
  - !ruby/object:Gem::Dependency
84
114
  name: addressable
85
115
  requirement: !ruby/object:Gem::Requirement
86
116
  requirements:
87
117
  - - ">="
88
118
  - !ruby/object:Gem::Version
89
- version: '2.5'
119
+ version: 2.5.2
90
120
  - - "<"
91
121
  - !ruby/object:Gem::Version
92
- version: '2.6'
122
+ version: '2.7'
93
123
  type: :runtime
94
124
  prerelease: false
95
125
  version_requirements: !ruby/object:Gem::Requirement
96
126
  requirements:
97
127
  - - ">="
98
128
  - !ruby/object:Gem::Version
99
- version: '2.5'
129
+ version: 2.5.2
100
130
  - - "<"
101
131
  - !ruby/object:Gem::Version
102
- version: '2.6'
132
+ version: '2.7'
103
133
  description:
104
134
  email:
105
135
  - toshi.alternative@gmail.com
@@ -117,7 +147,6 @@ files:
117
147
  - bin/setup
118
148
  - diva.gemspec
119
149
  - lib/diva.rb
120
- - lib/diva/combinator.rb
121
150
  - lib/diva/datasource.rb
122
151
  - lib/diva/error.rb
123
152
  - lib/diva/field.rb
@@ -147,8 +176,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
147
176
  - !ruby/object:Gem::Version
148
177
  version: '0'
149
178
  requirements: []
150
- rubyforge_project:
151
- rubygems_version: 2.7.6
179
+ rubygems_version: 3.0.3
152
180
  signing_key:
153
181
  specification_version: 4
154
182
  summary: Implementation of expression for handling things.
@@ -1,106 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
-
3
- module Diva::Combinable
4
- class Combinator
5
- def initialize(a, b)
6
- @a, @b = a, b
7
- end
8
-
9
- # コンストラクタに渡された二つの値が _behavior_ をサポートしていれば真を返す
10
- # ==== Args
11
- # [behavior] 想定する振る舞い(Symbol)
12
- # ==== Return
13
- # true or false
14
- def =~(behavior)
15
- fail 'Not implement'
16
- end
17
-
18
- def ===(behavior)
19
- self =~ behavior
20
- end
21
-
22
- # このCombinatorが持っている値のすべての組み合わせのうち、適切に _behavior_
23
- # をサポートしている組み合わせについて繰り返すEnumeratorを返す
24
- # ==== Args
25
- # [behavior] 想定する振る舞い(Symbol)
26
- # ==== Return
27
- # [レシーバ, 引数] のペアを列挙するEnumerator
28
- def enum(behavior)
29
- Enumerator.new do |yielder|
30
- yielder << [@a, @b] if a_b(behavior)
31
- yielder << [@b, @a] if b_a(behavior)
32
- end
33
- end
34
-
35
- def method_missing(behavior, *rest)
36
- if rest.empty?
37
- return self =~ behavior
38
- end
39
- super
40
- end
41
-
42
- private
43
-
44
- def a_b(behavior)
45
- @a.respond_to?(behavior) && @a.__send__(behavior, @b)
46
- end
47
-
48
- def b_a(behavior)
49
- @b.respond_to?(behavior) && @b.__send__(behavior, @a)
50
- end
51
- end
52
-
53
- class PluralCombinator < Combinator
54
- def enum(behavior)
55
- Enumerator.new do |yielder|
56
- @b.each do |b|
57
- (b | @a).enum(behavior).each(&yielder.method(:<<))
58
- end
59
- end
60
- end
61
- end
62
-
63
- class SingleCombinator < Combinator
64
- def =~(behavior)
65
- a_b(behavior) || b_a(behavior)
66
- end
67
- end
68
-
69
- class AnyCombinator < PluralCombinator
70
- def =~(behavior)
71
- @b.any?{|b| b | @a =~ behavior }
72
- end
73
- end
74
-
75
- class AllCombinator < PluralCombinator
76
- def =~(behavior)
77
- @b.all?{|b| b | @a =~ behavior }
78
- end
79
- end
80
-
81
- # _other_ との Diva::Conbinable::Combinator を生成する
82
- # ==== Args
83
- # [other] Diva::Modelか、Diva::Modelを列挙するEnumerable
84
- # ==== Return
85
- # Diva::Conbinable::Combinator
86
- def |(other)
87
- if other.is_a? Enumerable
88
- AnyCombinator.new(self, other)
89
- else
90
- SingleCombinator.new(self, other)
91
- end
92
- end
93
-
94
- # _other_ との Diva::Conbinable::Combinator を生成する
95
- # ==== Args
96
- # [other] Diva::Modelか、Diva::Modelを列挙するEnumerable
97
- # ==== Return
98
- # Diva::Conbinable::Combinator
99
- def &(other)
100
- if other.is_a? Enumerable
101
- AllCombinator.new(self, other)
102
- else
103
- SingleCombinator.new(self, other)
104
- end
105
- end
106
- end