Skip to content

Commit f0bab6a

Browse files
BurdetteLamarkou
andauthored
Split recipes into three pages: parsing, generating, filtering (#184)
Co-authored-by: Sutou Kouhei <kou@clear-code.com>
1 parent d7ae3df commit f0bab6a

File tree

5 files changed

+350
-240
lines changed

5 files changed

+350
-240
lines changed

csv.gemspec

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,15 @@ Gem::Specification.new do |spec|
4343
"LICENSE.txt",
4444
"NEWS.md",
4545
"README.md",
46-
"doc/csv/recipes.rdoc"
4746
]
47+
recipes_dir = File.join(doc_dir, "csv", "recipes")
48+
if File.exist?(recipes_dir)
49+
Dir.chdir(recipes_dir) do
50+
Dir.glob("**/*.rdoc").each do |recipe_file|
51+
rdoc_files << "doc/csv/recipes/#{recipe_file}"
52+
end
53+
end
54+
end
4855
spec.extra_rdoc_files = rdoc_files
4956

5057
spec.required_ruby_version = ">= 2.5.0"

doc/csv/recipes/filtering.rdoc

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
== Recipes for Filtering \CSV
2+
3+
For other recipes, see {Recipes for CSV}[./recipes_rdoc.html].
4+
5+
All code snippets on this page assume that the following has been executed:
6+
require 'csv'
7+
8+
=== Contents
9+
10+
- {Source and Output Formats}[#label-Source+and+Output+Formats]
11+
- {Filtering String to String}[#label-Filtering+String+to+String]
12+
- {Recipe: Filter String to String with Headers}[#label-Recipe-3A+Filter+String+to+String+with+Headers]
13+
- {Recipe: Filter String to String Without Headers}[#label-Recipe-3A+Filter+String+to+String+Without+Headers]
14+
- {Filtering String to IO Stream}[#label-Filtering+String+to+IO+Stream]
15+
- {Recipe: Filter String to IO Stream with Headers}[#label-Recipe-3A+Filter+String+to+IO+Stream+with+Headers]
16+
- {Recipe: Filter String to IO Stream Without Headers}[#label-Recipe-3A+Filter+String+to+IO+Stream+Without+Headers]
17+
- {Filtering IO Stream to String}[#label-Filtering+IO+Stream+to+String]
18+
- {Recipe: Filter IO Stream to String with Headers}[#label-Recipe-3A+Filter+IO+Stream+to+String+with+Headers]
19+
- {Recipe: Filter IO Stream to String Without Headers}[#label-Recipe-3A+Filter+IO+Stream+to+String+Without+Headers]
20+
- {Filtering IO Stream to IO Stream}[#label-Filtering+IO+Stream+to+IO+Stream]
21+
- {Recipe: Filter IO Stream to IO Stream with Headers}[#label-Recipe-3A+Filter+IO+Stream+to+IO+Stream+with+Headers]
22+
- {Recipe: Filter IO Stream to IO Stream Without Headers}[#label-Recipe-3A+Filter+IO+Stream+to+IO+Stream+Without+Headers]
23+
24+
=== Source and Output Formats
25+
26+
You can use a Unix-style "filter" for \CSV data.
27+
The filter reads source \CSV data and writes output \CSV data as modified by the filter.
28+
The input and output \CSV data may be any mixture of \Strings and \IO streams.
29+
30+
==== Filtering \String to \String
31+
32+
You can filter one \String to another, with or without headers.
33+
34+
===== Recipe: Filter \String to \String with Headers
35+
36+
Use class method CSV.filter with option +headers+ to filter a \String to another \String:
37+
in_string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
38+
out_string = ''
39+
CSV.filter(in_string, out_string, headers: true) do |row|
40+
row[0] = row[0].upcase
41+
row[1] *= 4
42+
end
43+
out_string # => "Name,Value\nFOO,0000\nBAR,1111\nBAZ,2222\n"
44+
45+
===== Recipe: Filter \String to \String Without Headers
46+
47+
Use class method CSV.filter without option +headers+ to filter a \String to another \String:
48+
in_string = "foo,0\nbar,1\nbaz,2\n"
49+
out_string = ''
50+
CSV.filter(in_string, out_string) do |row|
51+
row[0] = row[0].upcase
52+
row[1] *= 4
53+
end
54+
out_string # => "FOO,0000\nBAR,1111\nBAZ,2222\n"
55+
56+
==== Filtering \String to \IO Stream
57+
58+
You can filter a \String to an \IO stream, with or without headers.
59+
60+
===== Recipe: Filter \String to \IO Stream with Headers
61+
62+
Use class method CSV.filter with option +headers+ to filter a \String to an \IO stream:
63+
in_string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
64+
path = 't.csv'
65+
File.open(path, 'w') do |out_io|
66+
CSV.filter(in_string, out_io, headers: true) do |row|
67+
row[0] = row[0].upcase
68+
row[1] *= 4
69+
end
70+
end
71+
p File.read(path) # => "Name,Value\nFOO,0000\nBAR,1111\nBAZ,2222\n"
72+
73+
===== Recipe: Filter \String to \IO Stream Without Headers
74+
75+
Use class method CSV.filter without option +headers+ to filter a \String to an \IO stream:
76+
in_string = "foo,0\nbar,1\nbaz,2\n"
77+
path = 't.csv'
78+
File.open(path, 'w') do |out_io|
79+
CSV.filter(in_string, out_io) do |row|
80+
row[0] = row[0].upcase
81+
row[1] *= 4
82+
end
83+
end
84+
p File.read(path) # => "FOO,0000\nBAR,1111\nBAZ,2222\n"
85+
86+
==== Filtering \IO Stream to \String
87+
88+
You can filter an \IO stream to a \String, with or without headers.
89+
90+
===== Recipe: Filter \IO Stream to \String with Headers
91+
92+
Use class method CSV.filter with option +headers+ to filter an \IO stream to a \String:
93+
in_string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
94+
path = 't.csv'
95+
File.write(path, in_string)
96+
out_string = ''
97+
File.open(path, headers: true) do |in_io|
98+
CSV.filter(in_io, out_string, headers: true) do |row|
99+
row[0] = row[0].upcase
100+
row[1] *= 4
101+
end
102+
end
103+
out_string # => "Name,Value\nFOO,0000\nBAR,1111\nBAZ,2222\n"
104+
105+
===== Recipe: Filter \IO Stream to \String Without Headers
106+
107+
Use class method CSV.filter without option +headers+ to filter an \IO stream to a \String:
108+
in_string = "foo,0\nbar,1\nbaz,2\n"
109+
path = 't.csv'
110+
File.write(path, in_string)
111+
out_string = ''
112+
File.open(path) do |in_io|
113+
CSV.filter(in_io, out_string) do |row|
114+
row[0] = row[0].upcase
115+
row[1] *= 4
116+
end
117+
end
118+
out_string # => "FOO,0000\nBAR,1111\nBAZ,2222\n"
119+
120+
==== Filtering \IO Stream to \IO Stream
121+
122+
You can filter an \IO stream to another \IO stream, with or without headers.
123+
124+
===== Recipe: Filter \IO Stream to \IO Stream with Headers
125+
126+
Use class method CSV.filter with option +headers+ to filter an \IO stream to another \IO stream:
127+
in_path = 't.csv'
128+
in_string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
129+
File.write(in_path, in_string)
130+
out_path = 'u.csv'
131+
File.open(in_path) do |in_io|
132+
File.open(out_path, 'w') do |out_io|
133+
CSV.filter(in_io, out_io, headers: true) do |row|
134+
row[0] = row[0].upcase
135+
row[1] *= 4
136+
end
137+
end
138+
end
139+
p File.read(out_path) # => "Name,Value\nFOO,0000\nBAR,1111\nBAZ,2222\n"
140+
141+
===== Recipe: Filter \IO Stream to \IO Stream Without Headers
142+
143+
Use class method CSV.filter without option +headers+ to filter an \IO stream to another \IO stream:
144+
in_path = 't.csv'
145+
in_string = "foo,0\nbar,1\nbaz,2\n"
146+
File.write(in_path, in_string)
147+
out_path = 'u.csv'
148+
File.open(in_path) do |in_io|
149+
File.open(out_path, 'w') do |out_io|
150+
CSV.filter(in_io, out_io) do |row|
151+
row[0] = row[0].upcase
152+
row[1] *= 4
153+
end
154+
end
155+
end
156+
p File.read(out_path) # => "FOO,0000\nBAR,1111\nBAZ,2222\n"

doc/csv/recipes/generating.rdoc

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
== Recipes for Generating \CSV
2+
3+
For other recipes, see {Recipes for CSV}[./recipes_rdoc.html].
4+
5+
All code snippets on this page assume that the following has been executed:
6+
require 'csv'
7+
8+
=== Contents
9+
10+
- {Output Formats}[#label-Output+Formats]
11+
- {Generating to a String}[#label-Generating+to+a+String]
12+
- {Recipe: Generate to String with Headers}[#label-Recipe-3A+Generate+to+String+with+Headers]
13+
- {Recipe: Generate to String Without Headers}[#label-Recipe-3A+Generate+to+String+Without+Headers]
14+
- {Generating to a File}[#label-Generating+to+a+File]
15+
- {Recipe: Generate to File with Headers}[#label-Recipe-3A+Generate+to+File+with+Headers]
16+
- {Recipe: Generate to File Without Headers}[#label-Recipe-3A+Generate+to+File+Without+Headers]
17+
- {Generating to IO an Stream}[#label-Generating+to+an+IO+Stream]
18+
- {Recipe: Generate to IO Stream with Headers}[#label-Recipe-3A+Generate+to+IO+Stream+with+Headers]
19+
- {Recipe: Generate to IO Stream Without Headers}[#label-Recipe-3A+Generate+to+IO+Stream+Without+Headers]
20+
21+
=== Output Formats
22+
23+
You can generate \CSV output to a \String, to a \File (via its path), or to an \IO stream.
24+
25+
==== Generating to a \String
26+
27+
You can generate \CSV output to a \String, with or without headers.
28+
29+
===== Recipe: Generate to \String with Headers
30+
31+
Use class method CSV.generate with option +headers+ to generate to a \String.
32+
33+
This example uses method CSV#<< to append the rows
34+
that are to be generated:
35+
output_string = CSV.generate('', headers: ['Name', 'Value'], write_headers: true) do |csv|
36+
csv << ['Foo', 0]
37+
csv << ['Bar', 1]
38+
csv << ['Baz', 2]
39+
end
40+
output_string # => "Name,Value\nFoo,0\nBar,1\nBaz,2\n"
41+
42+
===== Recipe: Generate to \String Without Headers
43+
44+
Use class method CSV.generate without option +headers+ to generate to a \String.
45+
46+
This example uses method CSV#<< to append the rows
47+
that are to be generated:
48+
output_string = CSV.generate do |csv|
49+
csv << ['Foo', 0]
50+
csv << ['Bar', 1]
51+
csv << ['Baz', 2]
52+
end
53+
output_string # => "Foo,0\nBar,1\nBaz,2\n"
54+
55+
==== Generating to a \File
56+
57+
You can generate /CSV data to a \File, with or without headers.
58+
59+
===== Recipe: Generate to \File with Headers
60+
61+
Use class method CSV.open with option +headers+ generate to a \File.
62+
63+
This example uses method CSV#<< to append the rows
64+
that are to be generated:
65+
path = 't.csv'
66+
CSV.open(path, 'w', headers: ['Name', 'Value'], write_headers: true) do |csv|
67+
csv << ['Foo', 0]
68+
csv << ['Bar', 1]
69+
csv << ['Baz', 2]
70+
end
71+
p File.read(path) # => "Name,Value\nFoo,0\nBar,1\nBaz,2\n"
72+
73+
===== Recipe: Generate to \File Without Headers
74+
75+
Use class method CSV.open without option +headers+ to generate to a \File.
76+
77+
This example uses method CSV#<< to append the rows
78+
that are to be generated:
79+
path = 't.csv'
80+
CSV.open(path, 'w') do |csv|
81+
csv << ['Foo', 0]
82+
csv << ['Bar', 1]
83+
csv << ['Baz', 2]
84+
end
85+
p File.read(path) # => "Foo,0\nBar,1\nBaz,2\n"
86+
87+
==== Generating to an \IO Stream
88+
89+
You can generate \CSV data to an \IO stream, with or without headers.
90+
91+
==== Recipe: Generate to \IO Stream with Headers
92+
93+
Use class method CSV.new with option +headers+ to generate \CSV data to an \IO stream:
94+
path = 't.csv'
95+
File.open(path, 'w') do |file|
96+
csv = CSV.new(file, headers: ['Name', 'Value'], write_headers: true)
97+
csv << ['Foo', 0]
98+
csv << ['Bar', 1]
99+
csv << ['Baz', 2]
100+
end
101+
p File.read(path) # => "Name,Value\nFoo,0\nBar,1\nBaz,2\n"
102+
103+
===== Recipe: Generate to \IO Stream Without Headers
104+
105+
Use class method CSV.new without option +headers+ to generate \CSV data to an \IO stream:
106+
path = 't.csv'
107+
File.open(path, 'w') do |file|
108+
csv = CSV.new(file)
109+
csv << ['Foo', 0]
110+
csv << ['Bar', 1]
111+
csv << ['Baz', 2]
112+
end
113+
p File.read(path) # => "Foo,0\nBar,1\nBaz,2\n"

0 commit comments

Comments
 (0)