striuct 0.0.11.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gemtest ADDED
File without changes
data/History.rdoc ADDED
@@ -0,0 +1,110 @@
1
+ === 0.0.11 2011-12-23
2
+
3
+ * modify
4
+ * Subclass.cname?
5
+
6
+ * add:
7
+ * inference checker
8
+
9
+ === 0.0.10 2011-12-23
10
+
11
+ * delete
12
+ * Subclass#lock, Subclass#unlock?
13
+
14
+ * modify
15
+ * Subclass#freeze
16
+ * has_condition? -> has_conditions?
17
+ * Subclass.lock, Subclass.lock? -> .close, .closed?
18
+
19
+ * add:
20
+ * Subclass.protect_level # class macro
21
+ * Subclass#default?
22
+
23
+ === 0.0.9 2011-12-21
24
+
25
+ * delete
26
+ * Striuct.load_pairs
27
+ * Subclass.conditions
28
+ * Subclass.procedures
29
+ * Subclass.defaults
30
+
31
+ * add:
32
+ * Striuct.define
33
+ * Subclass.lock
34
+ * Subclass.default_for
35
+
36
+ * fix:
37
+ * Subclass#inspect
38
+ * Subclass#to_s
39
+
40
+ * note:
41
+ * innner name changed "procedure" to "flavor"
42
+
43
+ === 0.0.8 2011-12-18
44
+
45
+ * modify:
46
+ * Subclass.define
47
+ * Subclass.accept?
48
+ * functional checker's action:
49
+ Proc: context to instance
50
+ Method: === to call
51
+
52
+ * add:
53
+ * Subclass.default
54
+
55
+ * fix:
56
+ * Subclass#values_at
57
+
58
+ === 0.0.7 2011-12-16
59
+
60
+ * modify:
61
+ * called macro's block to procedure
62
+ * public to private Subclass#unlock
63
+
64
+ * add:
65
+ * Subclass.define
66
+ * Subclass.accept?
67
+ * Subclass.restrict?
68
+ * Subclass#assign?
69
+ * Subclass#assign
70
+
71
+ * fix:
72
+ * use clone method ( initialize_copy )
73
+
74
+ === 0.0.6 2011-12-14
75
+
76
+ * modify:
77
+ * error type in some methods
78
+
79
+ * add:
80
+ * Subclass.sufficent?
81
+ * Subclass.define
82
+ * Subclass#sufficent?
83
+ * Subclass#secure?
84
+ * Subclass#lock?
85
+ * Subclass#lock
86
+ * Subclass#unlock
87
+
88
+ * fix:
89
+ * typo
90
+
91
+ === 0.0.5 2011-12-14
92
+
93
+ * fix class constructor
94
+ * modify #inspect
95
+ * add arguments checks
96
+
97
+ === 0.0.4 2011-12-13
98
+
99
+ * divide modules for subclass methods
100
+ * modify return values for void methods
101
+
102
+ === 0.0.3 2011-12-12
103
+
104
+ === 0.0.2 2011-12-11
105
+
106
+ === 0.0.1 2011-12-11
107
+
108
+ * 1 major enhancement:
109
+ * Initial release
110
+
data/Manifest.txt ADDED
@@ -0,0 +1,15 @@
1
+ History.rdoc
2
+ Manifest.txt
3
+ README.rdoc
4
+ README.ja.rdoc
5
+ Rakefile
6
+ example.rb
7
+ lib/striuct.rb
8
+ lib/striuct/core.rb
9
+ lib/striuct/version.rb
10
+ lib/striuct/classutil.rb
11
+ lib/striuct/subclass.rb
12
+ lib/striuct/subclass_eigen.rb
13
+ lib/striuct/import.rb
14
+ test/test_helper.rb
15
+ test/test_striuct.rb
data/README.ja.rdoc ADDED
@@ -0,0 +1,244 @@
1
+ = Striuct
2
+
3
+ * http://github.com/kachick/striuct
4
+ * https://rubygems.org/gems/striuct
5
+ * http://rubyforge.org/projects/striuct
6
+
7
+ == DESCRIPTION
8
+
9
+ Strict Struct の略です。そのまま StrictStruct でも使えます。
10
+
11
+ メンバ名チェックのかかるStructは、安心感という意味ではHashよりも好ましい事があるかと思います。
12
+ でもそうやってStructを使うぐらいなわけだから、名前だけじゃなく参照先にもある程度の代入条件をかけたいと思う事が多くありませんか?
13
+
14
+ RubyのStructを愛しつつも、こういった部分をなんとかしたいと感じている方へお勧めします。
15
+
16
+ 1. ノーガードで参照を付けられるのがおっかないときもある
17
+ 2. かといって、型チェックしか出来ないようじゃRubyのメリットが死ぬんではなかろうか
18
+ 3. メンバ名でフツーのメソッド名を上書きしかねないのもおっかない
19
+ 4. 最初に代入したオブジェクトのクラスで固定したい
20
+ 5. どうせなら、チェックだけじゃなくキャストなりもやらせたものを参照したい
21
+ 6. メンバによっては標準値も定義したい
22
+
23
+ == FEATURES
24
+
25
+ * メンバ毎に、参照条件を簡単に定義できます。
26
+ * 型チェックではなく式チェックなので、動的言語の良さを殺しません
27
+ * Proc(lambda)やMethod等 を使うことで、さらに柔軟なチェックが可能です
28
+ * どれか一つの構造体で最初に代入したオブジェクトのクラスで固定するようなメンバを作れます。
29
+ * 参照前に、ちょっとした処理を加える事も可能です
30
+ * 構造体としてのメンバ追加時、Rubyの既存メソッドと干渉しないかを指定レベル別にチェック可能です。
31
+ * Structの心地よい操作感を残したまま機能追加をしています。
32
+ * 既存クラスやメソッドの上書き等を(勝手には)しない、控えめな名前空間
33
+ * pure-ruby
34
+
35
+ == SYNOPSIS
36
+
37
+ * setup
38
+ require 'striuct'
39
+
40
+ * Structには無い機能として、memberというクラスマクロを用意しました。
41
+ ここでの定義順通りにindexが振られます。
42
+ 引数1にメンバ名、引数2以降に参照条件を渡して下さい。caseのwhen節と同じ感覚で使えます。
43
+ 引数1のみの場合、Structのメンバと同様ノーチェックになります。
44
+ class User < Striuct.new
45
+ member :id, Integer
46
+ member :address, /\A((\w+) ?)+\z/
47
+ member :age, (20..140)
48
+ member :name, /\A\w+\z/, /\A\w+ \w+\z/
49
+ end
50
+
51
+ # これはOK
52
+ user = User.new 128381, 'Tokyo Japan', 20
53
+
54
+ # これもOK
55
+ user.age = 30
56
+ user.name = 'taro yamada'
57
+
58
+ # これは駄目(例外 Striuct::ConditionError)
59
+ user[:id] = 10.0
60
+ user[1] = 'Tokyo-to'
61
+ user.age = 19
62
+ user.name = nil
63
+
64
+
65
+ * リンク貼る時どれだけ注意しても、その後参照先のオブジェクトがぶっ壊れる可能性は残りますよね。
66
+ これは致し方無いと思うので、チェックだけでも簡単にできるようにしています。
67
+ user.strict? #=> true
68
+ user.address.clear
69
+ user.strict? #=> false
70
+
71
+ * 単純な例としてはこんな感じですが、更に細かいチェッカが必要であれば関数オブジェクトを使って下さい。
72
+ この時Proc(lambda)を構造体インスタンスのコンテキストで評価する為、他のメンバと連携したチェックも簡単です。
73
+ module Game
74
+ class Character
75
+ end
76
+
77
+ class DB < Striuct.new
78
+ member :monsters, ->monsters{(monsters - characters).empty?}
79
+ member :characters, ->characters{characters.all?{|c|c.kind_of? Character}}
80
+ end
81
+
82
+ monster = Character.new
83
+ db = DB.new
84
+
85
+ # fail
86
+ db.characters = [1, 2]
87
+
88
+ # pass
89
+ db.characters = [monster, Character.new]
90
+
91
+ # fail
92
+ db.monsters = [:dummy]
93
+
94
+ # pass
95
+ db.monsters = [monster]
96
+ end
97
+
98
+ * 構造体クラスのコンテキスト内だけで使える "inference" というメソッドの返り値を渡すと、
99
+ 最初にどれか一つのインスタンスで参照したクラスが以降の参照条件となります。
100
+ class FlexibleContainer < Striuct.new
101
+ member :anything, inference
102
+ member :number, inference, Numeric
103
+ end
104
+
105
+ fc1, fc2 = FlexibleContainer.new, FlexibleContainer.new
106
+ # pass
107
+ fc1.anything = 'str'
108
+
109
+ # fail
110
+ fc1.anything = :sym
111
+ fc2.anything = :sym
112
+
113
+ # pass
114
+ fc2.anything = 'string too'
115
+
116
+ # fail
117
+ fc1.number = 'str'
118
+
119
+ # pass
120
+ fc1.number = 1.0
121
+
122
+ # fail
123
+ fc2.number = 1
124
+
125
+
126
+ * memberマクロへブロックを渡しておくと、チェック後一処理加えた値を代入可能です。
127
+ class User2 < Striuct.new
128
+ # 数字っぽければIntegerへ変換してから
129
+ member :age, /\A\d+\z/, Numeric do |v|
130
+ Integer v
131
+ end
132
+
133
+ # Symbolに変換した上で代入。
134
+ member :name, ->v{v.respond_to? :to_s} do |v|
135
+ v.to_s.to_sym
136
+ end
137
+ end
138
+
139
+ user2 = User2.new
140
+ user2.age = 9 #=> 9(Fixnum)
141
+ user2.age = 10.1 #=> 10(Fixnum)
142
+ user2.age = '10' #=> 10(Fixnum)
143
+
144
+ user2.name = 10 #=> :10(Symbol)
145
+
146
+ * Structだと標準値は全て nil になってしまいますが、これもクラスマクロで定義できるようにしました。
147
+ class User3 < Striuct.new
148
+ member :lank, Fixnum
149
+ default :lank, 3
150
+ member :name
151
+ end
152
+
153
+ user3 = User3.new
154
+ user3.lank #=> 3
155
+
156
+ * 「意図的にnilを定義する」事もありますよね
157
+ 初期nilとの判別用メソッドを追加しました。
158
+
159
+ user3.name #=> nil
160
+ user3.assign? :name #=> false
161
+ user3.name = nil
162
+ user3.assign? :name #=> true
163
+
164
+ * Structはこんな感じで、ノーガード上書き&メソッド定義出来ない物も無警告で進みます
165
+ NoGuard = Struct.new :__send__, :'? !'
166
+ noguard = NoGuard.new false
167
+ p noguard.__send__
168
+ p noguard.methods.include?(:'? !') # lost!!
169
+
170
+ * ということで、意図しない上書き等を防ぐために安全度を設定出来るようにしました。
171
+ 標準値は上から2番目です。
172
+ class SafetyNaming < Striuct.new
173
+ begin
174
+ member :__send__
175
+ rescue
176
+ p $!
177
+ end
178
+
179
+ begin
180
+ member :'? !'
181
+ rescue
182
+ p $!
183
+ end
184
+
185
+ # ここで下げると、定義可能に
186
+ protect_level :struct
187
+
188
+ member :__send__, :'? !'
189
+ end
190
+
191
+ * Structの良さは無くしたくないですよね
192
+ Sth1 = Striuct.new :id, :last_name, :family_name, :address, :age
193
+
194
+ Sth2 = Striuct.new do
195
+ def my_special_method
196
+ end
197
+ end
198
+
199
+ Sth2.new.respond_to?(:my_special_method) #=> true
200
+
201
+ * 混在利用させたい向きとかに、Structにも同じようなインターフェイスを用意できます。
202
+ 逆に言うと、これを使わない限りは名前空間をあんまし汚しません。
203
+ require 'striuct/import'
204
+
205
+ * 他にも幾つか機能追加しています。
206
+ また、ここの例だと返り値や例外が見づらいと思うので、同梱の example.rb を動かしてみてください
207
+
208
+ * 早わかり
209
+ https://github.com/kachick/striuct/wiki/EasyGuide
210
+
211
+ == REQUIREMENTS
212
+
213
+ === Ruby
214
+ * 1.9.3
215
+ * 1.9.2
216
+
217
+ == INSTALL
218
+
219
+ * sudo gem install striuct
220
+
221
+ == LICENSE
222
+
223
+ (The MIT License)
224
+
225
+ Copyright (c) 2011 Kenichi Kamiya
226
+
227
+ Permission is hereby granted, free of charge, to any person obtaining
228
+ a copy of this software and associated documentation files (the
229
+ 'Software'), to deal in the Software without restriction, including
230
+ without limitation the rights to use, copy, modify, merge, publish,
231
+ distribute, sublicense, and/or sell copies of the Software, and to
232
+ permit persons to whom the Software is furnished to do so, subject to
233
+ the following conditions:
234
+
235
+ The above copyright notice and this permission notice shall be
236
+ included in all copies or substantial portions of the Software.
237
+
238
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
239
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
240
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
241
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
242
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
243
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
244
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,220 @@
1
+ = Striuct
2
+
3
+ * http://github.com/kachick/striuct
4
+ * https://rubygems.org/gems/striuct
5
+ * http://rubyforge.org/projects/striuct
6
+
7
+ == DESCRIPTION
8
+
9
+ Striuct means Strict Struct.
10
+ Handy and safty than Ruby's Standard Struct.
11
+
12
+ == FEATURES
13
+ * Provides automated checking for your setters.
14
+ * When you link a object, Striuct checks "They are valid objects?".
15
+ These checkers are not only Type Checker. They judge under your expressions.
16
+ * when use "inference", member will be fixed first passed object's class
17
+ * After check, you can add one-step before link a object (call "flavor" at here).
18
+ * You will be set default-value, and we have different meanings between nil and default-value.
19
+ * without undesirable naming for conflict, no-identifier, and more cases
20
+ * Base API looks like Ruby's standard Struct
21
+ * not taint your name-space(exclude striuct/import)
22
+ * pure-ruby
23
+
24
+ == SYNOPSIS
25
+
26
+ * setup
27
+ require 'striuct'
28
+
29
+ * Macro "member" provides one of Struct+ interface.
30
+ It checks under conditions when change to link other.
31
+ class User < Striuct.new
32
+ member :id, Integer
33
+ member :address, /\A((\w+) ?)+\z/
34
+ member :age, (20..140)
35
+ member :name, /\A\w+\z/, /\A\w+ \w+\z/
36
+ end
37
+
38
+ # pass
39
+ user = User.new 128381, 'Tokyo Japan', 20
40
+
41
+ # pass
42
+ user.age = 30
43
+ user.name = 'taro yamada'
44
+
45
+ # fail
46
+ user[:id] = 10.0
47
+ user[1] = 'Tokyo-to'
48
+ user.age = 19
49
+ user.name = nil
50
+
51
+ * more detail checker do you need, you can use functional object here.
52
+ module Game
53
+ class Character
54
+ end
55
+
56
+ class DB < Striuct.new
57
+ member :monsters, ->monsters{(monsters - characters).empty?}
58
+ member :characters, ->characters{characters.all?{|c|c.kind_of? Character}}
59
+ end
60
+
61
+ monster = Character.new
62
+ db = DB.new
63
+
64
+ # fail
65
+ db.characters = [1, 2]
66
+
67
+ # pass
68
+ db.characters = [monster, Character.new]
69
+
70
+ # fail
71
+ db.monsters = [:dummy]
72
+
73
+ # pass
74
+ db.monsters = [monster]
75
+ end
76
+
77
+ * "inference", check under first passed object's class
78
+ class FlexibleContainer < Striuct.new
79
+ member :anything, inference
80
+ member :number, inference, Numeric
81
+ end
82
+
83
+ fc1, fc2 = FlexibleContainer.new, FlexibleContainer.new
84
+ # pass
85
+ fc1.anything = 'str'
86
+
87
+ # fail
88
+ fc1.anything = :sym
89
+ fc2.anything = :sym
90
+
91
+ # pass
92
+ fc2.anything = 'string too'
93
+
94
+ # fail
95
+ fc1.number = 'str'
96
+
97
+ # pass
98
+ fc1.number = 1.0
99
+
100
+ # fail
101
+ fc2.number = 1
102
+
103
+ * with flavor for type cast
104
+ class User2 < Striuct.new
105
+ member :age, /\A\d+\z/, Numeric do |arg|
106
+ Integer arg
107
+ end
108
+
109
+ member :name, ->v{v.respond_to? :to_s} do |v|
110
+ v.to_s.to_sym
111
+ end
112
+ end
113
+
114
+ user2 = User2.new
115
+ user2.age = 9 #=> 9(Fixnum)
116
+ user2.age = 10.1 #=> 10(Fixnum)
117
+ user2.age = '10' #=> 10(Fixnum)
118
+
119
+ user2.name = 10 #=> :10(Symbol)
120
+
121
+ * but, linked objects are able to clash
122
+ user.strict? #=> true
123
+ user.address.clear
124
+ user.strict? #=> false
125
+
126
+ * use default value
127
+ class User3 < Striuct.new
128
+ member :lank, Fixnum
129
+ default :lank, 3
130
+ member :name
131
+ end
132
+
133
+ user3 = User3.new
134
+ user3.lank #=> 3
135
+
136
+ * Standard Struct always define "nil is default". ...realy?
137
+ user3.name #=> nil
138
+ user3.assign? :name #=> false
139
+ user3.name = nil
140
+ user3.assign? :name #=> true
141
+
142
+ * Standard Struct no check member name.
143
+ NoGuard = Struct.new :__send__, :'? !'
144
+ noguard = NoGuard.new false
145
+ p noguard.__send__
146
+ p noguard.methods.include?(:'? !') # lost!!
147
+
148
+ * Striuct provides safety levels for naming.
149
+ class SafetyNaming < Striuct.new
150
+ begin
151
+ member :__send__
152
+ rescue
153
+ p $!
154
+ end
155
+
156
+ begin
157
+ member :'? !'
158
+ rescue
159
+ p $!
160
+ end
161
+
162
+ protect_level :struct
163
+
164
+ member :__send__, :'? !'
165
+ end
166
+
167
+
168
+ * Of course, keeping Struct's good interface
169
+ Sth1 = Striuct.new :id, :last_name, :family_name, :address, :age
170
+
171
+ Sth2 = Striuct.new do
172
+ def my_special_method
173
+ end
174
+ end
175
+
176
+ Sth2.new.respond_to?(:my_special_method) #=> true
177
+
178
+ * Here, not taint your name-space. but enhancers are too, you can choose it.
179
+ require 'striuct/import'
180
+
181
+ * run example.rb
182
+
183
+ * EasyGuide (in Japanese)
184
+ https://github.com/kachick/striuct/wiki/EasyGuide
185
+
186
+
187
+ == REQUIREMENTS
188
+
189
+ === Ruby
190
+ * 1.9.3
191
+ * 1.9.2
192
+
193
+ == INSTALL
194
+
195
+ * sudo gem install striuct
196
+
197
+ == LICENSE
198
+
199
+ (The MIT License)
200
+
201
+ Copyright (c) 2011 Kenichi Kamiya
202
+
203
+ Permission is hereby granted, free of charge, to any person obtaining
204
+ a copy of this software and associated documentation files (the
205
+ 'Software'), to deal in the Software without restriction, including
206
+ without limitation the rights to use, copy, modify, merge, publish,
207
+ distribute, sublicense, and/or sell copies of the Software, and to
208
+ permit persons to whom the Software is furnished to do so, subject to
209
+ the following conditions:
210
+
211
+ The above copyright notice and this permission notice shall be
212
+ included in all copies or substantial portions of the Software.
213
+
214
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
215
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
216
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
217
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
218
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
219
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
220
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,22 @@
1
+ require 'rubygems'
2
+ gem 'hoe', '>= 2.12.4'
3
+ require 'hoe'
4
+ require 'fileutils'
5
+
6
+ Hoe.plugin :newgem
7
+ # Hoe.plugin :website
8
+ # Hoe.plugin :cucumberfeatures
9
+
10
+ # Generate all the Rake tasks
11
+ # Run 'rake -T' to see list of generated tasks (from gem root directory)
12
+ $hoe = Hoe.spec 'striuct' do
13
+ self.developer 'Kenichi Kamiya', 'kachick1+ruby@gmail.com'
14
+ self.rubyforge_name = self.name # TODO this is default value
15
+ end
16
+
17
+ require 'newgem/tasks'
18
+ Dir['tasks/**/*.rake'].each { |t| load t }
19
+
20
+ # TODO - want other tests/tasks run by default? Add them to the list
21
+ # remove_task :default
22
+ # task :default => [:spec, :features]