xml_mapper 0.3.3 → 0.4.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.
- data/VERSION +1 -1
- data/lib/xml_mapper.rb +50 -36
- data/spec/example_spec.rb +6 -3
- data/spec/fixtures/base.xml +12 -2
- data/spec/my_mapper.rb +8 -1
- data/spec/xml_mapper_spec.rb +182 -3
- data/xml_mapper.gemspec +2 -2
- metadata +5 -5
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.4.0
|
data/lib/xml_mapper.rb
CHANGED
@@ -6,24 +6,10 @@ class XmlMapper
|
|
6
6
|
class << self
|
7
7
|
attr_accessor :mapper
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
def integer(*args)
|
14
|
-
mapper.add_mapping(:integer, *args)
|
15
|
-
end
|
16
|
-
|
17
|
-
def boolean(*args)
|
18
|
-
mapper.add_mapping(:boolean, *args)
|
19
|
-
end
|
20
|
-
|
21
|
-
def exists(*args)
|
22
|
-
mapper.add_mapping(:exists, *args)
|
23
|
-
end
|
24
|
-
|
25
|
-
def node(*args)
|
26
|
-
mapper.add_mapping(:node, *args)
|
9
|
+
[:text, :integer, :boolean, :exists, :not_exists, :node_name, :inner_text, :node, :attribute].each do |method_name|
|
10
|
+
define_method(method_name) do |*args|
|
11
|
+
mapper.add_mapping(method_name, *args)
|
12
|
+
end
|
27
13
|
end
|
28
14
|
|
29
15
|
def within(xpath, &block)
|
@@ -63,7 +49,7 @@ class XmlMapper
|
|
63
49
|
|
64
50
|
def capture_submapping(&block)
|
65
51
|
saved_mapper = self.mapper
|
66
|
-
self.mapper =
|
52
|
+
self.mapper = self.new
|
67
53
|
self.instance_eval(&block)
|
68
54
|
captured_mapper = self.mapper
|
69
55
|
self.mapper = saved_mapper
|
@@ -94,7 +80,10 @@ class XmlMapper
|
|
94
80
|
def add_mapping(type, *args)
|
95
81
|
options = extract_options_from_args(args)
|
96
82
|
if args.first.is_a?(Hash)
|
97
|
-
args.first.
|
83
|
+
if after_map_method = args.first.delete(:after_map)
|
84
|
+
options.merge!(:after_map => after_map_method)
|
85
|
+
end
|
86
|
+
args.first.map { |xpath, key| add_single_mapping(type, xpath, key, options) }
|
98
87
|
else
|
99
88
|
args.map { |arg| add_single_mapping(type, arg, arg, options) }
|
100
89
|
end
|
@@ -104,8 +93,14 @@ class XmlMapper
|
|
104
93
|
self.after_map_block = block
|
105
94
|
end
|
106
95
|
|
107
|
-
def add_single_mapping(type,
|
108
|
-
|
96
|
+
def add_single_mapping(type, xpath_or_attribute, key, options = {})
|
97
|
+
mappings = { :type => type, :key => key, :options => options }
|
98
|
+
xpath = type == :attribute ? nil : xpath_or_attribute
|
99
|
+
if type == :attribute
|
100
|
+
mappings[:attribute] = xpath_or_attribute.to_s
|
101
|
+
end
|
102
|
+
mappings[:xpath] = add_with_to_xpath(xpath)
|
103
|
+
self.mappings << mappings
|
109
104
|
end
|
110
105
|
|
111
106
|
def add_with_to_xpath(xpath)
|
@@ -126,6 +121,7 @@ class XmlMapper
|
|
126
121
|
xml_or_doc.map { |doc| attributes_from_xml(doc) }
|
127
122
|
else
|
128
123
|
doc = xml_or_doc.is_a?(Nokogiri::XML::Node) ? xml_or_doc : Nokogiri::XML(xml_or_doc)
|
124
|
+
doc = doc.root if doc.respond_to?(:root)
|
129
125
|
atts = self.mappings.inject(xml_path.nil? ? {} : { :xml_path => xml_path }) do |hash, mapping|
|
130
126
|
hash.merge(mapping[:key] => value_from_doc_and_mapping(doc, mapping))
|
131
127
|
end
|
@@ -137,28 +133,44 @@ class XmlMapper
|
|
137
133
|
def value_from_doc_and_mapping(doc, mapping)
|
138
134
|
if mapping[:type] == :many
|
139
135
|
mapping[:options][:mapper].attributes_from_xml(doc.search(mapping[:xpath]).to_a)
|
140
|
-
elsif mapping[:type] == :exists
|
141
|
-
!doc.at("//#{mapping[:xpath]}").nil?
|
142
136
|
else
|
143
|
-
|
144
|
-
|
137
|
+
node = mapping[:xpath].length == 0 ? doc : doc.xpath(mapping[:xpath]).first
|
138
|
+
if mapping[:type] == :exists
|
139
|
+
!node.nil?
|
140
|
+
elsif mapping[:type] == :not_exists
|
141
|
+
node.nil?
|
142
|
+
else
|
143
|
+
value =
|
144
|
+
case mapping[:type]
|
145
|
+
when :node_name
|
146
|
+
doc.nil? ? nil : doc.name
|
147
|
+
when :inner_text
|
148
|
+
doc.nil? ? nil : doc.inner_text
|
149
|
+
when :node
|
150
|
+
node
|
151
|
+
when :attribute
|
152
|
+
node.nil? ? nil : (node.respond_to?(:root) ? node.root : node)[mapping[:attribute]]
|
153
|
+
else
|
154
|
+
inner_text_for_node(node)
|
155
|
+
end
|
156
|
+
apply_after_map_to_value(value, mapping)
|
157
|
+
end
|
145
158
|
end
|
146
159
|
end
|
147
160
|
|
148
161
|
def apply_after_map_to_value(value, mapping)
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
162
|
+
after_mappings = [TYPE_TO_AFTER_CODE[mapping[:type]], mapping[:options][:after_map]].compact
|
163
|
+
if value
|
164
|
+
after_mappings.each do |after_map|
|
165
|
+
value = value.send(after_map) if value.respond_to?(after_map)
|
166
|
+
value = self.send(after_map, value) if self.respond_to?(after_map)
|
167
|
+
end
|
154
168
|
end
|
155
169
|
value
|
156
170
|
end
|
157
171
|
|
158
|
-
def
|
159
|
-
if node
|
160
|
-
node.inner_text
|
161
|
-
end
|
172
|
+
def inner_text_for_node(node)
|
173
|
+
node.inner_text if node
|
162
174
|
end
|
163
175
|
|
164
176
|
MAPPINGS = {
|
@@ -166,7 +178,9 @@ class XmlMapper
|
|
166
178
|
"false" => false,
|
167
179
|
"yes" => true,
|
168
180
|
"y" => true,
|
169
|
-
"n" => false
|
181
|
+
"n" => false,
|
182
|
+
"1" => true,
|
183
|
+
"0" => false
|
170
184
|
}
|
171
185
|
|
172
186
|
def string_to_boolean(value)
|
data/spec/example_spec.rb
CHANGED
@@ -11,7 +11,10 @@ describe "ExampleSpec" do
|
|
11
11
|
{
|
12
12
|
:title => "Black on Both Sides", :version_title => "Extended Edition", :released_in => 1999,
|
13
13
|
:artist_name => "Mos Def", :artist_id => 1212, :country => "DE", :allows_streaming => true,
|
14
|
-
:tracks_count => 2, :released_on => Date.new(1999, 10, 12)
|
14
|
+
:tracks_count => 2, :released_on => Date.new(1999, 10, 12), :contributions => [
|
15
|
+
{ :role => "artist", :name => "Mos Def" },
|
16
|
+
{ :role => "producer", :name => "DJ Premier" },
|
17
|
+
]
|
15
18
|
}.each do |key, value|
|
16
19
|
it "extracts #{value.inspect} as #{key}" do
|
17
20
|
@attributes[key].should == value
|
@@ -19,8 +22,8 @@ describe "ExampleSpec" do
|
|
19
22
|
end
|
20
23
|
|
21
24
|
[
|
22
|
-
{ :track_title => "Fear Not of Man", :track_number => 1, :disk_number => 1, :explicit_lyrics => true },
|
23
|
-
{ :track_title => "Hip Hop", :track_number => 2, :disk_number => 1, :explicit_lyrics =>
|
25
|
+
{ :track_title => "Fear Not of Man", :track_number => 1, :disk_number => 1, :explicit_lyrics => true, :isrc => "1234" },
|
26
|
+
{ :track_title => "Hip Hop", :track_number => 2, :disk_number => 1, :explicit_lyrics => false, :isrc => "2345" },
|
24
27
|
].each_with_index do |hash, offset|
|
25
28
|
hash.each do |key, value|
|
26
29
|
it "extracts #{value.inspect} for #{key} for track with offset #{offset}" do
|
data/spec/fixtures/base.xml
CHANGED
@@ -9,17 +9,27 @@
|
|
9
9
|
<name>Mos Def</name>
|
10
10
|
<id>1212</id>
|
11
11
|
</artist>
|
12
|
+
<contributions>
|
13
|
+
<artist>Mos Def</artist>
|
14
|
+
<producer>DJ Premier</producer>
|
15
|
+
</contributions>
|
12
16
|
<tracks>
|
13
|
-
<track>
|
17
|
+
<track code="1234">
|
14
18
|
<title>Fear Not of Man</title>
|
15
19
|
<number>1</number>
|
16
20
|
<disk>1</number>
|
17
21
|
<explicit_lyrics />
|
22
|
+
<not_streamable_in>
|
23
|
+
<country>de</country>
|
24
|
+
</not_streamable_in>
|
18
25
|
</track>
|
19
|
-
<track>
|
26
|
+
<track code="2345">
|
20
27
|
<title>Hip Hop</title>
|
21
28
|
<number>2</number>
|
22
29
|
<disk>1</number>
|
30
|
+
<not_streamable_in>
|
31
|
+
<country>at</country>
|
32
|
+
</not_streamable_in>
|
23
33
|
</track>
|
24
34
|
</tracks>
|
25
35
|
</album>
|
data/spec/my_mapper.rb
CHANGED
@@ -13,11 +13,18 @@ class MyMapper < XmlMapper
|
|
13
13
|
integer :id => :artist_id
|
14
14
|
end
|
15
15
|
|
16
|
+
many "contributions/*" => :contributions do # use the name of xml nodes for mappings
|
17
|
+
node_name :role # map name of xml node to :role
|
18
|
+
inner_text :name # map inner_text of xml node to :name
|
19
|
+
end
|
20
|
+
|
16
21
|
many "tracks/track" => :tracks do # maps xpath "tracks/track" to array with key :tracks
|
22
|
+
attribute :code => :isrc # map xml attribute "code" to :isrc
|
17
23
|
text :title => :track_title
|
18
24
|
integer :number => :track_number
|
19
25
|
integer :disk => :disk_number
|
20
|
-
exists :explicit_lyrics
|
26
|
+
exists :explicit_lyrics # checks if a node with the xpath exists
|
27
|
+
not_exists "not_streamable_in/country[text()='de']" => :allows_streaming
|
21
28
|
end
|
22
29
|
|
23
30
|
after_map do # is called after attributes are extracted, self references the extracted attributes
|
data/spec/xml_mapper_spec.rb
CHANGED
@@ -29,6 +29,20 @@ describe "XmlMapper" do
|
|
29
29
|
]
|
30
30
|
end
|
31
31
|
|
32
|
+
it "sets attribute for attribute mapping when attribute is mapped to same name" do
|
33
|
+
@mapper.add_mapping(:attribute, :first_name)
|
34
|
+
@mapper.mappings.should == [
|
35
|
+
{ :type => :attribute, :attribute => "first_name", :key => :first_name, :options => {}, :xpath => "" }
|
36
|
+
]
|
37
|
+
end
|
38
|
+
|
39
|
+
it "sets attribute for attribute mapping when attribute is mapped to different name" do
|
40
|
+
@mapper.add_mapping(:attribute, :first_name => :firstname)
|
41
|
+
@mapper.mappings.should == [
|
42
|
+
{ :type => :attribute, :attribute => "first_name", :key => :firstname, :options => {}, :xpath => "" }
|
43
|
+
]
|
44
|
+
end
|
45
|
+
|
32
46
|
it "adds mappings when mapping given as hash" do
|
33
47
|
@mapper.add_mapping(:text, :name => :first_name)
|
34
48
|
@mapper.mappings.should == [{ :type => :text, :xpath => "name", :key => :first_name, :options => {} }]
|
@@ -61,6 +75,7 @@ describe "XmlMapper" do
|
|
61
75
|
describe "#exists" do
|
62
76
|
it "returns true when node exists" do
|
63
77
|
xml = %(<album><title>Black on Both Sides</title><rights><country>DE</country></rights></album>)
|
78
|
+
root = Nokogiri::XML(xml).root
|
64
79
|
@mapper.add_mapping(:exists, "rights[country='DE']" => :allows_streaming)
|
65
80
|
@mapper.attributes_from_xml(xml).should == { :allows_streaming => true }
|
66
81
|
end
|
@@ -138,10 +153,29 @@ describe "XmlMapper" do
|
|
138
153
|
}
|
139
154
|
end
|
140
155
|
|
156
|
+
it "allows multiple after_code mappings" do
|
157
|
+
class << @mapper
|
158
|
+
def double(value)
|
159
|
+
value * 2
|
160
|
+
end
|
161
|
+
end
|
162
|
+
@mapper.add_mapping(:integer, :track_number, :after_map => :double)
|
163
|
+
@mapper.attributes_from_xml(@xml).should == {
|
164
|
+
:track_number => 14
|
165
|
+
}
|
166
|
+
end
|
167
|
+
|
168
|
+
it "allows defining a after_map mapping without ridicolous brackets" do
|
169
|
+
@mapper.add_mapping(:string, :track_number => :num, :after_map => :to_i)
|
170
|
+
@mapper.attributes_from_xml(@xml).should == {
|
171
|
+
:num => 7
|
172
|
+
}
|
173
|
+
end
|
174
|
+
|
141
175
|
it "uses mapper method defined in xml_mapper when value does not respond to :after_map and given as hash" do
|
142
176
|
class << @mapper
|
143
177
|
def double(value)
|
144
|
-
value
|
178
|
+
value * 2
|
145
179
|
end
|
146
180
|
end
|
147
181
|
# [{:type=>:text, :xpath=>"Graphic/ImgFormat", :key=>:image_format, :options=>{:after_map=>:double}}]
|
@@ -153,12 +187,27 @@ describe "XmlMapper" do
|
|
153
187
|
|
154
188
|
it "takes a nokogiri node as argument" do
|
155
189
|
@mapper.add_mapping(:text, :artist_name)
|
156
|
-
@mapper.attributes_from_xml(Nokogiri::XML(@xml)).should == {
|
190
|
+
@mapper.attributes_from_xml(Nokogiri::XML(@xml).root).should == {
|
191
|
+
:artist_name => "Mos Def"
|
192
|
+
}
|
193
|
+
end
|
194
|
+
|
195
|
+
it "takes a nokogiri document as argument" do
|
196
|
+
@mapper.add_mapping(:text, :artist_name)
|
197
|
+
@mapper.attributes_from_xml(Nokogiri::XML(@xml).root).should == {
|
157
198
|
:artist_name => "Mos Def"
|
158
199
|
}
|
159
200
|
end
|
160
201
|
|
161
202
|
it "should also takes an array of nodes as argument" do
|
203
|
+
@mapper.add_mapping(:text, :artist_name)
|
204
|
+
@mapper.attributes_from_xml([Nokogiri::XML(@xml).root, Nokogiri::XML(@xml).root]).should == [
|
205
|
+
{ :artist_name => "Mos Def" },
|
206
|
+
{ :artist_name => "Mos Def" }
|
207
|
+
]
|
208
|
+
end
|
209
|
+
|
210
|
+
it "also takes an array of nokogiri documents as argument" do
|
162
211
|
@mapper.add_mapping(:text, :artist_name)
|
163
212
|
@mapper.attributes_from_xml([Nokogiri::XML(@xml), Nokogiri::XML(@xml)]).should == [
|
164
213
|
{ :artist_name => "Mos Def" },
|
@@ -265,7 +314,7 @@ describe "XmlMapper" do
|
|
265
314
|
describe "#string_to_boolean" do
|
266
315
|
{
|
267
316
|
"true" => true, "false" => false, "y" => true, "TRUE" => true, "" => nil, "YES" => true, "yes" => true,
|
268
|
-
"n" => false
|
317
|
+
"n" => false, "1" => true, "0" => false
|
269
318
|
}.each do |value, result|
|
270
319
|
it "converts #{value.inspect} to #{result}" do
|
271
320
|
@mapper.string_to_boolean(value).should == result
|
@@ -351,6 +400,31 @@ describe "XmlMapper" do
|
|
351
400
|
}
|
352
401
|
end
|
353
402
|
|
403
|
+
it "allows after map when used in submapper and method exists in mapper" do
|
404
|
+
xml = %(
|
405
|
+
<album>
|
406
|
+
<tracks>
|
407
|
+
<track>
|
408
|
+
<track_number>11</track_number>
|
409
|
+
</track>
|
410
|
+
<track>
|
411
|
+
<track_number>22</track_number>
|
412
|
+
</track>
|
413
|
+
</tracks>
|
414
|
+
</album>
|
415
|
+
)
|
416
|
+
@clazz.send(:define_method, "double") do |*args|
|
417
|
+
args.first * 2
|
418
|
+
end
|
419
|
+
|
420
|
+
@clazz.many "tracks/track" => :tracks do
|
421
|
+
integer :track_number => :num, :after_map => :double
|
422
|
+
end
|
423
|
+
@clazz.attributes_from_xml(xml).should == {
|
424
|
+
:tracks => [ { :num => 22 }, { :num => 44 }]
|
425
|
+
}
|
426
|
+
end
|
427
|
+
|
354
428
|
it "accepts boolean as keyword" do
|
355
429
|
@clazz.boolean(:allows_streaming)
|
356
430
|
xml = %(<album><title>Test Title</title><allows_streaming>true</allows_streaming></album>)
|
@@ -363,6 +437,41 @@ describe "XmlMapper" do
|
|
363
437
|
@clazz.attributes_from_xml(xml).should == { :allows_streaming => true }
|
364
438
|
end
|
365
439
|
|
440
|
+
it "accepts not_exists as keyword" do
|
441
|
+
@clazz.not_exists("forbidden_countries/country[text()='DE']" => :allows_streaming)
|
442
|
+
xml = %(<album><title>Black on Both Sides</title><forbidden_countries><country>DE</country></rights></album>)
|
443
|
+
@clazz.attributes_from_xml(xml).should == { :allows_streaming => false }
|
444
|
+
end
|
445
|
+
|
446
|
+
it "does keep scope for not_exists" do
|
447
|
+
xml = %(
|
448
|
+
<album>
|
449
|
+
<tracks>
|
450
|
+
<track>
|
451
|
+
<title>Track 1</title>
|
452
|
+
<forbidden_countries>
|
453
|
+
<country>DE</country>
|
454
|
+
</forbidden_countries>
|
455
|
+
</track>
|
456
|
+
<track>
|
457
|
+
<title>Track 2</title>
|
458
|
+
<forbidden_countries>
|
459
|
+
<country>AT</country>
|
460
|
+
</forbidden_countries>
|
461
|
+
</track>
|
462
|
+
</tracks>
|
463
|
+
</album>
|
464
|
+
)
|
465
|
+
@clazz.many "tracks/track" => :tracks do
|
466
|
+
text :title
|
467
|
+
not_exists "forbidden_countries/country[text()='DE']" => :allows_streaming
|
468
|
+
end
|
469
|
+
@clazz.attributes_from_xml(xml)[:tracks].should == [
|
470
|
+
{ :title => "Track 1", :allows_streaming => false },
|
471
|
+
{ :title => "Track 2", :allows_streaming => true },
|
472
|
+
]
|
473
|
+
end
|
474
|
+
|
366
475
|
describe "#within" do
|
367
476
|
it "adds the within xpath to all xpath mappings" do
|
368
477
|
@clazz.within("artist") do
|
@@ -511,5 +620,75 @@ describe "XmlMapper" do
|
|
511
620
|
end
|
512
621
|
end
|
513
622
|
|
623
|
+
|
624
|
+
describe "using node_name, inner_text and attribute" do
|
625
|
+
it "extracts attributes for a many relationship when node_name and inner_text is used" do
|
626
|
+
xml = %(
|
627
|
+
<album>
|
628
|
+
<Contributors>
|
629
|
+
<Performer>Sexy sushi</Performer>
|
630
|
+
<Composer>Sexi Sushi</Composer>
|
631
|
+
<Author>Sexi Sushi</Author>
|
632
|
+
</Contributors>
|
633
|
+
</album>
|
634
|
+
)
|
635
|
+
@clazz.many "Contributors/*" => :contributions do
|
636
|
+
node_name :contribution_type
|
637
|
+
inner_text :name
|
638
|
+
end
|
639
|
+
@clazz.attributes_from_xml(xml).should == {
|
640
|
+
:contributions => [
|
641
|
+
{ :contribution_type => "Performer", :name => "Sexy sushi" },
|
642
|
+
{ :contribution_type => "Composer", :name => "Sexi Sushi" },
|
643
|
+
{ :contribution_type => "Author", :name => "Sexi Sushi" },
|
644
|
+
]
|
645
|
+
}
|
646
|
+
end
|
647
|
+
|
648
|
+
it "extracts the correct attributes when attribute keyword is used in 'many'-mapping" do
|
649
|
+
xml = %(
|
650
|
+
<album>
|
651
|
+
<tracks>
|
652
|
+
<track some_code="1234">
|
653
|
+
<title>Track 1</title>
|
654
|
+
</track>
|
655
|
+
</tracks>
|
656
|
+
</album>
|
657
|
+
)
|
658
|
+
@clazz.many "tracks/track" => :tracks do
|
659
|
+
attribute "some_code" => :isrc
|
660
|
+
text :title
|
661
|
+
end
|
662
|
+
@clazz.attributes_from_xml(xml).should == {
|
663
|
+
:tracks => [
|
664
|
+
{ :isrc => "1234", :title => "Track 1" }
|
665
|
+
]
|
666
|
+
}
|
667
|
+
end
|
668
|
+
|
669
|
+
it "extracts the correct attributes when attribute is used in within-mapping" do
|
670
|
+
xml = %(
|
671
|
+
<album>
|
672
|
+
<meta code="1234">
|
673
|
+
<title>Product Title</title>
|
674
|
+
</meta>
|
675
|
+
</></album>
|
676
|
+
)
|
677
|
+
@clazz.within "meta" do
|
678
|
+
attribute "code" => :upc
|
679
|
+
end
|
680
|
+
@clazz.attributes_from_xml(xml)[:upc].should == "1234"
|
681
|
+
end
|
682
|
+
|
683
|
+
it "extracts the correct attributes when attribute is used in root mapping" do
|
684
|
+
xml = %(
|
685
|
+
<album code="1234">
|
686
|
+
<title>Product Title</title>
|
687
|
+
</></album>
|
688
|
+
)
|
689
|
+
@clazz.attribute :code => :upc
|
690
|
+
@clazz.attributes_from_xml(xml)[:upc].should == "1234"
|
691
|
+
end
|
692
|
+
end
|
514
693
|
end
|
515
694
|
end
|
data/xml_mapper.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{xml_mapper}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.4.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Tobias Schwab"]
|
12
|
-
s.date = %q{2010-
|
12
|
+
s.date = %q{2010-12-01}
|
13
13
|
s.description = %q{Declarative XML to Ruby mapping}
|
14
14
|
s.email = %q{tobias.schwab@dynport.de}
|
15
15
|
s.extra_rdoc_files = [
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: xml_mapper
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 15
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
8
|
+
- 4
|
9
|
+
- 0
|
10
|
+
version: 0.4.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Tobias Schwab
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-
|
18
|
+
date: 2010-12-01 00:00:00 +01:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|