diva 0.3.2 → 1.0.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/diva.gemspec +6 -6
- data/lib/diva/field.rb +7 -0
- data/lib/diva/model.rb +10 -2
- data/lib/diva/model_extend.rb +11 -0
- data/lib/diva/type.rb +96 -25
- data/lib/diva/uri.rb +3 -2
- data/lib/diva/version.rb +1 -1
- metadata +53 -25
- data/lib/diva/combinator.rb +0 -106
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 65b2025d22ea687dfa98ca063ca511630ce75a4928e0e6be9581f7b6f2216ce2
|
4
|
+
data.tar.gz: 6b514157b95438022b2b28ab72b0af436489e3f8edf8e8c12bca80e1298a1b69
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ea64c7762bc79c8c4eba0f9ac41fd3622a3af663c2a9f2057175695da9ba0f9226b4dbb71133e91c288dfc2799cdfae6d075fb84dab1905cc19ec2b7081b7045
|
7
|
+
data.tar.gz: af41fb3db4368b08f71af3cc1886ae44553865d4797f6402278ec1a6a812e2095e94ec752785734592c09f757f58fcde3198e185efc49a494260692dd2afb45f
|
data/diva.gemspec
CHANGED
@@ -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",
|
22
|
-
spec.add_development_dependency "rake",
|
23
|
-
spec.add_development_dependency "minitest",
|
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.
|
27
|
+
spec.add_dependency "addressable", ">= 2.5.2", "< 2.7"
|
28
28
|
end
|
data/lib/diva/field.rb
CHANGED
data/lib/diva/model.rb
CHANGED
@@ -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
|
data/lib/diva/model_extend.rb
CHANGED
@@ -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
|
#
|
data/lib/diva/type.rb
CHANGED
@@ -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
|
-
|
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,
|
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
|
195
|
-
def initialize(
|
196
|
-
|
197
|
-
@
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
data/lib/diva/uri.rb
CHANGED
@@ -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
|
100
|
-
|
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)
|
data/lib/diva/version.rb
CHANGED
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.
|
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:
|
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
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
119
|
+
version: 2.5.2
|
90
120
|
- - "<"
|
91
121
|
- !ruby/object:Gem::Version
|
92
|
-
version: '2.
|
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:
|
129
|
+
version: 2.5.2
|
100
130
|
- - "<"
|
101
131
|
- !ruby/object:Gem::Version
|
102
|
-
version: '2.
|
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
|
-
|
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.
|
data/lib/diva/combinator.rb
DELETED
@@ -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
|