ruby-druid 0.1.8 → 0.1.9

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: adfe39dfd535cfb911d89bece7d3921b8e63c162
4
- data.tar.gz: 74fcfe3637e3131dfb9e057c3ee1c33ff62840bf
3
+ metadata.gz: d0e676ac15efc4d9777fa182d8c8855bc1ebf386
4
+ data.tar.gz: e54d2ec80e3bb5efdf02d3b5b127c565c5cfce86
5
5
  SHA512:
6
- metadata.gz: d06463d4a10c5d142f09b71acb3785bf8906cf5cf1719995b60006499754d609fce7ba1ed9b23ea338dd1587bb6b6bc967509c696ba2c09fc80e1a67367b529f
7
- data.tar.gz: a6726f41601627488627aeeedc55163b2e65602d3845dacf0a1bcb66ec412d7dca8333cdeb440a860046ac75a93447132cd0ed5d250d5094532ae50743cda7d9
6
+ metadata.gz: 884a621b0fb481490d114248bfff0207bc2fd54e889832cf86318c6d26fb53c73c535d97d4d832fc9872a4f6b76b0d426a7050190e41639abfad2d728a36dd7a
7
+ data.tar.gz: b46976c63af7169c6581d092522f5ac97098320efe903bd6d5a6e58c9c2792aab34d0e17c474de174fc44e74d91a0fc6594a89d39beaf3c8f7fabe3f432af21e
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --colour
2
+ --require spec_helper
data/.travis.yml CHANGED
@@ -3,8 +3,7 @@ rvm:
3
3
  - jruby
4
4
  - 2.0.0
5
5
  - 1.9.3
6
+ script:
7
+ - bundle exec rspec --format documentation
6
8
  notifications:
7
9
  email: false
8
- hipchat:
9
- rooms:
10
- secure: WhPGqnsNAVchiJz/rmmIPIFHXI7NVd+k/zClVhtgyoPEdebFYFgOCEIGbE/53IVymVeXFFBeJUVQg1Um4AVsZzVpS5sC6ABWw7rH5PZQZ7k177ZmuhbIAVYLLXcX0OmolgsATvGejifVj5i/Kld46kRx3JDlWL/mA465Kso7a/k=
data/README.md CHANGED
@@ -91,12 +91,18 @@ A simple syntax for post aggregations with +,-,/,* can be used like:
91
91
 
92
92
  ```ruby
93
93
  query = Druid::Query.new('service/source').long_sum([:aggregate1, :aggregate2])
94
- query.postagg{(aggregate2 + aggregate2).as output_field_name}
94
+ query.postagg { (aggregate2 + aggregate2).as output_field_name }
95
95
  ```
96
96
 
97
97
  Required fields for the postaggregation are fetched automatically by the
98
98
  library.
99
99
 
100
+ Javascript post aggregations are also supported:
101
+
102
+ ```ruby
103
+ query.postagg { js('function(aggregate1, aggregate2) { return aggregate1 + aggregate2; }').as result }
104
+ ```
105
+
100
106
  ### Query Interval
101
107
 
102
108
  The interval for the query takes a string with date and time or objects that
data/lib/druid/having.rb CHANGED
@@ -7,13 +7,19 @@ module Druid
7
7
  end
8
8
  end
9
9
 
10
- class HavingClause
11
- (instance_methods + private_instance_methods).each do |method|
12
- unless method.to_s =~ /^(__|instance_eval|instance_exec|initialize|object_id|raise|puts|inspect|class)/ || method.to_s =~ /\?/
13
- undef_method method
14
- end
10
+ class HavingFilter
11
+ include Serializable
12
+
13
+ def clause?
14
+ is_a?(HavingClause)
15
+ end
16
+
17
+ def operator?
18
+ is_a?(HavingOperator)
15
19
  end
20
+ end
16
21
 
22
+ class HavingClause < HavingFilter
17
23
  def initialize(metric)
18
24
  @metric = metric
19
25
  end
@@ -30,24 +36,34 @@ module Druid
30
36
  self
31
37
  end
32
38
 
