rroonga 1.0.3 → 1.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/NEWS.ja.rdoc +12 -1
- data/NEWS.rdoc +11 -0
- data/ext/groonga/rb-grn-column.c +84 -10
- data/ext/groonga/rb-grn-object.c +13 -12
- data/ext/groonga/rb-grn-utils.c +4 -3
- data/ext/groonga/rb-grn.h +1 -1
- data/html/index.html +1 -1
- data/lib/groonga/record.rb +33 -6
- data/lib/groonga/schema.rb +1 -0
- data/test/test-fix-size-column.rb +10 -2
- data/test/test-index-column.rb +24 -2
- data/test/test-record.rb +43 -0
- data/test/test-variable-size-column.rb +10 -2
- metadata +3 -3
data/NEWS.ja.rdoc
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
= お知らせ
|
2
2
|
|
3
|
-
== 1.0.
|
3
|
+
== 1.0.4: 2010-11-29
|
4
4
|
|
5
5
|
=== 改良
|
6
6
|
|
@@ -31,6 +31,15 @@
|
|
31
31
|
* Groonga::Database#touchを追加。
|
32
32
|
* Groonga::Table#exist?を追加。
|
33
33
|
* Groonga::Record#valid?を追加。
|
34
|
+
* Groonga::Column#vector?を追加。
|
35
|
+
* Groonga::Column#scalar?を追加。
|
36
|
+
* Groonga::Record#vector_column?を追加。
|
37
|
+
* Groonga::Record#scalar_column?を追加。
|
38
|
+
* レコードIDが必要なところにrecord_raw_idを持つオブジェクトなら
|
39
|
+
Groonga::Record以外も渡せるようにした。
|
40
|
+
* Groonga::Record#record_raw_idを追加。
|
41
|
+
* ベクタの参照カラムの値にArray以外でもto_aryを持つオブジェクトを
|
42
|
+
設定できるようにした。
|
34
43
|
|
35
44
|
== 変更
|
36
45
|
|
@@ -41,6 +50,8 @@
|
|
41
50
|
場合はShortTextを使用するようにした。
|
42
51
|
* Groonga::Schema#loadをGroonga::Schema#restoreに改名。
|
43
52
|
* pkg-config 1.0.7対応。
|
53
|
+
* Groonga::Column#index?を追加。Groonga::Column#index_column?は非推奨。
|
54
|
+
* Groonga::Column#reference?を追加。Groonga::Column#reference_column?は非推奨。
|
44
55
|
|
45
56
|
=== 修正
|
46
57
|
|
data/NEWS.rdoc
CHANGED
@@ -31,6 +31,14 @@
|
|
31
31
|
* Added Groonga::Database#touch.
|
32
32
|
* Added Groonga::Table#exist?.
|
33
33
|
* Added Groonga::Record#valid?.
|
34
|
+
* Added Groonga::Column#vector?.
|
35
|
+
* Added Groonga::Column#scalar?.
|
36
|
+
* Added Groonga::Record#vector_column?.
|
37
|
+
* Added Groonga::Record#scalar_column?.
|
38
|
+
* Accepted any object that has record_raw_id method for record ID required
|
39
|
+
location. Groonga::Record isn't required.
|
40
|
+
* Added Groonga::Record#record_raw_id.
|
41
|
+
* Accepted any object that as to_ary method for reference vector column value.
|
34
42
|
|
35
43
|
== Changes
|
36
44
|
|
@@ -41,6 +49,9 @@
|
|
41
49
|
Groonga::Hash#create and Groonga::PatriciaTrie#create.
|
42
50
|
* Renamed Groonga::Schema#load to Groonga::Schema#restore.
|
43
51
|
* Supported pkg-confg 1.0.7.
|
52
|
+
* Added Groonga::Column#index? and deprecated Groonga::Column#index_column?.
|
53
|
+
* Added Groonga::Column#reference? and deprecated
|
54
|
+
Groonga::Column#reference_column?.
|
44
55
|
|
45
56
|
=== Fixes
|
46
57
|
|
data/ext/groonga/rb-grn-column.c
CHANGED
@@ -553,16 +553,18 @@ rb_grn_column_is_locked (int argc, VALUE *argv, VALUE self)
|
|
553
553
|
}
|
554
554
|
|
555
555
|
/*
|
556
|
-
* Document-method:
|
556
|
+
* Document-method: reference?
|
557
557
|
*
|
558
558
|
* call-seq:
|
559
|
-
* column.
|
559
|
+
* column.reference? -> true/false
|
560
560
|
*
|
561
561
|
* _column_の値がテーブルのレコードとなる場合は+true+を返し、
|
562
562
|
* そうでない場合は+false+を返す。
|
563
|
+
*
|
564
|
+
* @since: 1.0.5
|
563
565
|
*/
|
564
566
|
static VALUE
|
565
|
-
|
567
|
+
rb_grn_column_reference_p (VALUE self)
|
566
568
|
{
|
567
569
|
grn_ctx *context;
|
568
570
|
grn_obj *column;
|
@@ -589,16 +591,18 @@ rb_grn_column_reference_column_p (VALUE self)
|
|
589
591
|
}
|
590
592
|
|
591
593
|
/*
|
592
|
-
* Document-method:
|
594
|
+
* Document-method: index?
|
593
595
|
*
|
594
596
|
* call-seq:
|
595
|
-
* column.
|
597
|
+
* column.index? -> true/false
|
596
598
|
*
|
597
599
|
* _column_がGroonga::IndexColumnの場合は+true+を返し、
|
598
600
|
* そうでない場合は+false+を返す。
|
601
|
+
*
|
602
|
+
* @since: 1.0.5
|
599
603
|
*/
|
600
604
|
static VALUE
|
601
|
-
|
605
|
+
rb_grn_column_index_p (VALUE self)
|
602
606
|
{
|
603
607
|
grn_ctx *context;
|
604
608
|
grn_obj *column;
|
@@ -614,6 +618,72 @@ rb_grn_column_index_column_p (VALUE self)
|
|
614
618
|
}
|
615
619
|
}
|
616
620
|
|
621
|
+
/*
|
622
|
+
* Document-method: vector?
|
623
|
+
*
|
624
|
+
* call-seq:
|
625
|
+
* column.vector? -> true/false
|
626
|
+
*
|
627
|
+
* _column_がベクターカラムの場合は+true+を返し、
|
628
|
+
* そうでない場合は+false+を返す。
|
629
|
+
*
|
630
|
+
* @since: 1.0.5
|
631
|
+
*/
|
632
|
+
static VALUE
|
633
|
+
rb_grn_column_vector_p (VALUE self)
|
634
|
+
{
|
635
|
+
grn_ctx *context;
|
636
|
+
grn_obj *column;
|
637
|
+
|
638
|
+
rb_grn_column_deconstruct(SELF(self), &column, &context,
|
639
|
+
NULL, NULL,
|
640
|
+
NULL, NULL, NULL);
|
641
|
+
|
642
|
+
if (column->header.type == GRN_COLUMN_VAR_SIZE &&
|
643
|
+
((column->header.flags & GRN_OBJ_COLUMN_TYPE_MASK) ==
|
644
|
+
GRN_OBJ_COLUMN_VECTOR)) {
|
645
|
+
return Qtrue;
|
646
|
+
} else {
|
647
|
+
return Qfalse;
|
648
|
+
}
|
649
|
+
}
|
650
|
+
|
651
|
+
/*
|
652
|
+
* Document-method: scalar?
|
653
|
+
*
|
654
|
+
* call-seq:
|
655
|
+
* column.scalar? -> true/false
|
656
|
+
*
|
657
|
+
* _column_がスカラーカラムの場合は+true+を返し、
|
658
|
+
* そうでない場合は+false+を返す。
|
659
|
+
*
|
660
|
+
* @since: 1.0.5
|
661
|
+
*/
|
662
|
+
static VALUE
|
663
|
+
rb_grn_column_scalar_p (VALUE self)
|
664
|
+
{
|
665
|
+
grn_ctx *context;
|
666
|
+
grn_obj *column;
|
667
|
+
|
668
|
+
rb_grn_column_deconstruct(SELF(self), &column, &context,
|
669
|
+
NULL, NULL,
|
670
|
+
NULL, NULL, NULL);
|
671
|
+
|
672
|
+
switch (column->header.type) {
|
673
|
+
case GRN_COLUMN_FIX_SIZE:
|
674
|
+
return Qtrue;
|
675
|
+
case GRN_COLUMN_VAR_SIZE:
|
676
|
+
if ((column->header.flags & GRN_OBJ_COLUMN_TYPE_MASK) ==
|
677
|
+
GRN_OBJ_COLUMN_SCALAR) {
|
678
|
+
return Qtrue;
|
679
|
+
} else {
|
680
|
+
return Qfalse;
|
681
|
+
}
|
682
|
+
default:
|
683
|
+
return Qfalse;
|
684
|
+
}
|
685
|
+
}
|
686
|
+
|
617
687
|
void
|
618
688
|
rb_grn_init_column (VALUE mGrn)
|
619
689
|
{
|
@@ -628,10 +698,14 @@ rb_grn_init_column (VALUE mGrn)
|
|
628
698
|
rb_define_method(rb_cGrnColumn, "unlock", rb_grn_column_unlock, -1);
|
629
699
|
rb_define_method(rb_cGrnColumn, "clear_lock", rb_grn_column_clear_lock, -1);
|
630
700
|
rb_define_method(rb_cGrnColumn, "locked?", rb_grn_column_is_locked, -1);
|
631
|
-
rb_define_method(rb_cGrnColumn, "
|
632
|
-
|
633
|
-
|
634
|
-
|
701
|
+
rb_define_method(rb_cGrnColumn, "reference?", rb_grn_column_reference_p, 0);
|
702
|
+
/* deprecated: backward compatibility */
|
703
|
+
rb_define_alias(rb_cGrnColumn, "reference_column?", "reference?");
|
704
|
+
rb_define_method(rb_cGrnColumn, "index?", rb_grn_column_index_p, 0);
|
705
|
+
/* deprecated: backward compatibility */
|
706
|
+
rb_define_alias(rb_cGrnColumn, "index_column?", "index?");
|
707
|
+
rb_define_method(rb_cGrnColumn, "vector?", rb_grn_column_vector_p, 0);
|
708
|
+
rb_define_method(rb_cGrnColumn, "scalar?", rb_grn_column_scalar_p, 0);
|
635
709
|
|
636
710
|
rb_grn_init_fix_size_column(mGrn);
|
637
711
|
rb_grn_init_variable_size_column(mGrn);
|
data/ext/groonga/rb-grn-object.c
CHANGED
@@ -1199,7 +1199,7 @@ rb_uvector_value_p (RbGrnObject *rb_grn_object, VALUE rb_value)
|
|
1199
1199
|
case GRN_TABLE_NO_KEY:
|
1200
1200
|
case GRN_TABLE_VIEW:
|
1201
1201
|
first_element = rb_ary_entry(rb_value, 0);
|
1202
|
-
if (
|
1202
|
+
if (rb_respond_to(first_element, rb_intern("record_raw_id"))) {
|
1203
1203
|
return RB_GRN_TRUE;
|
1204
1204
|
}
|
1205
1205
|
break;
|
@@ -1217,25 +1217,26 @@ rb_grn_object_set_raw (RbGrnObject *rb_grn_object, grn_id id,
|
|
1217
1217
|
grn_ctx *context;
|
1218
1218
|
grn_obj value;
|
1219
1219
|
grn_rc rc;
|
1220
|
-
VALUE exception;
|
1220
|
+
VALUE exception, rb_values;
|
1221
1221
|
|
1222
1222
|
context = rb_grn_object->context;
|
1223
|
-
|
1224
|
-
|
1225
|
-
GRN_OBJ_INIT(&value, GRN_UVECTOR, 0,
|
1226
|
-
rb_grn_object->object->header.domain);
|
1227
|
-
RVAL2GRNUVECTOR(rb_value, context, &value, related_object);
|
1228
|
-
} else {
|
1229
|
-
GRN_OBJ_INIT(&value, GRN_VECTOR, 0, GRN_ID_NIL);
|
1230
|
-
RVAL2GRNVECTOR(rb_value, context, &value);
|
1231
|
-
}
|
1232
|
-
} else {
|
1223
|
+
rb_values = rb_check_array_type(rb_value);
|
1224
|
+
if (NIL_P(rb_values)) {
|
1233
1225
|
if (NIL_P(rb_value)) {
|
1234
1226
|
GRN_OBJ_INIT(&value, GRN_BULK, 0, GRN_ID_NIL);
|
1235
1227
|
} else {
|
1236
1228
|
GRN_OBJ_INIT(&value, GRN_BULK, 0, GRN_ID_NIL);
|
1237
1229
|
RVAL2GRNBULK(rb_value, context, &value);
|
1238
1230
|
}
|
1231
|
+
} else {
|
1232
|
+
if (rb_uvector_value_p(rb_grn_object, rb_values)) {
|
1233
|
+
GRN_OBJ_INIT(&value, GRN_UVECTOR, 0,
|
1234
|
+
rb_grn_object->object->header.domain);
|
1235
|
+
RVAL2GRNUVECTOR(rb_values, context, &value, related_object);
|
1236
|
+
} else {
|
1237
|
+
GRN_OBJ_INIT(&value, GRN_VECTOR, 0, GRN_ID_NIL);
|
1238
|
+
RVAL2GRNVECTOR(rb_values, context, &value);
|
1239
|
+
}
|
1239
1240
|
}
|
1240
1241
|
rc = grn_obj_set_value(context, rb_grn_object->object, id,
|
1241
1242
|
&value, flags);
|
data/ext/groonga/rb-grn-utils.c
CHANGED
@@ -555,13 +555,14 @@ rb_grn_uvector_from_ruby_object (VALUE object, grn_ctx *context,
|
|
555
555
|
id = NUM2UINT(value);
|
556
556
|
break;
|
557
557
|
default:
|
558
|
-
if (
|
559
|
-
id = NUM2UINT(rb_funcall(value, rb_intern("
|
558
|
+
if (rb_respond_to(value, rb_intern("record_raw_id"))) {
|
559
|
+
id = NUM2UINT(rb_funcall(value, rb_intern("record_raw_id"), 0));
|
560
560
|
} else {
|
561
561
|
grn_obj_unlink(context, uvector);
|
562
562
|
rb_raise(rb_eArgError,
|
563
563
|
"uvector value should be one of "
|
564
|
-
"[Fixnum
|
564
|
+
"[Fixnum or object that has #record_raw_id]: "
|
565
|
+
"%s (%s): %s",
|
565
566
|
rb_grn_inspect(value),
|
566
567
|
rb_grn_inspect(object),
|
567
568
|
rb_grn_inspect(related_object));
|
data/ext/groonga/rb-grn.h
CHANGED
data/html/index.html
CHANGED
data/lib/groonga/record.rb
CHANGED
@@ -21,8 +21,6 @@ module Groonga
|
|
21
21
|
class Record
|
22
22
|
# レコードが所属するテーブル
|
23
23
|
attr_reader :table
|
24
|
-
# レコードのID
|
25
|
-
attr_reader :id
|
26
24
|
# _table_の_id_に対応するレコードを作成する。_values_には各
|
27
25
|
# カラムに設定する値を以下のような形式で指定する。
|
28
26
|
#
|
@@ -129,7 +127,7 @@ module Groonga
|
|
129
127
|
#
|
130
128
|
# 名前が_name_のカラムが参照カラムであるなら+true+を返す。
|
131
129
|
def reference_column?(name)
|
132
|
-
column(name).
|
130
|
+
column(name).reference?
|
133
131
|
end
|
134
132
|
|
135
133
|
# call-seq:
|
@@ -138,7 +136,27 @@ module Groonga
|
|
138
136
|
# 名前が_name_のカラムが索引カラム
|
139
137
|
# (Groonga::IndexColumn)であるなら+true+を返す。
|
140
138
|
def index_column?(name)
|
141
|
-
column(name).
|
139
|
+
column(name).index?
|
140
|
+
end
|
141
|
+
|
142
|
+
# call-seq:
|
143
|
+
# record.vector_column?(name) -> true/false
|
144
|
+
#
|
145
|
+
# 名前が_name_のカラムの値がベクターであるなら+true+を返す。
|
146
|
+
#
|
147
|
+
# @since: 1.0.5
|
148
|
+
def vector_column?(name)
|
149
|
+
column(name).vector?
|
150
|
+
end
|
151
|
+
|
152
|
+
# call-seq:
|
153
|
+
# record.scalar_column?(name) -> true/false
|
154
|
+
#
|
155
|
+
# 名前が_name_のカラムの値がスカラーであるなら+true+を返す。
|
156
|
+
#
|
157
|
+
# @since: 1.0.5
|
158
|
+
def scalar_column?(name)
|
159
|
+
column(name).scalar?
|
142
160
|
end
|
143
161
|
|
144
162
|
# call-seq:
|
@@ -181,13 +199,22 @@ module Groonga
|
|
181
199
|
end
|
182
200
|
end
|
183
201
|
|
202
|
+
# call-seq:
|
203
|
+
# record.record_raw_id -> ID
|
204
|
+
#
|
205
|
+
# レコードのIDを返す。
|
206
|
+
def record_raw_id
|
207
|
+
@id
|
208
|
+
end
|
209
|
+
alias_method :id, :record_raw_id
|
210
|
+
|
184
211
|
# call-seq:
|
185
212
|
# record.score -> スコア値
|
186
213
|
#
|
187
214
|
# レコードのスコア値を返す。検索結果として生成されたテーブル
|
188
215
|
# のみに定義される。
|
189
216
|
def score
|
190
|
-
self["
|
217
|
+
self["_score"]
|
191
218
|
end
|
192
219
|
|
193
220
|
# call-seq:
|
@@ -199,7 +226,7 @@ module Groonga
|
|
199
226
|
# Groonga::Record#support_sub_recordsでこの値を利用でき
|
200
227
|
# るかがわかる。
|
201
228
|
def n_sub_records
|
202
|
-
self["
|
229
|
+
self["_nsubrecs"]
|
203
230
|
end
|
204
231
|
|
205
232
|
# call-seq:
|
data/lib/groonga/schema.rb
CHANGED
@@ -32,8 +32,16 @@ class FixSizeColumnTest < Test::Unit::TestCase
|
|
32
32
|
:path => @viewed_column_path.to_s)
|
33
33
|
end
|
34
34
|
|
35
|
-
def
|
36
|
-
assert_not_predicate(@viewed, :
|
35
|
+
def test_index?
|
36
|
+
assert_not_predicate(@viewed, :index?)
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_vector?
|
40
|
+
assert_not_predicate(@viewed, :vector?)
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_scalar?
|
44
|
+
assert_predicate(@viewed, :scalar?)
|
37
45
|
end
|
38
46
|
|
39
47
|
def test_inspect
|
data/test/test-index-column.rb
CHANGED
@@ -22,7 +22,7 @@ class IndexColumnTest < Test::Unit::TestCase
|
|
22
22
|
setup_database
|
23
23
|
end
|
24
24
|
|
25
|
-
def
|
25
|
+
def test_index?
|
26
26
|
articles = Groonga::Array.create(:name => "Articles")
|
27
27
|
articles.define_column("content", "Text")
|
28
28
|
|
@@ -30,7 +30,29 @@ class IndexColumnTest < Test::Unit::TestCase
|
|
30
30
|
:default_tokenizer => "TokenBigram")
|
31
31
|
content_index = terms.define_index_column("content", articles,
|
32
32
|
:with_section => true)
|
33
|
-
assert_predicate(content_index, :
|
33
|
+
assert_predicate(content_index, :index?)
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_vector?
|
37
|
+
articles = Groonga::Array.create(:name => "Articles")
|
38
|
+
articles.define_column("content", "Text")
|
39
|
+
|
40
|
+
terms = Groonga::Hash.create(:name => "Terms",
|
41
|
+
:default_tokenizer => "TokenBigram")
|
42
|
+
content_index = terms.define_index_column("content", articles,
|
43
|
+
:with_section => true)
|
44
|
+
assert_not_predicate(content_index, :vector?)
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_scalar?
|
48
|
+
articles = Groonga::Array.create(:name => "Articles")
|
49
|
+
articles.define_column("content", "Text")
|
50
|
+
|
51
|
+
terms = Groonga::Hash.create(:name => "Terms",
|
52
|
+
:default_tokenizer => "TokenBigram")
|
53
|
+
content_index = terms.define_index_column("content", articles,
|
54
|
+
:with_section => true)
|
55
|
+
assert_not_predicate(content_index, :scalar?)
|
34
56
|
end
|
35
57
|
|
36
58
|
def test_array_set_with_record
|
data/test/test-record.rb
CHANGED
@@ -171,6 +171,20 @@ class RecordTest < Test::Unit::TestCase
|
|
171
171
|
assert_true(index.index_column?("content"))
|
172
172
|
end
|
173
173
|
|
174
|
+
def test_vector_column?
|
175
|
+
bookmark = @bookmarks.add
|
176
|
+
assert_false(bookmark.vector_column?("uri"))
|
177
|
+
morita = @users.add("morita")
|
178
|
+
assert_true(morita.vector_column?("addresses"))
|
179
|
+
end
|
180
|
+
|
181
|
+
def test_scalar_column?
|
182
|
+
bookmark = @bookmarks.add
|
183
|
+
assert_true(bookmark.scalar_column?("uri"))
|
184
|
+
morita = @users.add("morita")
|
185
|
+
assert_false(morita.scalar_column?("addresses"))
|
186
|
+
end
|
187
|
+
|
174
188
|
def test_score
|
175
189
|
groonga = @bookmarks.add
|
176
190
|
groonga["content"] = "full text search search search engine."
|
@@ -282,4 +296,33 @@ class RecordTest < Test::Unit::TestCase
|
|
282
296
|
users = @users.select {|record| record.key == "morita"}
|
283
297
|
assert_predicate(users.to_a[0], :support_sub_records?)
|
284
298
|
end
|
299
|
+
|
300
|
+
def test_set_record_like_object
|
301
|
+
kou_at_clear_code = @addresses.add(:mail => "kou@clear-code.com")
|
302
|
+
record_like_class = Class.new do
|
303
|
+
attr_reader :record_raw_id
|
304
|
+
def initialize(record_raw_id)
|
305
|
+
@record_raw_id = record_raw_id
|
306
|
+
end
|
307
|
+
end
|
308
|
+
record_like_object = record_like_class.new(kou_at_clear_code.record_raw_id)
|
309
|
+
kou = @users.add("kou")
|
310
|
+
kou.addresses = [record_like_object]
|
311
|
+
end
|
312
|
+
|
313
|
+
def test_set_array_like_records
|
314
|
+
kou_at_clear_code = @addresses.add(:mail => "kou@clear-code.com")
|
315
|
+
array_like_class = Class.new do
|
316
|
+
def initialize(records)
|
317
|
+
@records = records
|
318
|
+
end
|
319
|
+
|
320
|
+
def to_ary
|
321
|
+
@records
|
322
|
+
end
|
323
|
+
end
|
324
|
+
array_like_object = array_like_class.new([kou_at_clear_code])
|
325
|
+
kou = @users.add("kou")
|
326
|
+
kou.addresses = array_like_object
|
327
|
+
end
|
285
328
|
end
|
@@ -50,8 +50,16 @@ class VariableSizeColumnTest < Test::Unit::TestCase
|
|
50
50
|
@yu = @users.add(:name => "Yutaro Shimamura")
|
51
51
|
end
|
52
52
|
|
53
|
-
def
|
54
|
-
assert_not_predicate(@nick_names, :
|
53
|
+
def test_index?
|
54
|
+
assert_not_predicate(@nick_names, :index?)
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_vector?
|
58
|
+
assert_predicate(@nick_names, :vector?)
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_scalar?
|
62
|
+
assert_not_predicate(@nick_names, :scalar?)
|
55
63
|
end
|
56
64
|
|
57
65
|
def test_inspect
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rroonga
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 31
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 1
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 1.0.
|
9
|
+
- 4
|
10
|
+
version: 1.0.4
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Kouhei Sutou
|