csvision 0.1.0 → 0.2.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/README.md +145 -7
- data/csvision.gemspec +0 -1
- data/lib/csvision.rb +6 -2
- data/lib/csvision/csv_helper.rb +23 -18
- data/lib/csvision/version.rb +1 -1
- data/test/app/models/sample_stack.rb +21 -0
- data/test/app/models/user.rb +18 -0
- data/test/db/schema.rb +5 -0
- data/test/outside_of_rails_test.rb +44 -0
- data/test/test_helper.rb +8 -3
- data/test/user_test.rb +47 -0
- metadata +16 -21
data/README.md
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# CSVision
|
2
2
|
|
3
|
+
[](http://travis-ci.org/cloverinteractive/csvision)
|
4
|
+
|
3
5
|
Convert a Hash into a CSV the easy way.
|
4
6
|
|
5
7
|
## Installation
|
@@ -18,20 +20,20 @@ Or install it yourself as:
|
|
18
20
|
|
19
21
|
## Usage
|
20
22
|
|
21
|
-
CSVision has no prerequisites other than ruby itself, which is pretty cool just include the `
|
23
|
+
CSVision has no prerequisites other than ruby itself, which is pretty cool just include the `csvision` gem in your app and you'll be good to go.
|
22
24
|
|
23
25
|
### Hash
|
24
26
|
|
25
|
-
CSVision adds to `Hash` the `to_csv` method, anything that inherits from `Hash` will inherit this method as well, you do not need to open `Hash` and include `CSVision` in it, just
|
27
|
+
CSVision adds to `Hash` the `to_csv` method, anything that inherits from `Hash` will inherit this method as well, you do not need to open `Hash` and include `CSVision` in it, just require the library in your code.
|
26
28
|
|
27
29
|
```ruby
|
28
|
-
|
30
|
+
require 'csvision'
|
29
31
|
sample = { :name => 'foo', :last_name => 'bar', :age => 10 }
|
30
32
|
sample.to_csv #=> "\"last_name\",\"name\",\"age\"\n\"bar\",\"foo\",\"10\""
|
31
33
|
```
|
32
34
|
### Rails
|
33
35
|
|
34
|
-
CSVision adds the
|
36
|
+
CSVision adds the following methods to Rails:
|
35
37
|
|
36
38
|
1. `to_csv` at the model instance
|
37
39
|
2. `to_csv` at the model class
|
@@ -53,11 +55,147 @@ CSVision lets you customize the way your CSV is formed, you can use any of the f
|
|
53
55
|
3. `:delimeter` this set the field delimeter and it defaults to `"`
|
54
56
|
4. `:separator` this set the field separator and it defults to `,`
|
55
57
|
|
58
|
+
That's good and all but, you never want to just convert a single object to csv but collections instead, so imagine this model instead:
|
59
|
+
|
60
|
+
```ruby
|
61
|
+
class User < ActiveRecord::Base
|
62
|
+
add_csvision :csv_headers => %w/street_cred nickname incognito/, :body => lambda { |u| [ u.street_cred, u.nickname, u.incognito ] }
|
63
|
+
|
64
|
+
scope :flunky, where( 'points <= 5' )
|
65
|
+
|
66
|
+
def incognito
|
67
|
+
nickname.reverse
|
68
|
+
end
|
69
|
+
|
70
|
+
def street_cred
|
71
|
+
points * 100 + ( nickname_cred )
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
def nickname_cred
|
76
|
+
nickname.unpack( 'U' * nickname.length ).sum # good nickname equals more street cred
|
77
|
+
end
|
78
|
+
end
|
79
|
+
```
|
80
|
+
|
81
|
+
You can use the `:headers` option to set your header names, and the `:body` option to specify the methods or properties from the option you want
|
82
|
+
called in your csv, this gives you flexibility to choose how your csv is formed and from what it is formed, so this is an example of how this works.
|
83
|
+
|
84
|
+
```ruby
|
85
|
+
5.times { |i| User.create( :nickname => "user#{ i * 3 }", :points => i * 5 ) }
|
86
|
+
puts User.to_csv
|
87
|
+
```
|
88
|
+
|
89
|
+
this will print:
|
90
|
+
|
91
|
+
```
|
92
|
+
"street_cred","nickname","incognito"
|
93
|
+
"495","user0","0resu"
|
94
|
+
"998","user3","3resu"
|
95
|
+
"1501","user6","6resu"
|
96
|
+
"2004","user9","9resu"
|
97
|
+
"2546","user12","21resu"
|
98
|
+
```
|
99
|
+
|
100
|
+
You can chain active record calls and even scopes in to your mix, so consider:
|
101
|
+
|
102
|
+
```ruby
|
103
|
+
5.times { |i| User.create( :nickname => "user#{ i * 3 }", :points => i *5 ) }
|
104
|
+
puts User.flunky.to_csv
|
105
|
+
```
|
106
|
+
will print:
|
107
|
+
|
108
|
+
```
|
109
|
+
"street_cred","nickname","incognito"
|
110
|
+
"495","user0","0resu"
|
111
|
+
"998","user3","3resu"
|
112
|
+
"1501","user6","6resu"
|
113
|
+
```
|
114
|
+
|
115
|
+
Lastly, with the exception of `:except` and `:only` which will be ignore because you're setting the body manually all other option work:
|
116
|
+
|
117
|
+
```ruby
|
118
|
+
5.times { |i| User.create( :nickname => "user#{ i * 3 }", :points => i *5 ) }
|
119
|
+
puts User.to_csv( :headers => false )
|
120
|
+
```
|
121
|
+
|
122
|
+
Will print:
|
123
|
+
|
124
|
+
```
|
125
|
+
"495","user0","0resu"
|
126
|
+
"998","user3","3resu"
|
127
|
+
"1501","user6","6resu"
|
128
|
+
"2004","user9","9resu"
|
129
|
+
"2546","user12","21resu"
|
130
|
+
```
|
131
|
+
|
132
|
+
### Outside of Rails
|
133
|
+
|
134
|
+
Anything that inherits from `Hash` will `respond_to? :to_csv` however if you want to use this in any other regular class make sure you do the following:
|
135
|
+
|
136
|
+
1. Create a `Hash` attribute named `attributes`.
|
137
|
+
2. You'll need to have a class `count` and `find_each` methods if you want support for setting the `body`.
|
138
|
+
3. `include CSVision` in your class.
|
139
|
+
|
140
|
+
```ruby
|
141
|
+
class SampleStack
|
142
|
+
include CSVision
|
143
|
+
attr_accessor :attributes, :count
|
144
|
+
|
145
|
+
add_csvision :csv_headers => %w/price name/, :body => lambda { |s| [ s[:name], s[:price] ] }
|
146
|
+
|
147
|
+
def initialize( attributes={}, inventory = [] )
|
148
|
+
@attributes = attributes
|
149
|
+
@@inventory = inventory
|
150
|
+
end
|
151
|
+
|
152
|
+
def self.count
|
153
|
+
@@inventory.size
|
154
|
+
end
|
155
|
+
|
156
|
+
def self.find_each( opts={} )
|
157
|
+
@@inventory.each do |item|
|
158
|
+
yield item
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
```
|
163
|
+
|
164
|
+
After wards imagine the following:
|
165
|
+
|
166
|
+
```ruby
|
167
|
+
sample_stack = SampleStack.new( :foo => 'foo', :bar => 'bar' )
|
168
|
+
puts sample_stack.to_csv
|
169
|
+
```
|
170
|
+
|
171
|
+
Will print:
|
172
|
+
|
173
|
+
```
|
174
|
+
"foo","bar"
|
175
|
+
"foo","bar"
|
176
|
+
```
|
177
|
+
|
178
|
+
But more importantly `to_csv` at the class level will:
|
179
|
+
|
180
|
+
```ruby
|
181
|
+
inventory = [ { :name => 'beer', :price => 9 }, { :name => 'milk', :price => 5 }, { :name => 'tuna', :price => 3 } ]
|
182
|
+
sample_stack = SampleStack.new({ :name => 'groceries'}, inventory)
|
183
|
+
puts SampleStack.to_csv
|
184
|
+
```
|
185
|
+
|
186
|
+
Prints:
|
187
|
+
|
188
|
+
```
|
189
|
+
"price","name"
|
190
|
+
"beer","9"
|
191
|
+
"milk","5"
|
192
|
+
"tuna","3"
|
193
|
+
```
|
194
|
+
|
56
195
|
## TODO:
|
57
196
|
|
58
|
-
1.
|
59
|
-
2.
|
60
|
-
3. Rails 3.x responder.
|
197
|
+
1. Add support for other ORM's
|
198
|
+
2. Rails 3.x responder.
|
61
199
|
|
62
200
|
|
63
201
|
## Contributing
|
data/csvision.gemspec
CHANGED
@@ -19,7 +19,6 @@ Gem::Specification.new do |gem|
|
|
19
19
|
gem.add_development_dependency 'activerecord'
|
20
20
|
gem.add_development_dependency 'activesupport'
|
21
21
|
gem.add_development_dependency 'sqlite3'
|
22
|
-
gem.add_development_dependency 'mocha'
|
23
22
|
gem.add_development_dependency 'rake'
|
24
23
|
gem.add_development_dependency 'turn', '0.8.2'
|
25
24
|
end
|
data/lib/csvision.rb
CHANGED
@@ -2,6 +2,10 @@ require "csvision/version"
|
|
2
2
|
require "csvision/csv_helper"
|
3
3
|
|
4
4
|
module CSVision
|
5
|
-
|
6
|
-
|
5
|
+
def self.included(base)
|
6
|
+
base.extend CSVHelper
|
7
|
+
end
|
7
8
|
end
|
9
|
+
|
10
|
+
ActiveRecord::Base.send( :include, CSVision ) if defined? ActiveRecord::Base
|
11
|
+
Hash.send( :include, CSVision::CSVHelper::InstanceMethods )
|
data/lib/csvision/csv_helper.rb
CHANGED
@@ -1,38 +1,43 @@
|
|
1
1
|
module CSVision
|
2
|
-
def self.included(base)
|
3
|
-
base.extend CSVHelper
|
4
|
-
end
|
5
|
-
|
6
2
|
module CSVHelper
|
7
3
|
def add_csvision(options={})
|
8
4
|
return if included_modules.include? InstanceMethods
|
9
|
-
cattr_accessor :csv_except, :csv_only, :csv_delimeter, :csv_separator, :csv_headers
|
5
|
+
cattr_accessor :csv_except, :csv_only, :csv_delimeter, :csv_separator, :csv_headers, :body
|
10
6
|
|
11
7
|
self.csv_only = options[:only]
|
12
8
|
self.csv_except = options[:except]
|
13
9
|
self.csv_delimeter = options[:delimeter] || '"'
|
14
10
|
self.csv_separator = options[:separator] || ','
|
11
|
+
self.csv_headers = options[:csv_headers]
|
12
|
+
self.body = options[:body]
|
15
13
|
|
16
14
|
include InstanceMethods
|
17
15
|
extend ClassMethods
|
18
16
|
end
|
19
17
|
|
20
18
|
module ClassMethods
|
21
|
-
def to_csv(options={})
|
22
|
-
options[:
|
23
|
-
|
19
|
+
def to_csv(options={ :headers => true, :batch_size => 100 })
|
20
|
+
options[:delimeter] ||= csv_delimeter
|
21
|
+
options[:separator] ||= csv_separator
|
22
|
+
options[:batch_size] ||= 100
|
24
23
|
|
25
|
-
self.
|
26
|
-
headers
|
27
|
-
|
24
|
+
unless self.count < 1
|
25
|
+
headers, csv_array = nil, []
|
26
|
+
self.find_each :batch_size => options[:batch_size] do |object|
|
27
|
+
unless self.body
|
28
|
+
headers ||= object.csvize( object.attributes.only( *csv_only ).keys, options ) if csv_only && !csv_only.empty?
|
29
|
+
headers ||= object.csvize( object.attributes.except( *csv_except ).keys, options ) if csv_except && !csv_except.empty?
|
28
30
|
|
29
|
-
|
30
|
-
|
31
|
-
|
31
|
+
csv_array << object.to_csv( options.merge(:headers => false) )
|
32
|
+
else
|
33
|
+
values = self.body.call object
|
34
|
+
headers ||= object.csvize( self.csv_headers, options ) if self.csv_headers
|
35
|
+
csv_array << object.csvize( values, options )
|
36
|
+
end
|
37
|
+
end
|
32
38
|
|
33
|
-
|
34
|
-
headers + "\n" + content
|
35
|
-
else
|
39
|
+
content = csv_array.join("\n")
|
40
|
+
return headers + "\n" + content if options[:headers]
|
36
41
|
content
|
37
42
|
end
|
38
43
|
end
|
@@ -61,7 +66,7 @@ module CSVision
|
|
61
66
|
@csv += csvize(values, options)
|
62
67
|
end
|
63
68
|
|
64
|
-
def csvize(values, options)
|
69
|
+
def csvize(values, options={})
|
65
70
|
delimeter = options[:delimeter] || csv_delimeter
|
66
71
|
separator = options[:separator] || csv_separator
|
67
72
|
|
data/lib/csvision/version.rb
CHANGED
@@ -0,0 +1,21 @@
|
|
1
|
+
class SampleStack
|
2
|
+
include CSVision
|
3
|
+
attr_accessor :attributes
|
4
|
+
|
5
|
+
add_csvision :csv_headers => %w/price name/, :body => lambda { |s| [ s[:name], s[:price] ] }
|
6
|
+
|
7
|
+
def initialize( attributes={}, inventory = [] )
|
8
|
+
@attributes = attributes
|
9
|
+
@@inventory = inventory
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.count
|
13
|
+
@@inventory.size
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.find_each( opts={} )
|
17
|
+
@@inventory.each do |item|
|
18
|
+
yield item
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class User < ActiveRecord::Base
|
2
|
+
add_csvision :csv_headers => %w/street_cred nickname incognito/, :body => lambda { |u| [ u.street_cred, u.nickname, u.incognito ] }
|
3
|
+
|
4
|
+
scope :flunky, where( 'points <= 5' )
|
5
|
+
|
6
|
+
def incognito
|
7
|
+
nickname.reverse
|
8
|
+
end
|
9
|
+
|
10
|
+
def street_cred
|
11
|
+
points * 100 + ( nickname_cred )
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
def nickname_cred
|
16
|
+
nickname.unpack( 'U' * nickname.length ).sum # good nickname equals more street cred
|
17
|
+
end
|
18
|
+
end
|
data/test/db/schema.rb
CHANGED
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class OutsideOfRails < ActiveSupport::TestCase
|
4
|
+
EXPECTED_CSV = <<-CSV
|
5
|
+
"price","name"
|
6
|
+
"beer","9"
|
7
|
+
"milk","5"
|
8
|
+
"tuna","3"
|
9
|
+
CSV
|
10
|
+
|
11
|
+
EXPECTED_CSV_WITHOUT_HEADERS = <<-CSV
|
12
|
+
"beer","9"
|
13
|
+
"milk","5"
|
14
|
+
"tuna","3"
|
15
|
+
CSV
|
16
|
+
|
17
|
+
def setup
|
18
|
+
assert @inventory = [
|
19
|
+
{ :name => 'beer', :price => 9 },
|
20
|
+
{ :name => 'milk', :price => 5 },
|
21
|
+
{ :name => 'tuna', :price => 3 } ]
|
22
|
+
end
|
23
|
+
|
24
|
+
test "can use csvsion on POROS" do
|
25
|
+
assert sample_stack = SampleStack.new( :foo => 'foo', :bar => 'bar' )
|
26
|
+
assert sample_stack.respond_to?( :to_csv )
|
27
|
+
assert csv = sample_stack.to_csv( :headers => false )
|
28
|
+
assert_match /foo/, csv
|
29
|
+
assert_match /bar/, csv
|
30
|
+
end
|
31
|
+
|
32
|
+
test "can make use of class methods" do
|
33
|
+
assert sample_stack = SampleStack.new({ :name => 'groceries'}, @inventory)
|
34
|
+
assert SampleStack.respond_to?( :to_csv )
|
35
|
+
assert csv = SampleStack.to_csv
|
36
|
+
assert_equal EXPECTED_CSV.chomp, csv
|
37
|
+
end
|
38
|
+
|
39
|
+
test "can use option filters on POROS" do
|
40
|
+
assert sample_stack = SampleStack.new({ :name => 'groceries'}, @inventory)
|
41
|
+
assert csv = SampleStack.to_csv( :headers => false )
|
42
|
+
assert_equal EXPECTED_CSV_WITHOUT_HEADERS.chomp, csv
|
43
|
+
end
|
44
|
+
end
|
data/test/test_helper.rb
CHANGED
@@ -1,14 +1,12 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'bundler/setup'
|
3
|
-
require 'csvision'
|
4
3
|
require 'test/unit'
|
5
4
|
require 'active_record'
|
6
5
|
require 'active_support'
|
7
6
|
require 'active_support/dependencies'
|
7
|
+
require 'csvision'
|
8
8
|
require 'turn'
|
9
9
|
|
10
|
-
include CSVision
|
11
|
-
|
12
10
|
TEST_PATH = File.expand_path( File.join File.dirname( __FILE__ ) )
|
13
11
|
config = YAML::load( IO.read( File.join TEST_PATH, 'config', 'database.yml' ) )['test']['sqlite']
|
14
12
|
|
@@ -19,3 +17,10 @@ ActiveRecord::Base.silence do
|
|
19
17
|
ActiveRecord::Migration.verbose = false
|
20
18
|
load File.join( TEST_PATH, 'db','schema.rb' )
|
21
19
|
end
|
20
|
+
|
21
|
+
class ActiveSupport::TestCase
|
22
|
+
def teardown
|
23
|
+
User.delete_all
|
24
|
+
Product.delete_all
|
25
|
+
end
|
26
|
+
end
|
data/test/user_test.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class UserTest < ActiveSupport::TestCase
|
4
|
+
EXPECTED_CSV = <<-CSV
|
5
|
+
"street_cred","nickname","incognito"
|
6
|
+
"495","user0","0resu"
|
7
|
+
"998","user3","3resu"
|
8
|
+
"1501","user6","6resu"
|
9
|
+
"2004","user9","9resu"
|
10
|
+
"2546","user12","21resu"
|
11
|
+
CSV
|
12
|
+
|
13
|
+
EXPECTED_CSV_WITH_SCOPE = <<-CSV
|
14
|
+
"street_cred","nickname","incognito"
|
15
|
+
"495","user0","0resu"
|
16
|
+
"998","user3","3resu"
|
17
|
+
"1501","user6","6resu"
|
18
|
+
CSV
|
19
|
+
|
20
|
+
EXPECTED_CSV_WITHOUT_HEADERS = <<-CSV
|
21
|
+
"495","user0","0resu"
|
22
|
+
"998","user3","3resu"
|
23
|
+
"1501","user6","6resu"
|
24
|
+
"2004","user9","9resu"
|
25
|
+
"2546","user12","21resu"
|
26
|
+
CSV
|
27
|
+
|
28
|
+
def setup
|
29
|
+
5.times { |i| assert User.create( :nickname => "user#{ i * 3}", :points => i * 5 ) }
|
30
|
+
end
|
31
|
+
|
32
|
+
test "can call to_csv directly from model" do
|
33
|
+
assert User.respond_to?(:to_csv)
|
34
|
+
assert csv = User.to_csv
|
35
|
+
assert_equal EXPECTED_CSV.chomp, csv
|
36
|
+
end
|
37
|
+
|
38
|
+
test "can chain scopes into the csv call" do
|
39
|
+
assert csv = User.flunky.to_csv
|
40
|
+
assert EXPECTED_CSV_WITH_SCOPE.chomp, csv
|
41
|
+
end
|
42
|
+
|
43
|
+
test "can pass options to t_csv" do
|
44
|
+
assert csv = User.to_csv( :headers => false )
|
45
|
+
assert_equal EXPECTED_CSV_WITHOUT_HEADERS.chomp, csv
|
46
|
+
end
|
47
|
+
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: csvision
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 23
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
8
|
+
- 2
|
9
9
|
- 0
|
10
|
-
version: 0.
|
10
|
+
version: 0.2.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Enrique Vidal
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2012-04-
|
18
|
+
date: 2012-04-14 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: activerecord
|
@@ -60,7 +60,7 @@ dependencies:
|
|
60
60
|
type: :development
|
61
61
|
version_requirements: *id003
|
62
62
|
- !ruby/object:Gem::Dependency
|
63
|
-
name:
|
63
|
+
name: rake
|
64
64
|
prerelease: false
|
65
65
|
requirement: &id004 !ruby/object:Gem::Requirement
|
66
66
|
none: false
|
@@ -73,24 +73,10 @@ dependencies:
|
|
73
73
|
version: "0"
|
74
74
|
type: :development
|
75
75
|
version_requirements: *id004
|
76
|
-
- !ruby/object:Gem::Dependency
|
77
|
-
name: rake
|
78
|
-
prerelease: false
|
79
|
-
requirement: &id005 !ruby/object:Gem::Requirement
|
80
|
-
none: false
|
81
|
-
requirements:
|
82
|
-
- - ">="
|
83
|
-
- !ruby/object:Gem::Version
|
84
|
-
hash: 3
|
85
|
-
segments:
|
86
|
-
- 0
|
87
|
-
version: "0"
|
88
|
-
type: :development
|
89
|
-
version_requirements: *id005
|
90
76
|
- !ruby/object:Gem::Dependency
|
91
77
|
name: turn
|
92
78
|
prerelease: false
|
93
|
-
requirement: &
|
79
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
94
80
|
none: false
|
95
81
|
requirements:
|
96
82
|
- - "="
|
@@ -102,7 +88,7 @@ dependencies:
|
|
102
88
|
- 2
|
103
89
|
version: 0.8.2
|
104
90
|
type: :development
|
105
|
-
version_requirements: *
|
91
|
+
version_requirements: *id005
|
106
92
|
description: Gives Hash the ability to be turned into csv files
|
107
93
|
email:
|
108
94
|
- enrique@cloverinteractive.com
|
@@ -123,11 +109,15 @@ files:
|
|
123
109
|
- lib/csvision/csv_helper.rb
|
124
110
|
- lib/csvision/version.rb
|
125
111
|
- test/app/models/product.rb
|
112
|
+
- test/app/models/sample_stack.rb
|
113
|
+
- test/app/models/user.rb
|
126
114
|
- test/config/database.yml
|
127
115
|
- test/csvision_test.rb
|
128
116
|
- test/db/schema.rb
|
117
|
+
- test/outside_of_rails_test.rb
|
129
118
|
- test/product_test.rb
|
130
119
|
- test/test_helper.rb
|
120
|
+
- test/user_test.rb
|
131
121
|
homepage: http://cloverinteractive.github.com/csvision/
|
132
122
|
licenses: []
|
133
123
|
|
@@ -163,8 +153,13 @@ specification_version: 3
|
|
163
153
|
summary: Adds support to hashes to be turned into csv
|
164
154
|
test_files:
|
165
155
|
- test/app/models/product.rb
|
156
|
+
- test/app/models/sample_stack.rb
|
157
|
+
- test/app/models/user.rb
|
166
158
|
- test/config/database.yml
|
167
159
|
- test/csvision_test.rb
|
168
160
|
- test/db/schema.rb
|
161
|
+
- test/outside_of_rails_test.rb
|
169
162
|
- test/product_test.rb
|
170
163
|
- test/test_helper.rb
|
164
|
+
- test/user_test.rb
|
165
|
+
has_rdoc:
|