33
- def to_s
34
- to_hash.to_s
39
+ def to_hash
40
+ {
41
+ :type => @type,
42
+ :aggregation => @metric,
43
+ :value => @value
44
+ }
45
+ end
46
+ end
47
+
48
+ class HavingOperator < HavingFilter
49
+ def initialize(type)
50
+ @type = type
51
+ @elements = []
35
52
  end
36
53
 
37
- def as_json(*a)
38
- to_hash
54
+ def and?
55
+ @type == 'and'
39
56
  end
40
57
 
41
- def to_json(*a)
42
- to_hash.to_json(*a)
58
+ def add(element)
59
+ @elements << element
43
60
  end
44
61
 
45
62
  def to_hash
46
63
  {
47
64
  :type => @type,
48
- :aggregation => @metric,
49
- :value => @value
65
+ :havingSpecs => @elements
50
66
  }
51
67
  end
52
68
  end
53
- end
69
+ end
@@ -5,6 +5,14 @@ module Druid
5
5
  PostAggregationField.new(name)
6
6
  end
7
7
  end
8
+
9
+ def js(*args)
10
+ if args.empty?
11
+ PostAggregationField.new(:js)
12
+ else
13
+ PostAggregationJavascript.new(args.first)
14
+ end
15
+ end
8
16
  end
9
17
 
10
18
  module PostAggregationOperators
@@ -90,6 +98,8 @@ module Druid
90
98
  end
91
99
 
92
100
  class PostAggregationConstant
101
+ include PostAggregationOperators
102
+
93
103
  attr_reader :value
94
104
 
95
105
  def initialize(value)
@@ -108,4 +118,40 @@ module Druid
108
118
  to_hash
109
119
  end
110
120
  end
121
+
122
+ class PostAggregationJavascript
123
+ include PostAggregationOperators
124
+ include Serializable
125
+
126
+ def initialize(function)
127
+ @field_names = extract_fields(function)
128
+ @function = function
129
+ end
130
+
131
+ def get_field_names
132
+ @field_names
133
+ end
134
+
135
+ def as(field)
136
+ @name = field.name.to_s
137
+ self
138
+ end
139
+
140
+ def to_hash
141
+ {
142
+ "type" => "javascript",
143
+ "name" => @name,
144
+ "fieldNames" => @field_names,
145
+ "function" => @function
146
+ }
147
+ end
148
+
149
+ private
150
+
151
+ def extract_fields(function)
152
+ match = function.match(/function\((.+)\)/)
153
+ raise 'Invalid Javascript function' unless match && match.captures
154
+ match.captures.first.split(',').map {|field| field.strip }
155
+ end
156
+ end
111
157
  end
data/lib/druid/query.rb CHANGED
@@ -1,6 +1,8 @@
1
+ require 'druid/serializable'
1
2
  require 'druid/filter'
2
3
  require 'druid/having'
3
4
  require 'druid/post_aggregation'
5
+
4
6
  require 'time'
5
7
  require 'json'
6
8
 
@@ -137,7 +139,20 @@ module Druid
137
139
 
138
140
  def having(&block)
139
141
  having = Having.new.instance_exec(&block)
140
- @properties[:having] = having
142
+
143
+ if old_having = @properties[:having]
144
+ if old_having.operator? && old_having.and?
145
+ new_having = old_having
146
+ else
147
+ new_having = HavingOperator.new('and')
148
+ new_having.add(old_having)
149
+ end
150
+ new_having.add(having)
151
+ else
152
+ new_having = having
153
+ end
154
+
155
+ @properties[:having] = new_having
141
156
  self
142
157
  end
143
158
 
@@ -0,0 +1,19 @@
1
+ module Druid
2
+ module Serializable
3
+ def to_hash
4
+ {}
5
+ end
6
+
7
+ def to_s
8
+ to_hash.to_s
9
+ end
10
+
11
+ def as_json(*a)
12
+ to_hash
13
+ end
14
+
15
+ def to_json(*a)
16
+ to_hash.to_json(*a)
17
+ end
18
+ end
19
+ end
data/ruby-druid.gemspec CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |spec|
4
4
  spec.name = "ruby-druid"
