diva 0.0.0 → 0.1.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
  SHA1:
3
- metadata.gz: 6594ddfdf0d7d54cce0063d1425246ce84291045
4
- data.tar.gz: de71b5a108ab8c031af92741d4e0a2ff4821ea94
3
+ metadata.gz: f3d371525ed19621b1a152a2623587783e4802e9
4
+ data.tar.gz: dfbe31dde289f9399e54ddbb07174652dc41efc8
5
5
  SHA512:
6
- metadata.gz: 67a56657f4fadeef7e12ff4e1c801325ee4bcfd868c4327d26d7e7786a43df7d4c28eea3707ee1d08999a632dac5718b7a652de20f9605b6cc3e067509183c16
7
- data.tar.gz: f5d90f5f20af7d0841960acb87fdb1fab828655cbf5e242f4a195aebb53ea2ea7ea6367243bf7b3bfce1ec82912af0709c4b48d68bd083f6b2c73715a7589c63
6
+ metadata.gz: 1b8cded54cb6406710cca50f95947c39f72fa3398ce43a7a0b38e69b7932a9860714a5aa005cf1e561cfdd2bd8cab557b647b036f241898b2f568c8e6f972105
7
+ data.tar.gz: 81150d4fa04f1b9d4a8c83e754b788362f21ddf441ff5fc0fcc2e84b4bb53f08818fc613c096f874db9412cb1356c504324f26b387c009a228ed114308f14025
data/.gitignore CHANGED
@@ -7,3 +7,4 @@
7
7
  /pkg/
8
8
  /spec/reports/
9
9
  /tmp/
10
+ /vendor/
data/diva.gemspec CHANGED
@@ -21,4 +21,8 @@ Gem::Specification.new do |spec|
21
21
  spec.add_development_dependency "bundler", "~> 1.12"
22
22
  spec.add_development_dependency "rake", "~> 10.0"
23
23
  spec.add_development_dependency "minitest", "~> 5.0"
24
+ spec.add_development_dependency "pry"
25
+ spec.add_development_dependency "simplecov"
26
+
27
+ spec.add_dependency "addressable", ">= 2.5", "< 2.6"
24
28
  end
data/lib/diva.rb CHANGED
@@ -1,4 +1,15 @@
1
- require "diva/version"
1
+ # coding: utf-8
2
+ require 'diva/version'
3
+ require 'diva/datasource'
4
+ require 'diva/error'
5
+ require 'diva/field_generator'
6
+ require 'diva/field'
7
+ require 'diva/model'
8
+ require 'diva/spec'
9
+ require 'diva/type'
10
+ require 'diva/uri'
11
+ require 'diva/version'
12
+
2
13
 
3
14
  module Diva
4
15
  # Your code goes here...
