eeml 0.0.25 → 0.0.29
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/.gitignore +1 -0
- data/CHANGELOG +8 -0
- data/ci/build_hudson.sh +28 -0
- data/lib/eeml/csv_parser_v1.rb +2 -3
- data/lib/eeml/csv_parser_v2.rb +4 -3
- data/lib/eeml/environment.rb +14 -2
- data/lib/eeml/environment_builder.rb +4 -2
- data/lib/eeml/helpers.rb +7 -0
- data/lib/eeml/json_environment_parser_v005.rb +2 -2
- data/lib/eeml/json_environment_parser_v006.rb +2 -2
- data/lib/eeml/json_environment_parser_v100.rb +2 -2
- data/lib/eeml/libxml_eeml_parser_v005.rb +1 -1
- data/lib/eeml/libxml_eeml_parser_v051.rb +1 -1
- data/lib/eeml.rb +2 -1
- data/test/test_csv_parser_v1.rb +14 -0
- data/test/test_csv_parser_v2.rb +18 -0
- data/test/test_environment.rb +88 -2
- metadata +9 -7
data/.gitignore
CHANGED
data/CHANGELOG
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
commit 750283de4b56996f05adae5bc02f992c56af4ef5
|
2
|
+
Author: Paul Bellamy <paul@connectedenvironments.com>
|
3
|
+
Date: Mon Jan 17 10:30:15 2011 +0000
|
4
|
+
|
5
|
+
Version 0.0.29
|
6
|
+
|
7
|
+
Fix for JSON parsing when receiving bad data
|
8
|
+
|
1
9
|
commit c4e0c43b3600256942fddd26d4e77d33549299cb
|
2
10
|
Author: Levent Ali <lebreeze@gmail.com>
|
3
11
|
Date: Fri Oct 8 11:18:09 2010 +0000
|
data/ci/build_hudson.sh
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
set -e
|
3
|
+
set -u
|
4
|
+
set -x
|
5
|
+
|
6
|
+
echo "Build script started $0 at `date`"
|
7
|
+
echo "dir is `pwd`"
|
8
|
+
outdir=build_artefacts
|
9
|
+
|
10
|
+
mkdir -p $outdir
|
11
|
+
|
12
|
+
custom_gem_dir=./gem_deps_manual
|
13
|
+
export GEM_PATH=$custom_gem_dir
|
14
|
+
|
15
|
+
set +e
|
16
|
+
~/sysadmin/show_platform/show_platform.sh > $outdir/platform.txt 2>&1
|
17
|
+
set -e
|
18
|
+
|
19
|
+
#this only really needs to be done initially, or on change to dependencies
|
20
|
+
gem install --install-dir $custom_gem_dir -y mocha jeweler libxml-ruby lightcsv yajl-ruby --no-rdoc --no-ri
|
21
|
+
|
22
|
+
set +e
|
23
|
+
rake test > $outdir/rspec.log
|
24
|
+
spec_rc=$?
|
25
|
+
set -e
|
26
|
+
|
27
|
+
exit $spec_rc
|
28
|
+
|
data/lib/eeml/csv_parser_v1.rb
CHANGED
@@ -2,8 +2,8 @@ module Eeml
|
|
2
2
|
class CsvParserV1
|
3
3
|
|
4
4
|
def self.make_environment_from_csv(csv_content)
|
5
|
-
csv = LightCsv.parse(csv_content)
|
6
|
-
environment = Environment.new
|
5
|
+
csv = LightCsv.parse(strip_content(csv_content))
|
6
|
+
environment = Environment.new(:csv_version => 'v1')
|
7
7
|
|
8
8
|
raise(CsvEncodingError, "Currently Pachube can only accept csv for your most recent set of values. You have submitted #{csv.size} rows of data.") unless csv.size == 1
|
9
9
|
|
@@ -12,6 +12,5 @@ module Eeml
|
|
12
12
|
end
|
13
13
|
environment
|
14
14
|
end
|
15
|
-
|
16
15
|
end
|
17
16
|
end
|
data/lib/eeml/csv_parser_v2.rb
CHANGED
@@ -4,8 +4,10 @@ module Eeml
|
|
4
4
|
class CsvParserV2
|
5
5
|
|
6
6
|
def self.make_environment_from_csv(csv_content)
|
7
|
-
csv = LightCsv.parse(csv_content)
|
8
|
-
environment = Environment.new
|
7
|
+
csv = LightCsv.parse(strip_content(csv_content))
|
8
|
+
environment = Environment.new(:csv_version => 'v2')
|
9
|
+
|
10
|
+
csv = strip_content(csv)
|
9
11
|
|
10
12
|
csv.each do |datastream|
|
11
13
|
raise(CsvEncodingError, "CSV is invalid. Double check you are properly encoding line breaks.") if datastream.length == 3 && datastream[1].include?('\n')
|
@@ -14,6 +16,5 @@ module Eeml
|
|
14
16
|
end
|
15
17
|
environment
|
16
18
|
end
|
17
|
-
|
18
19
|
end
|
19
20
|
end
|
data/lib/eeml/environment.rb
CHANGED
@@ -99,6 +99,7 @@ module Eeml
|
|
99
99
|
attr_accessor :identifier, :updated, :creator
|
100
100
|
attr_accessor :title, :description, :feed_url, :website, :email, :icon, :status
|
101
101
|
attr_accessor :location
|
102
|
+
attr_accessor :csv_version
|
102
103
|
attr_accessor :datastreams
|
103
104
|
attr_accessor :tags
|
104
105
|
attr_writer :private
|
@@ -116,6 +117,7 @@ module Eeml
|
|
116
117
|
@email = options[:email]
|
117
118
|
@icon = options[:icon]
|
118
119
|
@private = options[:private]
|
120
|
+
@csv_version = options[:csv_version]
|
119
121
|
@tags = []
|
120
122
|
end
|
121
123
|
|
@@ -144,8 +146,8 @@ module Eeml
|
|
144
146
|
end
|
145
147
|
|
146
148
|
# Create a new Environment object from a CSV string
|
147
|
-
def self.new_from_csv(csv_str, version)
|
148
|
-
EnvironmentBuilder.build_from_csv(csv_str, version)
|
149
|
+
def self.new_from_csv(csv_str, version = nil)
|
150
|
+
EnvironmentBuilder.build_from_csv(csv_str, detect_csv_version(version, csv_str))
|
149
151
|
end
|
150
152
|
|
151
153
|
def update_datastreams_from_csv_values!(csv_values)
|
@@ -178,6 +180,16 @@ module Eeml
|
|
178
180
|
return false
|
179
181
|
end
|
180
182
|
end
|
183
|
+
|
184
|
+
private
|
185
|
+
|
186
|
+
def self.detect_csv_version(version, csv)
|
187
|
+
return version if version
|
188
|
+
parsed_csv = LightCsv.parse(strip_content(csv))
|
189
|
+
return :v2 if parsed_csv.size >= 2
|
190
|
+
return :v1 if parsed_csv.size == 1 && parsed_csv.first.length != 2
|
191
|
+
raise(CsvEncodingError, "CSV version could not be detected")
|
192
|
+
end
|
181
193
|
|
182
194
|
end
|
183
195
|
|
@@ -35,13 +35,15 @@ module Eeml
|
|
35
35
|
if json["version"].to_i == Constants::EEML['0.5.0'][:version].to_i
|
36
36
|
parser = JsonEnvironmentParserV005.new
|
37
37
|
elsif json["version"] == Constants::JSON_API['1.0.0'][:version]
|
38
|
-
|
38
|
+
parser = JsonEnvironmentParserV100.new
|
39
39
|
elsif json["version"].to_f == Constants::JSON_API['0.6-alpha'][:version].to_f
|
40
40
|
parser = JsonEnvironmentParserV006.new
|
41
41
|
else
|
42
|
-
raise
|
42
|
+
raise # raise something so we jump to the rescue block below
|
43
43
|
end
|
44
44
|
return parser.make_environment_from_hash(json)
|
45
|
+
rescue
|
46
|
+
raise JSON::ParserError, "Invalid version specification. Permitted versions are #{Constants::EEML['0.5.0'][:version]}, #{Constants::JSON_API["0.6-alpha"][:version]} and #{Constants::JSON_API["1.0.0"][:version]}"
|
45
47
|
end
|
46
48
|
|
47
49
|
def self.build_from_csv(csv_str, version = :v1)
|
data/lib/eeml/helpers.rb
ADDED
@@ -24,7 +24,7 @@ module Eeml
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def make_environment_from_json(json_str)
|
27
|
-
env_hash = JSON.parse(json_str)
|
27
|
+
env_hash = JSON.parse(strip_content(json_str))
|
28
28
|
return make_environment_from_hash(env_hash)
|
29
29
|
end
|
30
30
|
|
@@ -44,7 +44,7 @@ module Eeml
|
|
44
44
|
|
45
45
|
def buildDatastreams(env_hash)
|
46
46
|
datastreams_hash = env_hash["datastreams"]
|
47
|
-
return if datastreams_hash.nil?
|
47
|
+
return [] if datastreams_hash.nil?
|
48
48
|
datastreams = []
|
49
49
|
datastreams_hash.each do |datastream_hash|
|
50
50
|
datastream = DataStream.new
|
@@ -24,7 +24,7 @@ module Eeml
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def make_environment_from_json(json_str)
|
27
|
-
env_hash = JSON.parse(json_str)
|
27
|
+
env_hash = JSON.parse(strip_content(json_str))
|
28
28
|
return make_environment_from_hash(env_hash)
|
29
29
|
end
|
30
30
|
|
@@ -44,7 +44,7 @@ module Eeml
|
|
44
44
|
|
45
45
|
def buildDatastreams(env_hash)
|
46
46
|
datastreams_hash = env_hash["datastreams"]
|
47
|
-
return if datastreams_hash.nil?
|
47
|
+
return [] if datastreams_hash.nil?
|
48
48
|
datastreams = []
|
49
49
|
datastreams_hash.each do |datastream_hash|
|
50
50
|
datastream = DataStream.new
|
@@ -26,7 +26,7 @@ module Eeml
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def make_environment_from_json(json_str)
|
29
|
-
env_hash = JSON.parse(json_str)
|
29
|
+
env_hash = JSON.parse(strip_content(json_str))
|
30
30
|
return make_environment_from_hash(env_hash)
|
31
31
|
end
|
32
32
|
|
@@ -46,7 +46,7 @@ module Eeml
|
|
46
46
|
|
47
47
|
def buildDatastreams(env_hash)
|
48
48
|
datastreams_hash = env_hash["datastreams"]
|
49
|
-
return if datastreams_hash.nil?
|
49
|
+
return [] if datastreams_hash.nil?
|
50
50
|
datastreams = []
|
51
51
|
datastreams_hash.each do |datastream_hash|
|
52
52
|
datastream = DataStream.new
|
@@ -37,7 +37,7 @@ module Eeml
|
|
37
37
|
#TODO: are these configurations per-thread? If they're global (e.g. class variables) then we shouldn't be setting them here.
|
38
38
|
XML.default_line_numbers=true
|
39
39
|
|
40
|
-
parser = XML::Parser.string(xml_str)
|
40
|
+
parser = XML::Parser.string(strip_content(xml_str))
|
41
41
|
begin
|
42
42
|
doc = parser.parse
|
43
43
|
rescue XML::Error => e
|
@@ -37,7 +37,7 @@ module Eeml
|
|
37
37
|
#TODO: are these configurations per-thread? If they're global (e.g. class variables) then we shouldn't be setting them here.
|
38
38
|
XML.default_line_numbers=true
|
39
39
|
|
40
|
-
parser = XML::Parser.string(xml_str)
|
40
|
+
parser = XML::Parser.string(strip_content(xml_str))
|
41
41
|
begin
|
42
42
|
doc = parser.parse
|
43
43
|
rescue XML::Error => e
|
data/lib/eeml.rb
CHANGED
@@ -8,6 +8,7 @@ require 'yajl/json_gem'
|
|
8
8
|
require 'lightcsv'
|
9
9
|
require 'eeml/constants'
|
10
10
|
require 'eeml/exceptions'
|
11
|
+
require 'eeml/helpers'
|
11
12
|
require 'eeml/environment'
|
12
13
|
require 'eeml/environment_builder'
|
13
14
|
require 'time'
|
@@ -15,7 +16,7 @@ require 'time'
|
|
15
16
|
module Eeml
|
16
17
|
|
17
18
|
# library version number
|
18
|
-
VERSION = '0.0.
|
19
|
+
VERSION = '0.0.29'
|
19
20
|
|
20
21
|
# TODO: put in some configuration file, not here
|
21
22
|
LOCAL_EEML_SCHEMA_LOCATION = 'schemas/eeml/005.xsd'
|
data/test/test_csv_parser_v1.rb
CHANGED
@@ -10,6 +10,20 @@ class TestCsvParserV1 < Test::Unit::TestCase
|
|
10
10
|
assert_equal "Currently Pachube can only accept csv for your most recent set of values. You have submitted 2 rows of data.", exception.message
|
11
11
|
end
|
12
12
|
|
13
|
+
test "should strip whitespace before parsing" do
|
14
|
+
csv = <<-EOF
|
15
|
+
20,10n5,fsa,432,6
|
16
|
+
|
17
|
+
|
18
|
+
EOF
|
19
|
+
environment = CsvParserV1.make_environment_from_csv(csv)
|
20
|
+
assert_equal 5, environment.datastreams.length
|
21
|
+
csv.split(',').each_with_index do |value, index|
|
22
|
+
assert_nil environment.datastreams[index].identifier
|
23
|
+
assert_equal value.strip, environment.datastreams[index].value
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
13
27
|
test "should parse and return Environment object with datastreams" do
|
14
28
|
csv = "20,10n5,fsa,432,6"
|
15
29
|
environment = CsvParserV1.make_environment_from_csv(csv)
|
data/test/test_csv_parser_v2.rb
CHANGED
@@ -18,6 +18,24 @@ class TestCsvParserV2 < Test::Unit::TestCase
|
|
18
18
|
assert_equal "CSV is invalid. Incorrect number of fields.", exception.message
|
19
19
|
end
|
20
20
|
|
21
|
+
test "should strip whitespace before parsing" do
|
22
|
+
csv = <<-EOF
|
23
|
+
|
24
|
+
20,10
|
25
|
+
|
26
|
+
5,6
|
27
|
+
|
28
|
+
|
29
|
+
EOF
|
30
|
+
environment = CsvParserV2.make_environment_from_csv(csv)
|
31
|
+
assert_equal 2, environment.datastreams.length
|
32
|
+
assert_equal "20", environment.datastreams.first.identifier
|
33
|
+
assert_equal "10", environment.datastreams.first.value
|
34
|
+
|
35
|
+
assert_equal "5", environment.datastreams.last.identifier
|
36
|
+
assert_equal "6", environment.datastreams.last.value
|
37
|
+
end
|
38
|
+
|
21
39
|
test "should parse and return Environment object with datastreams" do
|
22
40
|
csv = "20,10\n5,6"
|
23
41
|
environment = CsvParserV2.make_environment_from_csv(csv)
|
data/test/test_environment.rb
CHANGED
@@ -95,8 +95,6 @@ class TestEnvironment < Test::Unit::TestCase
|
|
95
95
|
#TODO: arguably, fetcher should also have rejected huge string
|
96
96
|
end
|
97
97
|
|
98
|
-
# should this actually pass? Location is essentially a datastream in it's own right, so a feed
|
99
|
-
# that only specified location should probably be alright.
|
100
98
|
test "passes if no datastreams" do
|
101
99
|
original_xml = File.read('test/data/doc_1.xml')
|
102
100
|
test_xml = remove_nodes_called('data', original_xml)
|
@@ -104,6 +102,7 @@ class TestEnvironment < Test::Unit::TestCase
|
|
104
102
|
environment = Environment.new_from_eeml(test_xml)
|
105
103
|
|
106
104
|
assert_equal('title here', environment.title)
|
105
|
+
assert_equal([], environment.datastreams)
|
107
106
|
end
|
108
107
|
|
109
108
|
test "fail if any datastream has no value" do
|
@@ -380,6 +379,27 @@ class TestEnvironment < Test::Unit::TestCase
|
|
380
379
|
end
|
381
380
|
end
|
382
381
|
|
382
|
+
test "passes if no datastreams from json" do
|
383
|
+
original_hash = JSON.parse(File.read('test/data/doc_1.json'))
|
384
|
+
original_hash.delete('datastreams')
|
385
|
+
test_json = original_hash.to_json
|
386
|
+
|
387
|
+
environment = Environment.new_from_json(test_json)
|
388
|
+
|
389
|
+
assert_equal('title here', environment.title)
|
390
|
+
assert_equal([], environment.datastreams)
|
391
|
+
end
|
392
|
+
|
393
|
+
test "parses a json with version missing and raises appropriate error" do
|
394
|
+
#original_hash = JSON.parse(File.read('test/data/doc_1.json'))
|
395
|
+
#original_hash.delete('version')
|
396
|
+
test_json = '[0,0,0,"9.44","83.68","1013.64"]'
|
397
|
+
|
398
|
+
assert_raises(JSON::ParserError) do
|
399
|
+
environment = Environment.new_from_json(test_json)
|
400
|
+
end
|
401
|
+
end
|
402
|
+
|
383
403
|
test "parses a v1.0.0 input file ok" do
|
384
404
|
env = create_env_from_json_v100_file_one
|
385
405
|
assert_not_nil env
|
@@ -444,6 +464,17 @@ class TestEnvironment < Test::Unit::TestCase
|
|
444
464
|
end
|
445
465
|
end
|
446
466
|
|
467
|
+
test "passes in v1.0.0 if no datastreams from json" do
|
468
|
+
original_hash = JSON.parse(File.read('test/data/doc_1_v1-0-0.json'))
|
469
|
+
original_hash.delete('datastreams')
|
470
|
+
test_json = original_hash.to_json
|
471
|
+
|
472
|
+
environment = Environment.new_from_json(test_json)
|
473
|
+
|
474
|
+
assert_equal('title here', environment.title)
|
475
|
+
assert_equal([], environment.datastreams)
|
476
|
+
end
|
477
|
+
|
447
478
|
test "parses environment level tags from v1.0.0 json" do
|
448
479
|
env = create_env_from_json_file('test/data/environment_tags.json')
|
449
480
|
assert_equal 3, env.datastreams.size
|
@@ -515,6 +546,17 @@ class TestEnvironment < Test::Unit::TestCase
|
|
515
546
|
end
|
516
547
|
end
|
517
548
|
|
549
|
+
test "passes in v6 if no datastreams from json" do
|
550
|
+
original_hash = JSON.parse(File.read('test/data/doc_1_v6.json'))
|
551
|
+
original_hash.delete('datastreams')
|
552
|
+
test_json = original_hash.to_json
|
553
|
+
|
554
|
+
environment = Environment.new_from_json(test_json)
|
555
|
+
|
556
|
+
assert_equal('title here', environment.title)
|
557
|
+
assert_equal([], environment.datastreams)
|
558
|
+
end
|
559
|
+
|
518
560
|
test "captures `private` attribute when parsing old json" do
|
519
561
|
env = create_env_from_json_file("test/data/doc_1_private.json")
|
520
562
|
assert_not_nil env
|
@@ -593,6 +635,50 @@ class TestEnvironment < Test::Unit::TestCase
|
|
593
635
|
assert_equal values, env.values_quick
|
594
636
|
end
|
595
637
|
|
638
|
+
test "creating via csv should accept version v1" do
|
639
|
+
environment = Environment.new_from_csv("1,2,3,4", :v1)
|
640
|
+
assert_equal 4, environment.datastreams.length
|
641
|
+
end
|
642
|
+
|
643
|
+
test "creating via csv should accept version v2" do
|
644
|
+
csv = <<-CSV
|
645
|
+
1,2
|
646
|
+
3,4
|
647
|
+
CSV
|
648
|
+
environment = Environment.new_from_csv(csv, :v2)
|
649
|
+
assert_equal 2, environment.datastreams.length
|
650
|
+
assert_equal ['1', '3'], environment.datastreams.map(&:identifier).sort
|
651
|
+
end
|
652
|
+
|
653
|
+
test "creating via csv should attempt to detect version" do
|
654
|
+
csv = <<-CSV
|
655
|
+
1,2
|
656
|
+
3,4
|
657
|
+
CSV
|
658
|
+
environment = Environment.new_from_csv(csv)
|
659
|
+
assert_equal 2, environment.datastreams.length
|
660
|
+
assert_equal ['1', '3'], environment.datastreams.map(&:identifier).sort
|
661
|
+
end
|
662
|
+
|
663
|
+
test "creating via csv should assume v1 if one row and one entry" do
|
664
|
+
environment = Environment.new_from_csv("nought")
|
665
|
+
assert_equal 1, environment.datastreams.length
|
666
|
+
assert_equal "nought", environment.datastreams.first.values.first.value
|
667
|
+
end
|
668
|
+
|
669
|
+
test "creating via csv should assume v1 if one row and 3+ entry" do
|
670
|
+
environment = Environment.new_from_csv("nought,two,free")
|
671
|
+
assert_equal 3, environment.datastreams.length
|
672
|
+
assert_equal ["free", "nought", "two"], environment.datastreams.collect(&:values).flatten.map(&:value).sort
|
673
|
+
end
|
674
|
+
|
675
|
+
test "creating via csv should raise an exception if it cannot detect the version" do
|
676
|
+
exception = assert_raises CsvEncodingError do
|
677
|
+
Environment.new_from_csv("1,2")
|
678
|
+
end
|
679
|
+
assert_equal "CSV version could not be detected", exception.message
|
680
|
+
end
|
681
|
+
|
596
682
|
# --- convenience stuff - don't put tests under here ------------------------------
|
597
683
|
|
598
684
|
def create_env_from_xml_string(string)
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: eeml
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 37
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 29
|
10
|
+
version: 0.0.29
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Neill Bogie
|
@@ -18,7 +18,7 @@ autorequire:
|
|
18
18
|
bindir: bin
|
19
19
|
cert_chain: []
|
20
20
|
|
21
|
-
date:
|
21
|
+
date: 2011-01-17 00:00:00 +00:00
|
22
22
|
default_executable:
|
23
23
|
dependencies:
|
24
24
|
- !ruby/object:Gem::Dependency
|
@@ -85,6 +85,7 @@ files:
|
|
85
85
|
- Manifest
|
86
86
|
- README
|
87
87
|
- Rakefile
|
88
|
+
- ci/build_hudson.sh
|
88
89
|
- example.rb
|
89
90
|
- lib/blank.rb
|
90
91
|
- lib/eeml.rb
|
@@ -94,6 +95,7 @@ files:
|
|
94
95
|
- lib/eeml/environment.rb
|
95
96
|
- lib/eeml/environment_builder.rb
|
96
97
|
- lib/eeml/exceptions.rb
|
98
|
+
- lib/eeml/helpers.rb
|
97
99
|
- lib/eeml/json_environment_parser_v005.rb
|
98
100
|
- lib/eeml/json_environment_parser_v006.rb
|
99
101
|
- lib/eeml/json_environment_parser_v100.rb
|
@@ -165,10 +167,10 @@ signing_key:
|
|
165
167
|
specification_version: 3
|
166
168
|
summary: Simple little library for programmatically manipulating EEML documents.
|
167
169
|
test_files:
|
168
|
-
- test/
|
170
|
+
- test/libxml_test_helper.rb
|
169
171
|
- test/test_libxml_test_helper.rb
|
172
|
+
- test/test_libxml_eeml_parser_v005.rb
|
170
173
|
- test/test_csv_parser_v2.rb
|
174
|
+
- test/test_helper.rb
|
171
175
|
- test/test_csv_parser_v1.rb
|
172
176
|
- test/test_environment.rb
|
173
|
-
- test/libxml_test_helper.rb
|
174
|
-
- test/test_helper.rb
|