5
- spec.version = "0.1.8"
5
+ spec.version = "0.1.9"
6
6
  spec.authors = ["LiquidM, Inc."]
7
7
  spec.email = ["opensource@liquidm.com"]
8
8
  spec.summary = %q{Ruby client for metamx druid}
@@ -1,5 +1,3 @@
1
- require 'spec_helper'
2
-
3
1
  describe Druid::Client do
4
2
 
5
3
  it 'calls zookeeper on intialize' do
@@ -1,5 +1,3 @@
1
- require "spec_helper"
2
-
3
1
  describe Druid::Query do
4
2
 
5
3
  before :each do
@@ -20,7 +18,7 @@ describe Druid::Query do
20
18
  @query.group_by()
21
19
  JSON.parse(@query.to_json)['queryType'].should == 'groupBy'
22
20
  end
23
-
21
+
24
22
  it 'sets query type to timeseries' do
25
23
  @query.time_series()
26
24
  JSON.parse(@query.to_json)['queryType'].should == 'timeseries'
@@ -39,91 +37,113 @@ describe Druid::Query do
39
37
  result['threshold'].should == 25
40
38
  end
41
39
 
42
- it 'build a post aggregation with a constant right' do
43
- @query.postagg{(a + 1).as ctr }
40
+ describe '#postagg' do
41
+ it 'build a post aggregation with a constant right' do
42
+ @query.postagg{(a + 1).as ctr }
44
43
 
45
- JSON.parse(@query.to_json)['postAggregations'].should == [{"type"=>"arithmetic",
46
- "fn"=>"+",
47
- "fields"=>
48
- [{"type"=>"fieldAccess", "name"=>"a", "fieldName"=>"a"},
49
- {"type"=>"constant", "value"=>1}],
50
- "name"=>"ctr"}]
51
- end
44
+ JSON.parse(@query.to_json)['postAggregations'].should == [{"type"=>"arithmetic",
45
+ "fn"=>"+",
46
+ "fields"=>
47
+ [{"type"=>"fieldAccess", "name"=>"a", "fieldName"=>"a"},
48
+ {"type"=>"constant", "value"=>1}],
49
+ "name"=>"ctr"}]
50
+ end
52
51
 
53
- it 'build a + post aggregation' do
54
- @query.postagg{(a + b).as ctr }
55
- JSON.parse(@query.to_json)['postAggregations'].should == [{"type"=>"arithmetic",
56
- "fn"=>"+",
57
- "fields"=>
58
- [{"type"=>"fieldAccess","name"=>"a", "fieldName"=>"a"},
59
- {"type"=>"fieldAccess", "name"=>"b", "fieldName"=>"b"}],
60
- "name"=>"ctr"}]
61
- end
52
+ it 'build a + post aggregation' do
53
+ @query.postagg{(a + b).as ctr }
54
+ JSON.parse(@query.to_json)['postAggregations'].should == [{"type"=>"arithmetic",
55
+ "fn"=>"+",
56
+ "fields"=>
57
+ [{"type"=>"fieldAccess","name"=>"a", "fieldName"=>"a"},
58
+ {"type"=>"fieldAccess", "name"=>"b", "fieldName"=>"b"}],
59
+ "name"=>"ctr"}]
60
+ end
61
+
62
+ it 'build a - post aggregation' do
63
+ @query.postagg{(a - b).as ctr }
64
+ JSON.parse(@query.to_json)['postAggregations'].should == [{"type"=>"arithmetic",
65
+ "fn"=>"-",
66
+ "fields"=>
67
+ [{"type"=>"fieldAccess", "name"=>"a", "fieldName"=>"a"},
68
+ {"type"=>"fieldAccess", "name"=>"b", "fieldName"=>"b"}],
69
+ "name"=>"ctr"}]
70
+ end
71
+
72
+ it 'build a * post aggregation' do
73
+ @query.postagg{(a * b).as ctr }
74
+ JSON.parse(@query.to_json)['postAggregations'].should == [{"type"=>"arithmetic",
75
+ "fn"=>"*",
76
+ "fields"=>
77
+ [{"type"=>"fieldAccess", "name"=>"a", "fieldName"=>"a"},
78
+ {"type"=>"fieldAccess", "name"=>"b", "fieldName"=>"b"}],
79
+ "name"=>"ctr"}]
80
+ end
62
81
 