@@ -0,0 +1,33 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ =begin rdoc
4
+ データの保存/復元を実際に担当するデータソース。
5
+ データソースをモデルにModel::add_data_retrieverにて幾つでも参加させることが出来る。
6
+ =end
7
+ module Diva::DataSource
8
+ USE_ALL = -1 # findbyidの引数。全てのDataSourceから探索する
9
+ USE_LOCAL_ONLY = -2 # findbyidの引数。ローカルにあるデータのみを使う
10
+
11
+ attr_accessor :keys
12
+
13
+ # idをもつデータを返す。
14
+ # もし返せない場合は、nilを返す
15
+ def findbyid(id, policy)
16
+ nil
17
+ end
18
+
19
+ # 取得できたらそのDivaのインスタンスをキーにして実行されるDeferredを返す
20
+ def idof(id)
21
+ Thread.new{ findbyid(id) } end
22
+ alias [] idof
23
+
24
+ # データの保存
25
+ # データ一件保存する。保存に成功したか否かを返す。
26
+ def store_datum(datum)
27
+ false
28
+ end
29
+
30
+ def inspect
31
+ self.class.to_s
32
+ end
33
+ end
data/lib/diva/error.rb ADDED
@@ -0,0 +1,19 @@
1
+ # -*- coding: utf-8 -*-
2
+ module Diva
3
+ class DivaError < StandardError; end
4
+
5
+ class InvalidTypeError < DivaError; end
6
+
7
+ class InvalidEntityError < DivaError; end
8
+
9
+ # 実装してもしなくてもいいメソッドが実装されておらず、結果を得られない
10
+ class NotImplementedError < DivaError; end
11
+
12
+ # IDやURIなどの一意にリソースを特定する情報を使ってデータソースに問い合わせたが、
13
+ # 対応する情報が見つからず、Modelを作成できない
14
+ class ModelNotFoundError < DivaError; end
15
+
16
+ # URIとして受け付けられない値を渡された
17
+ class InvalidURIError < InvalidTypeError; end
18
+
19
+ end
data/lib/diva/field.rb ADDED
@@ -0,0 +1,38 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'diva/type'
4
+
5
+ =begin rdoc
6
+ Modelのキーの情報を格納する。
7
+ キーひとつにつき1つのインスタンスが作られる。
8
+ =end
9
+ module Diva
10
+ class Field
11
+ attr_reader :name, :type, :required
12
+
13
+ # [name] Symbol フィールドの名前
14
+ # [type] Symbol フィールドのタイプ。:int, :string, :bool, :time のほか、Diva::Modelのサブクラスを指定する
15
+ # [required] boolean _true_ なら、この項目を必須とする
16
+ def initialize(name, type, required: false)
17
+ @name = name.to_sym
18
+ @type = Diva::Type.optional(Diva::Type(type))
19
+ @required = !!required
20
+ end
21
+
22
+ def required?
23
+ required
24
+ end
25
+
26
+ def to_sym
27
+ name
28
+ end
29
+
30
+ def to_s
31
+ name.to_s
32
+ end
33
+
34
+ def inspect
35
+ "#<#{self.class}: #{name}(#{type})#{required ? '*' : ''}>"
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,39 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ class Diva::FieldGenerator
4
+ def initialize(model_klass)
5
+ @model_klass = model_klass
6
+ end
7
+
8
+ def int(field_name, required: false)
9
+ @model_klass.add_field(field_name, type: :int, required: required)
10
+ end
11
+
12
+ def string(field_name, required: false)
13
+ @model_klass.add_field(field_name, type: :string, required: required)
14
+ end
15
+
16
+ def bool(field_name, required: false)
17
+ @model_klass.add_field(field_name, type: :bool, required: required)
18
+ end
19
+
20
+ def time(field_name, required: false)
21
+ @model_klass.add_field(field_name, type: :time, required: required)
22
+ end
23
+
24
+ def uri(field_name, required: false)
25
+ @model_klass.add_field(field_name, type: :uri, required: required)
26
+ end
27
+
28
+ def has(field_name, type, required: false)
29
+ @model_klass.add_field(field_name, type: type, required: required)
30
+ end
31
+ end
32
+
33
+
34
+
35
+
36
+
37
+
38
+
39
+
data/lib/diva/model.rb ADDED
@@ -0,0 +1,147 @@
1
+ # -*- coding: utf-8 -*-
2
+ =begin rdoc
3
+ いろんなリソースの基底クラス
4
+ =end
5
+
6
+ require 'diva/model_extend'
7
+ require 'diva/uri'
8
+ require 'diva/spec'
9
+
10
+ require 'securerandom'
11
+
12
+ class Diva::Model
13
+ include Comparable
14
+ extend Diva::ModelExtend
15
+
16
+ def initialize(args)
17
+ @value = args.dup
18
+ validate
19
+ self.class.store_datum(self)
20
+ end
21
+
22
+ # データをマージする。
23
+ # selfにあってotherにもあるカラムはotherの内容で上書きされる。
24
+ # 上書き後、データはDataSourceに保存される
25
+ def merge(other)
26
+ @value.update(other.to_hash)
27
+ validate
28
+ self.class.store_datum(self)
29
+ end
30
+
31
+ # このModelのパーマリンクを返す。
32
+ # パーマリンクはWebのURLで、Web上のリソースでない場合はnilを返す。
33
+ # ==== Return
34
+ # 次のいずれか
35
+ # [URI::HTTP|Diva::URI] パーマリンク
36
+ # [nil] パーマリンクが存在しない
37
+ def perma_link
38
+ nil
39
+ end
40
+
41
+ # このModelのURIを返す。
42
+ # ==== Return
43
+ # [URI::Generic|Diva::URI] パーマリンク
44
+ def uri
45
+ perma_link || Diva::URI.new("#{self.class.scheme}://#{self.class.host}#{path}")
46
+ end
47
+
48
+ # このModelが、登録されているアカウントのうちいずれかが作成したものであれば true を返す
49
+ # ==== Args
50
+ # [service] Service | Enumerable 「自分」のService
51
+ # ==== Return
52
+ # [true] 自分のによって作られたオブジェクトである
53
+ # [false] 自分のによって作られたオブジェクトではない
54
+ def me?(service=nil)
55
+ false
56
+ end
57
+
58
+ def hash
59
+ @_hash ||= self.uri.to_s.hash ^ self.class.hash
60
+ end
61
+
62
+ def <=>(other)
63
+ if other.is_a?(Diva::Model)
64
+ created - other.created
65
+ elsif other.respond_to?(:[]) and other[:created]
66
+ created - other[:created]
67
+ else
68
+ id - other
69
+ end
70
+ end
71
+
72
+ def ==(other)
73
+ if other.is_a? Diva::Model
74
+ self.class == other.class && uri == other.uri
75
+ end
76
+ end
77
+
78
+ def eql?(other)
79
+ self == other
80
+ end
81
+
82
+ def to_hash
83
+ Hash[self.class.fields.map{|f| [f.name, fetch(f.name)] }]
84
+ end
85
+
86
+ # カラムの生の内容を返す
87
+ def fetch(key)
88
+ @value[key.to_sym]
89
+ end
90
+ alias [] fetch
91
+
92
+ # カラムに別の値を格納する。
93
+ # 格納後、データはDataSourceに保存される
94
+ def []=(key, value)
95
+ @value[key.to_sym] = value
96
+ self.class.store_datum(self)
97
+ value
98
+ end
99
+
100
+ # カラムと型が違うものがある場合、例外を発生させる。
101
+ def validate
102
+ raise RuntimeError, "argument is #{@value}, not Hash" if not @value.is_a?(Hash)
103
+ self.class.fields.each do |field|
104
+ begin
105
+ @value[field.name] = field.type.cast(@value[field.name])
106
+ rescue Diva::InvalidTypeError => err
107
+ raise Diva::InvalidTypeError, "#{err} in field `#{field}'"
108
+ end
109
+ end
110
+ end
111
+
112
+ # キーとして定義されていない値を全て除外した配列を生成して返す。
113
+ # また、Modelを子に含んでいる場合、それを外部キーに変換する。
114
+ def filtering
115
+ datum = self.to_hash
116
+ result = Hash.new
117
+ self.class.fields.each do |field|
118
+ begin
119
+ result[field.name] = field.type.cast(datum[field.name])
120
+ rescue Diva::InvalidTypeError => err
121
+ raise Diva::InvalidTypeError, "#{err} in field `#{field}'"
122
+ end
123
+ end
124
+ result
125
+ end
126
+
127
+ # このインスタンスのタイトル。
128
+ def title
129
+ fields = self.class.fields.lazy.map(&:name)
130
+ case
131
+ when fields.include?(:name)
132
+ name.gsub("\n", '')
133
+ when fields.include?(:description)
134
+ description.gsub("\n", '')
135
+ else
136
+ to_s.gsub("\n", '')
137
+ end
138
+ end
139
+
140
+ private
141
+ # URIがデフォルトで使うpath要素
142
+ def path
143
+ @path ||= "/#{SecureRandom.uuid}"
144
+ end
145
+
146
+ end
147
+
@@ -0,0 +1,94 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'diva/field'
4
+ require 'diva/type'
5
+
6
+ =begin rdoc
7
+ Diva::Model のクラスメソッド
8
+ =end
9
+ module Diva::ModelExtend
10
+ extend Gem::Deprecate
11
+
12
+ attr_reader :slug, :spec
13
+
14
+ # Modelのインスタンスのuriスキーム。オーバライドして適切な値にする
15
+ # ==== Return
16
+ # [String] URIスキーム
17
+ def scheme
18
+ @_scheme ||= self.to_s.split('::',2).first.gsub(/\W/,'').downcase.freeze
19
+ end
20
+
21
+ # Modelのインスタンスのホスト名。オーバライドして適切な値にする
22
+ # ==== Return
23
+ # [String] ホスト名
24
+ def host
25
+ @_host ||= self.to_s.split('::',2).last.split('::').reverse.join('.').gsub(/[^\w\.]/,'').downcase.freeze
26
+ end
27
+
28
+ # Modelにフィールドを追加する。
29
+ # ==== Args
30
+ # [field_name] Symbol フィールドの名前
31
+ # [type] Symbol フィールドのタイプ。:int, :string, :bool, :time のほか、Diva::Modelのサブクラスを指定する
32
+ # [required] boolean _true_ なら、この項目を必須とする
33
+ def add_field(field, type: nil, required: false)
34
+ if field.is_a?(Symbol)
35
+ field = Diva::Field.new(field, type, required: required)
36
+ end
37
+ (@fields ||= []) << field
38
+ define_method(field.name) do
39
+ @value[field.name]
40
+ end
41
+
42
+ define_method("#{field.name}?") do
43
+ !!@value[field.name]
44
+ end
45
+
46
+ define_method("#{field.name}=") do |value|
47
+ @value[field.name] = field.type.cast(value)
48
+ self.class.store_datum(self)
49
+ value
50
+ end
51
+ self
52
+ end
53
+
54
+ def fields
55
+ @fields ||= []
56
+ end
57
+ alias :keys :fields
58
+ deprecate :keys, "fields", 2018, 02
59
+
60
+ #
61
+ # プライベートクラスメソッド
62
+ #
63
+
64
+ def field
65
+ Diva::FieldGenerator.new(self)
66
+ end
67
+
68
+ # URIに対応するリソースの内容を持ったModelを作成する。
69
+ # URIに対応する情報はネットワーク上などから取得される場合もある。そういった場合はこのメソッドは
70
+ # Delayer::Deferred::Deferredable を返す可能性がある。
71
+ # とくにオーバライドしない場合、このメソッドは常に例外 Diva::NotImplementedError を投げる。
72
+ # ==== Args
73
+ # [uri] _handle_ メソッドで指定したいずれかの条件に一致するURI
74
+ # ==== Return
75
+ # [Delayer::Deferred::Deferredable]
76
+ # ネットワークアクセスを行って取得するなど取得に時間がかかる場合
77
+ # [self]
78
+ # すぐにModelを生成できる場合、そのModel
79
+ # ==== Raise
80
+ # [Diva::NotImplementedError]
81
+ # このModelでは、find_by_uriが実装されていない
82
+ # [Diva::ModelNotFoundError]
83
+ # _uri_ に対応するリソースが見つからなかった
84
+ def find_by_uri(uri)
85
+ raise Diva::NotImplementedError, "#{self}.find_by_uri does not implement."
86
+ end
87
+
88
+ # Modelが生成・更新された時に呼ばれるコールバックメソッドです
89
+ def store_datum(retriever); end
90
+
91
+ def container_class
92
+ Array
93
+ end
94
+ end
data/lib/diva/spec.rb ADDED
@@ -0,0 +1,9 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ Diva::ModelSpec = Struct.new(
4
+ :slug,
5
+ :name,
6
+ :reply,
7
+ :myself,
8
+ :timeline,
9
+ )
data/lib/diva/type.rb ADDED
@@ -0,0 +1,216 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ =begin rdoc
4
+ Modelの各キーに格納できる値の制約。
5
+ この制約に満たない場合は、アトミックな制約であれば値の変換が行われ、そうでない場合は
6
+ Diva::InvalidTypeError 例外を投げる。
7
+
8
+ これは新しくインスタンスなどを作らず、INT、FLOATなどのプリセットを利用する。
9
+
10
+ == 設定できる制約
11
+ Modelフィールドの制約には以下のようなものがある。
12
+
13
+ === アトミックな制約
14
+ 以下のような値は、DivaのModelフィールドにおいてはアトミックな制約と呼び、そのまま格納できる。
15
+ [INT] 数値(Integer)
16
+ [FLOAT] 少数(Float)
17
+ [BOOL] 真理値(true|false)
18
+ [STRING] 文字列(String)
19
+ [TIME] 時刻(Time)
20
+ [URI] URI(Diva::URI|URI::Generic|Addressable::URI)
21
+
22
+ === Model
23
+ Diva::Modelのサブクラスであれば、それを制約とすることができる。
24
+
25
+ === 配列
26
+ アトミックな制約またはModel制約を満たした値の配列を格納することができる。
27
+ 配列の全ての要素が設定された制約を満たしていれば、配列制約が満たされたことになる。
28
+
29
+ =end
30
+ module Diva::Type
31
+ extend self
32
+
33
+ def model_of(model)
34
+ ModelType.new(model)
35
+ end
36
+
37
+ def array_of(type)
38
+ ArrayType.new(type)
39
+ end
40
+
41
+ def optional(type)
42
+ OptionalType.new(type)
43
+ end
44
+
45
+ # 全てのType共通のスーパークラス
46
+ class MetaType
47
+ attr_reader :name
48
+
49
+ def initialize(name, *rest, &cast)
50
+ @name = name.to_sym
51
+ if cast
52
+ define_singleton_method :cast, &cast
53
+ end
54
+ end
55
+
56
+ def cast(value)
57
+ value
58
+ end
59
+
60
+ def to_s
61
+ name.to_s
62
+ end
63
+
64
+ def inspect
65
+ "Diva::Type(#{to_s})"
66
+ end
67
+ end
68
+
69
+ class AtomicType < MetaType
70
+ end
71
+
72
+ INT = AtomicType.new(:int) do |v|
73
+ case v
74
+ when Integer
75
+ v
76
+ when Numeric, String, Time
77
+ v.to_i
78
+ when TrueClass
79
+ 1
80
+ when FalseClass
81
+ 0
82
+ else
83
+ raise Diva::InvalidTypeError, "The value is not a `#{name}'."
84
+ end
85
+ end
86
+ FLOAT = AtomicType.new(:float) do |v|
87
+ case v
88
+ when Float
89
+ v
90
+ when Numeric, String, Time
91
+ v.to_f
92
+ else
93
+ raise Diva::InvalidTypeError, "The value is not a `#{name}'."
94
+ end
95
+ end
96
+ BOOL = AtomicType.new(:bool) do |v|
97
+ case v
98
+ when TrueClass, FalseClass
99
+ v
100
+ when String
101
+ !v.empty?
102
+ when Integer
103
+ v != 0
104
+ else
105
+ raise Diva::InvalidTypeError, "The value is not a `#{name}'."
106
+ end
107
+ end
108
+ STRING = AtomicType.new(:string) do |v|
109
+ case v
110
+ when Diva::Model, Enumerable
111
+ raise Diva::InvalidTypeError, "The value is not a `#{name}'."
112
+ else
113
+ v.to_s
114
+ end
115
+ end
116
+ TIME = AtomicType.new(:time) do |v|
117
+ case v
118
+ when Time
119
+ v
120
+ when Integer, Float
121
+ Time.at(v)
122
+ when String
123
+ Time.new(v)
124
+ else
125
+ raise Diva::InvalidTypeError, "The value is not a `#{name}'."
126
+ end
127
+ end
128
+ URI = AtomicType.new(:uri) do |v|
129
+ case v
130
+ when Diva::URI, Addressable::URI, ::URI::Generic
131
+ v
132
+ when String
133
+ Diva::URI.new(v)
134
+ else
135
+ raise Diva::InvalidTypeError, "The value is not a `#{name}'."
136
+ end
137
+ end
138
+
139
+ class ModelType < MetaType
140
+ attr_reader :model
141
+ def initialize(model, *rest, &cast)
142
+ super(:model, *rest)
143
+ @model = model
144
+ end
145
+
146
+ def cast(value)
147
+ raise Diva::InvalidTypeError, "The value is not a `#{model}'." unless value.is_a?(model)
148
+ value
149
+ end
150
+
151
+ def to_s
152
+ "#{model} #{name}"
153
+ end
154
+ end
155
+
156
+ class ArrayType < MetaType
157
+ def initialize(type)
158
+ super("#{type.name}_array")
159
+ @type = type
160
+ end
161
+
162
+ def cast(value)
163
+ raise Diva::InvalidTypeError, "The value is not a `#{name}'." unless value.is_a?(Enumerable)
164
+ value.to_a.map(&@type.method(:cast))
165
+ end
166
+
167
+ def to_s
168
+ "Array of #{type.to_s}"
169
+ end
170
+ end
171
+
172
+ class OptionalType < MetaType
173
+ def initialize(type)
174
+ super("optional_#{type.name}")
175
+ @type = type
176
+ end
177
+
178
+ def cast(value)
179
+ if value.nil?
180
+ value
181
+ else
182
+ @type.cast(value)
183
+ end
184
+ end
185
+
186
+ def to_s
187
+ "#{type.to_s}|nil"
188
+ end
189
+ end
190
+
191
+ end
192
+
193
+ module Diva
194
+ def self.Type(type)
195
+ case type
196
+ when Diva::Type::MetaType
197
+ type
198
+ when :int
199
+ Diva::Type::INT
200
+ when :float
201
+ Diva::Type::FLOAT
202
+ when :bool
203
+ Diva::Type::BOOL
204
+ when :string
205
+ Diva::Type::STRING
206
+ when :time
207
+ Diva::Type::TIME
208
+ when :uri
209
+ Diva::Type::URI
210
+ when ->x{x.superclass == Diva::Model}
211
+ Diva::Type.model_of(type)
212
+ when Array
213
+ Diva::Type.array_of(type.first)
214
+ end
215
+ end
216
+ end
data/lib/diva/uri.rb ADDED
@@ -0,0 +1,131 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ =begin rdoc
4
+ =Model用のURIクラス
5
+
6
+ mikutterでは、 URI や Addressable::URI の代わりに、このクラスを使用します。
7
+ URI や Addressable::URI に比べて、次のような特徴があります。
8
+
9
+ * コンストラクタに文字列を渡している場合、 _to_s_ がその文字列を返す。
10
+ * 正規化しないかわりに高速に動作します。
11
+ * Diva::URI のインスタンスは URI と同じように使える
12
+ * unicode文字などが入っていて URI では表現できない場合、 Addressable::URI を使う
13
+ * Addressable::URIでないと表現できないURIであればそちらを使うという判断を自動で行う
14
+
15
+ == 使い方
16
+ Diva::URI() メソッドの引数にString, URI, Addressable::URI, Hash, Diva::URIのいずれかを与えます。
17
+
18
+ [String] uriの文字列(ex: "http://mikutter.hachune.net/")
19
+ [URI] URI のインスタンス
20
+ [Addressable::URI] Addressable::URI のインスタンス
21
+ [Hash] これを引数にURI::Generic.build に渡すのと同じ形式の Hash
22
+ [Diva::URI] 即座にこれ自身を返す
23
+
24
+ == 例
25
+
26
+ Diva::URI("http://mikutter.hachune.net/")
27
+ Diva::URI(URI::Generic.build(scheme: 'http', host: 'mikutter.hachune.net'))
28
+ =end
29
+
30
+ require 'uri'
31
+ require 'addressable/uri'
32
+
33
+ class Diva::URI
34
+ def initialize(uri)
35
+ case uri.freeze
36
+ when URI, Addressable::URI
37
+ @uri = uri
38
+ when String
39
+ @uri_string = uri
40
+ when Hash
41
+ @uri_hash = uri
42
+ end
43
+ end
44
+
45
+ def ==(other)
46
+ case other
47
+ when URI, Addressable::URI
48
+ other == to_uri
49
+ when Diva::URI
50
+ if has_string? or other.has_string?
51
+ to_s == other.to_s
52
+ else
53
+ other.to_uri == to_uri
54
+ end
55
+ end
56
+ end
57
+
58
+ def hash
59
+ to_s.hash ^ self.class.hash
60
+ end
61
+
62
+ def has_string?
63
+ !!@uri_string
64
+ end
65
+
66
+ def has_uri?
67
+ !!@uri
68
+ end
69
+
70
+ def to_s
71
+ @uri_string ||= to_uri.to_s.freeze
72
+ end
73
+
74
+ def to_uri
75
+ @uri ||= generate_uri.freeze
76
+ end
77
+
78
+ def scheme
79
+ if has_string? and !has_uri?
80
+ match = @uri_string.match(%r<\A(\w+):>)
81
+ if match
82
+ match[1]
83
+ else
84
+ to_uri.scheme
85
+ end
86
+ else
87
+ to_uri.scheme
88
+ end
89
+ end
90
+
91
+ def freeze
92
+ unless frozen?
93
+ to_uri
94
+ to_s
95
+ end
96
+ super
97
+ end
98
+
99
+ def respond_to?(method)
100
+ super or to_uri.respond_to?(method)
101
+ end
102
+
103
+ def method_missing(method, *rest, &block)
104
+ to_uri.__send__(method, *rest, &block)
105
+ end
106
+
107
+ private
108
+
109
+ def generate_uri
110
+ if @uri
111
+ @uri
112
+ elsif @uri_string
113
+ @uri = generate_uri_by_string
114
+ elsif @uri_hash
115
+ @uri = generate_uri_by_hash
116
+ end
117
+ @uri
118
+ end
119
+
120
+ def generate_uri_by_string
121
+ URI.parse(@uri_string)
122
+ rescue URI::InvalidComponentError
123
+ Addressable::URI.parse(@uri_string)
124
+ end
125
+
126
+ def generate_uri_by_hash
127
+ URI::Generic.build(@uri_hash)
128
+ rescue URI::InvalidComponentError
129
+ Addressable::URI.new(@uri_hash)
130
+ end
131
+ end
data/lib/diva/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Diva
2
- VERSION = "0.0.0"
2
+ VERSION = "0.1.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: diva
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.0
4
+ version: 0.1.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: 2017-02-05 00:00:00.000000000 Z
11
+ date: 2017-02-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -52,6 +52,54 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '5.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: pry
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: simplecov
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: addressable
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '2.5'
90
+ - - "<"
91
+ - !ruby/object:Gem::Version
92
+ version: '2.6'
93
+ type: :runtime
94
+ prerelease: false
95
+ version_requirements: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ version: '2.5'
100
+ - - "<"
101
+ - !ruby/object:Gem::Version
102
+ version: '2.6'
55
103
  description:
56
104
  email:
57
105
  - toshi.alternative@gmail.com
@@ -69,6 +117,15 @@ files:
69
117
  - bin/setup
70
118
  - diva.gemspec
71
119
  - lib/diva.rb
120
+ - lib/diva/datasource.rb
121
+ - lib/diva/error.rb
122
+ - lib/diva/field.rb
123
+ - lib/diva/field_generator.rb
124
+ - lib/diva/model.rb
125
+ - lib/diva/model_extend.rb
126
+ - lib/diva/spec.rb
127
+ - lib/diva/type.rb
128
+ - lib/diva/uri.rb
72
129
  - lib/diva/version.rb
73
130
  homepage: https://github.com/toshia/diva
74
131
  licenses:
@@ -90,7 +147,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
90
147
  version: '0'
91
148
  requirements: []
92
149
  rubyforge_project:
93
- rubygems_version: 2.5.1
150
+ rubygems_version: 2.6.8
94
151
  signing_key:
95
152
  specification_version: 4
96
153
  summary: Implementation of expression for handling things.