63
- it 'build a - post aggregation' do
64
- @query.postagg{(a - b).as ctr }
65
- JSON.parse(@query.to_json)['postAggregations'].should == [{"type"=>"arithmetic",
66
- "fn"=>"-",
67
- "fields"=>
68
- [{"type"=>"fieldAccess", "name"=>"a", "fieldName"=>"a"},
69
- {"type"=>"fieldAccess", "name"=>"b", "fieldName"=>"b"}],
82
+ it 'build a / post aggregation' do
83
+ @query.postagg{(a / b).as ctr }
84
+ JSON.parse(@query.to_json)['postAggregations'].should == [{"type"=>"arithmetic",
85
+ "fn"=>"/",
86
+ "fields"=>
87
+ [{"type"=>"fieldAccess", "name"=>"a", "fieldName"=>"a"},
88
+ {"type"=>"fieldAccess", "name"=>"b", "fieldName"=>"b"}],
70
89
  "name"=>"ctr"}]
71
- end
90
+ end
72
91
 
73
- it 'build a * post aggregation' do
74
- @query.postagg{(a * b).as ctr }
75
- JSON.parse(@query.to_json)['postAggregations'].should == [{"type"=>"arithmetic",
76
- "fn"=>"*",
77
- "fields"=>
78
- [{"type"=>"fieldAccess", "name"=>"a", "fieldName"=>"a"},
79
- {"type"=>"fieldAccess", "name"=>"b", "fieldName"=>"b"}],
92
+ it 'build a complex post aggregation' do
93
+ @query.postagg{((a / b) * 1000).as ctr }
94
+ JSON.parse(@query.to_json)['postAggregations'].should == [{"type"=>"arithmetic",
95
+ "fn"=>"*",
96
+ "fields"=>
97
+ [{"type"=>"arithmetic", "fn"=>"/", "fields"=>
98
+ [{"type"=>"fieldAccess", "name"=>"a", "fieldName"=>"a"},
99
+ {"type"=>"fieldAccess", "name"=>"b", "fieldName"=>"b"}]},
100
+ {"type"=>"constant", "value"=>1000}],
80
101
  "name"=>"ctr"}]
81
- end
102
+ end
82
103
 
83
- it 'build a / post aggregation' do
84
- @query.postagg{(a / b).as ctr }
85
- JSON.parse(@query.to_json)['postAggregations'].should == [{"type"=>"arithmetic",
86
- "fn"=>"/",
87
- "fields"=>
88
- [{"type"=>"fieldAccess", "name"=>"a", "fieldName"=>"a"},
89
- {"type"=>"fieldAccess", "name"=>"b", "fieldName"=>"b"}],
90
- "name"=>"ctr"}]
91
- end
104
+ it 'adds fields required by the postagg operation to longsum' do
105
+ @query.postagg{ (a/b).as c }
106
+ JSON.parse(@query.to_json)['aggregations'].should == [
107
+ {"type"=>"longSum", "name"=>"a", "fieldName"=>"a"},
108
+ {"type"=>"longSum", "name"=>"b", "fieldName"=>"b"}
109
+ ]
110
+ end
92
111
 
93
- it 'build a complex post aggregation' do
94
- @query.postagg{((a / b) * 1000).as ctr }
95
- JSON.parse(@query.to_json)['postAggregations'].should == [{"type"=>"arithmetic",
96
- "fn"=>"*",
97
- "fields"=>
98
- [{"type"=>"arithmetic", "fn"=>"/", "fields"=>
112
+ it 'chains aggregations' do
113
+ @query.postagg{(a / b).as ctr }.postagg{(b / a).as rtc }
114
+
115
+ JSON.parse(@query.to_json)['postAggregations'].should == [{"type"=>"arithmetic",
116
+ "fn"=>"/",
117
+ "fields"=>
99
118
  [{"type"=>"fieldAccess", "name"=>"a", "fieldName"=>"a"},
100
- {"type"=>"fieldAccess", "name"=>"b", "fieldName"=>"b"}]},
101
- {"type"=>"constant", "value"=>1000}],
102
- "name"=>"ctr"}]
103
- end
104
-
105
- it 'adds fields required by the postagg operation to longsum' do
106
- @query.postagg{ (a/b).as c }
107
- JSON.parse(@query.to_json)['aggregations'].should == [{"type"=>"longSum", "name"=>"a", "fieldName"=>"a"},
108
- {"type"=>"longSum", "name"=>"b", "fieldName"=>"b"}]
109
- end
110
-
111
- it 'chains aggregations' do
112
- @query.postagg{(a / b).as ctr }.postagg{(b / a).as rtc }
113
-
114
- JSON.parse(@query.to_json)['postAggregations'].should == [{"type"=>"arithmetic",
115
- "fn"=>"/",
116
- "fields"=>
117
- [{"type"=>"fieldAccess", "name"=>"a", "fieldName"=>"a"},
118
- {"type"=>"fieldAccess", "name"=>"b", "fieldName"=>"b"}],
119
- "name"=>"ctr"},
120
- {"type"=>"arithmetic",
121
- "fn"=>"/",
122
- "fields"=>
123
- [{"type"=>"fieldAccess", "name"=>"b", "fieldName"=>"b"},
124
- {"type"=>"fieldAccess", "name"=>"a", "fieldName"=>"a"}],
125
- "name"=>"rtc"}
126
- ]
119
+ {"type"=>"fieldAccess", "name"=>"b", "fieldName"=>"b"}],
120
+ "name"=>"ctr"},
121
+ {"type"=>"arithmetic",
122
+ "fn"=>"/",
123
+ "fields"=>
124
+ [{"type"=>"fieldAccess", "name"=>"b", "fieldName"=>"b"},
125
+ {"type"=>"fieldAccess", "name"=>"a", "fieldName"=>"a"}],
126
+ "name"=>"rtc"}
127
+ ]
128
+ end
129
+
130
+ it 'builds a javascript post aggregation' do
131
+ @query.postagg { js('function(agg1, agg2) { return agg1 + agg2; }').as result }
132
+ JSON.parse(@query.to_json)['postAggregations'].should == [
133
+ {
134
+ 'type' => 'javascript',
135
+ 'name' => 'result',
136
+ 'fieldNames' => ['agg1', 'agg2'],
137
+ 'function' => 'function(agg1, agg2) { return agg1 + agg2; }'
138
+ }
139
+ ]
140
+ end
141
+
142
+ it 'raises an error when an invalid javascript function is used' do
143
+ expect {
144
+ @query.postagg { js('{ return a_with_b - a; }').as b }
145
+ }.to raise_error
146
+ end
127
147
  end
128
148
 
129
149
  it 'builds aggregations on long_sum' do
@@ -135,7 +155,6 @@ describe Druid::Query do
135
155
  ]
136
156
  end
137
157
 
138
-
139
158
  it 'appends long_sum properties from aggregations on calling long_sum again' do
140
159
  @query.long_sum(:a, :b, :c)
141
160
  @query.double_sum(:x,:y)
@@ -368,11 +387,25 @@ end
368
387
  ]}
369
388
  end
370
389
 
371
- it 'creates a greater than having clause' do
372
- @query.having{a > 100}
373
- JSON.parse(@query.to_json)['having'].should == {
374
- "type"=>"greaterThan", "aggregation"=>"a", "value"=>100
375
- }
390
+ describe '#having' do
391
+ it 'creates a greater than having clause' do
392
+ @query.having{a > 100}
393
+ JSON.parse(@query.to_json)['having'].should == {
394
+ "type"=>"greaterThan", "aggregation"=>"a", "value"=>100
395
+ }
396
+ end
397
+
398
+ it 'chains having clauses with and' do
399
+ @query.having{a > 100}.having{b > 200}.having{c > 300}
400
+ JSON.parse(@query.to_json)['having'].should == {
401
+ "type" => "and",
402
+ "havingSpecs" => [
403
+ { "type" => "greaterThan", "aggregation" => "a", "value" => 100 },
404
+ { "type" => "greaterThan", "aggregation" => "b", "value" => 200 },
405
+ { "type" => "greaterThan", "aggregation" => "c", "value" => 300 }
406
+ ]
407
+ }
408
+ end
376
409
  end
377
410
 
378
411
  it 'does not accept in with empty array' do
@@ -1,5 +1,3 @@
1
- require "spec_helper"
2
-
3
1
  module ZK
4
2
  def self.new(uri, opts = {})
5
3
  Mock.new uri, opts
metadata CHANGED
@@ -1,43 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-druid
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.8
4
+ version: 0.1.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - LiquidM, Inc.
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-09-09 00:00:00.000000000 Z
11
+ date: 2014-10-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: zk
15
- version_requirements: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - '>='
18
- - !ruby/object:Gem::Version
19
- version: '0'
20
15
  requirement: !ruby/object:Gem::Requirement
21
16
  requirements:
22
- - - '>='
17
+ - - ">="
23
18
  - !ruby/object:Gem::Version
24
19
  version: '0'
25
- prerelease: false
26
20
  type: :runtime
27
- - !ruby/object:Gem::Dependency
28
- name: rest-client
21
+ prerelease: false
29
22
  version_requirements: !ruby/object:Gem::Requirement
30
23
  requirements:
31
- - - '>='
24
+ - - ">="
32
25
  - !ruby/object:Gem::Version
33
26
  version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rest-client
34
29
  requirement: !ruby/object:Gem::Requirement
35
30
  requirements:
36
- - - '>='
31
+ - - ">="
37
32
  - !ruby/object:Gem::Version
38
33
  version: '0'
39
- prerelease: false
40
34
  type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
41
  description: Ruby client for metamx druid
42
42
  email:
43
43
  - opensource@liquidm.com
@@ -46,8 +46,9 @@ executables:
46
46
  extensions: []
47
47
  extra_rdoc_files: []
48
48
  files:
49
- - .gitignore
50
- - .travis.yml
49
+ - ".gitignore"
50
+ - ".rspec"
51
+ - ".travis.yml"
51
52
  - Gemfile
52
53
  - LICENSE
53
54
  - README.md
@@ -62,6 +63,7 @@ files:
62
63
  - lib/druid/post_aggregation.rb
63
64
  - lib/druid/query.rb
64
65
  - lib/druid/response_row.rb
66
+ - lib/druid/serializable.rb
65
67
  - lib/druid/zoo_handler.rb
66
68
  - ruby-druid.gemspec
67
69
  - spec/lib/client_spec.rb
@@ -72,24 +74,24 @@ homepage: https://github.com/liquidm/ruby-druid
72
74
  licenses:
73
75
  - MIT
74
76
  metadata: {}
75
- post_install_message:
77
+ post_install_message:
76
78
  rdoc_options: []
77
79
  require_paths:
78
80
  - lib
79
81
  required_ruby_version: !ruby/object:Gem::Requirement
80
82
  requirements:
81
- - - '>='
83
+ - - ">="
82
84
  - !ruby/object:Gem::Version
83
85
  version: '0'
84
86
  required_rubygems_version: !ruby/object:Gem::Requirement
85
87
  requirements:
86
- - - '>='
88
+ - - ">="
87
89
  - !ruby/object:Gem::Version
88
90
  version: '0'
89
91
  requirements: []
90
- rubyforge_project:
91
- rubygems_version: 2.2.2
92
- signing_key:
92
+ rubyforge_project:
93
+ rubygems_version: 2.1.11
94
+ signing_key:
93
95
  specification_version: 4
94
96
  summary: Ruby client for metamx druid
95
97
  test_files:
@@ -97,4 +99,4 @@ test_files:
97
99
  - spec/lib/query_spec.rb
98
100
  - spec/lib/zoo_handler_spec.rb
99
101
  - spec/spec_helper.rb
100
- has_rdoc:
102
+ has_rdoc: