├── VERSION
├── .gitignore
├── init.rb
├── lib
├── csv_builder.rb
└── csv_builder
│ ├── action_controller.rb
│ └── template_handler
│ └── base.rb
├── Rakefile
├── MIT-LICENSE
├── did_csv_builder.gemspec
└── README
/VERSION:
--------------------------------------------------------------------------------
1 | 0.1.4.beta2
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | rdoc
2 | pkg
3 |
--------------------------------------------------------------------------------
/init.rb:
--------------------------------------------------------------------------------
1 | require 'csv_builder'
2 |
3 | ActionView::Template.register_template_handler 'csvbuilder', CsvBuilder::TemplateHandler::Base
4 |
--------------------------------------------------------------------------------
/lib/csv_builder.rb:
--------------------------------------------------------------------------------
1 | require 'action_controller'
2 | require 'action_view'
3 |
4 | require 'fastercsv'
5 | require 'iconv'
6 |
7 | require 'csv_builder/action_controller'
8 | require 'csv_builder/template_handler/base'
9 |
10 | class ActionController::Base
11 | include CsvBuilder::ActionController
12 | end
13 |
14 | ActionView::Template.register_template_handler 'csvbuilder', CsvBuilder::TemplateHandler::Base
15 |
--------------------------------------------------------------------------------
/lib/csv_builder/action_controller.rb:
--------------------------------------------------------------------------------
1 | module CsvBuilder
2 | module ActionController
3 |
4 | DEFAULT_CSV_BUILDER_OPTIONS = { :col_sep => ';' }
5 |
6 | def csv_builder(options)
7 | @csv_builder_options = options
8 | end
9 |
10 | private
11 |
12 | def compute_csv_builder_options
13 | options = DEFAULT_CSV_BUILDER_OPTIONS.dup
14 | options.merge!(@csv_builder_options || {})
15 | options
16 | end
17 |
18 | end
19 |
20 | end
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
1 | require 'rake'
2 | require 'rake/rdoctask'
3 |
4 | desc 'Generate documentation for the csv_builder plugin.'
5 | Rake::RDocTask.new(:rdoc) do |rdoc|
6 | rdoc.rdoc_dir = 'rdoc'
7 | rdoc.title = 'CSV Builder'
8 | rdoc.options << '--line-numbers' << '--inline-source'
9 | rdoc.rdoc_files.include('README')
10 | rdoc.rdoc_files.include('lib/**/*.rb')
11 | end
12 |
13 |
14 | begin
15 | require 'jeweler'
16 | Jeweler::Tasks.new do |gem|
17 | gem.name = "did_csv_builder"
18 | gem.summary = %Q{CSV template Rails plugin}
19 | gem.description = %Q{CSV template Rails plugin}
20 | gem.email = "didier@nocoffee.fr"
21 | gem.homepage = "https://github.com/did/csv_builder"
22 | gem.authors = ["Tom Stuart"]
23 | gem.files = Dir.glob('lib/**/*.rb')
24 | end
25 | Jeweler::GemcutterTasks.new
26 | rescue LoadError
27 | puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
28 | end
--------------------------------------------------------------------------------
/MIT-LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2008 Econsultancy.com
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining
4 | a copy of this software and associated documentation files (the
5 | "Software"), to deal in the Software without restriction, including
6 | without limitation the rights to use, copy, modify, merge, publish,
7 | distribute, sublicense, and/or sell copies of the Software, and to
8 | permit persons to whom the Software is furnished to do so, subject to
9 | the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be
12 | included in all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/did_csv_builder.gemspec:
--------------------------------------------------------------------------------
1 | # Generated by jeweler
2 | # DO NOT EDIT THIS FILE DIRECTLY
3 | # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4 | # -*- encoding: utf-8 -*-
5 |
6 | Gem::Specification.new do |s|
7 | s.name = %q{did_csv_builder}
8 | s.version = "0.1.4.beta2"
9 |
10 | s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
11 | s.authors = [%q{Tom Stuart}]
12 | s.date = %q{2011-07-29}
13 | s.description = %q{CSV template Rails plugin}
14 | s.email = %q{didier@nocoffee.fr}
15 | s.extra_rdoc_files = [
16 | "README"
17 | ]
18 | s.files = [
19 | "lib/csv_builder.rb",
20 | "lib/csv_builder/action_controller.rb",
21 | "lib/csv_builder/template_handler/base.rb"
22 | ]
23 | s.homepage = %q{https://github.com/did/csv_builder}
24 | s.rdoc_options = [%q{--charset=UTF-8}]
25 | s.require_paths = [%q{lib}]
26 | s.rubygems_version = %q{1.8.5}
27 | s.summary = %q{CSV template Rails plugin}
28 |
29 | if s.respond_to? :specification_version then
30 | s.specification_version = 3
31 |
32 | if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
33 | else
34 | end
35 | else
36 | end
37 | end
38 |
39 |
--------------------------------------------------------------------------------
/README:
--------------------------------------------------------------------------------
1 | = CSV Builder
2 |
3 | The CSV Builder Rails plugin provides a simple templating system for serving
4 | dynamically generated CSV files from your application.
5 |
6 |
7 | == Requirements
8 |
9 | CSV Builder requires Rails v2.1.
10 |
11 | It also depends upon the FasterCSV gem http://fastercsv.rubyforge.org,
12 | which you can install with
13 |
14 | $ sudo gem install fastercsv
15 |
16 |
17 | == Example
18 |
19 | CSV template files are suffixed with '.csv.csvbuilder', for example
20 | 'index.csv.csvbuilder'
21 |
22 | Add rows to your CSV file in the template by pushing arrays of columns into the
23 | csv object.
24 |
25 | # First row
26 | csv << [ 'cell 1', 'cell 2' ]
27 | # Second row
28 | csv << [ 'another cell value', 'and another' ]
29 | # etc...
30 |
31 | You can set the default filename for that a browser will use for 'save as' by
32 | setting @filename instance variable in your controller's action method
33 | e.g.
34 |
35 | @filename = 'report.csv'
36 |
37 | You can also set the input encoding and output encoding by setting
38 | @input_encoding and @output_encoding instance variables.
39 | These default to 'UTF-8' and 'LATIN1' respectively. e.g.
40 |
41 | @output_encoding = 'UTF-8'
42 |
43 | You can also attach a csv file to mail sent out by your application by
44 | including a snippet like the following in your mailer method
45 |
46 | attachment "text/csv" do |attachment|
47 | attachment.body = render(:file => 'example/index.csv.csvbuilder')
48 | attachment.filename = 'report.csv'
49 | end
50 |
51 | You can change the separator character and that is as simple as writing this in your controller's
52 | action method:
53 |
54 | csv_builder :sep => ';'
55 |
56 | Actually, all default FasterCSV options can be overriden thanks to the previous statement.
57 |
58 | Copyright (c) 2008 Econsultancy.com, released under the MIT license
59 |
--------------------------------------------------------------------------------
/lib/csv_builder/template_handler/base.rb:
--------------------------------------------------------------------------------
1 | module CsvBuilder
2 | module TemplateHandler
3 |
4 | # Template handler for csv templates
5 | #
6 | # Add rows to your CSV file in the template by pushing arrays of columns into csv
7 | #
8 | # # First row
9 | # csv << [ 'cell 1', 'cell 2' ]
10 | # # Second row
11 | # csv << [ 'another cell value', 'and another' ]
12 | # # etc...
13 | #
14 | # You can set the default filename for that a browser will use for 'save as' by
15 | # setting @filename instance variable in your controller's action method
16 | # e.g.
17 | #
18 | # @filename = 'report.csv'
19 | #
20 | # You can also set the input encoding and output encoding by setting
21 | # @input_encoding and @output_encoding instance variables.
22 | # These default to 'UTF-8' and 'LATIN1' respectively. e.g.
23 | #
24 | # @output_encoding = 'UTF-8'
25 |
26 | class Base < ActionView::TemplateHandler
27 |
28 | include ActionView::TemplateHandlers::Compilable
29 |
30 | def self.line_offset
31 | 9
32 | end
33 |
34 | def compile(template)
35 | <<-EOV
36 | begin
37 |
38 | unless defined?(ActionMailer) && defined?(ActionMailer::Base) && controller.is_a?(ActionMailer::Base)
39 | @filename ||= "\#{controller.action_name}.csv"
40 | controller.response.headers["Content-Type"] ||= 'text/csv'
41 | controller.response.headers['Content-Disposition'] = "attachment; filename=\#{@filename}"
42 | end
43 |
44 | result = FasterCSV.generate(controller.send(:compute_csv_builder_options)) do |csv|
45 | #{template.source}
46 | end
47 |
48 | # Transliterate into the required encoding if necessary
49 | # TODO: make defaults configurable
50 | @input_encoding ||= 'UTF-8'
51 | @output_encoding ||= 'LATIN1'
52 |
53 | if @input_encoding == @output_encoding
54 | result
55 | else
56 | # TODO: do some checking to make sure iconv works correctly in
57 | # current environment. See ActiveSupport::Inflector#transliterate
58 | # definition for details
59 | #
60 | # Not using the more standard //IGNORE//TRANLIST because it raises
61 | # Iconv::IllegalSequence for some inputs
62 | c = Iconv.new("\#{@output_encoding}//TRANSLIT//IGNORE", @input_encoding)
63 | c.iconv(result)
64 | end
65 |
66 | rescue Exception => e
67 | RAILS_DEFAULT_LOGGER.warn("Exception \#{e} \#{e.message} with class \#{e.class.name} thrown when rendering CSV")
68 | raise e
69 | end
70 | EOV
71 | end
72 |
73 |
74 | end
75 | end
76 | end
77 |
78 |
79 | module ActionView # :nodoc:
80 | module TemplateHandlers
81 | # Template handler for csv templates
82 | #
83 | # Add rows to your CSV file in the template by pushing arrays of columns into csv
84 | #
85 | # # First row
86 | # csv << [ 'cell 1', 'cell 2' ]
87 | # # Second row
88 | # csv << [ 'another cell value', 'and another' ]
89 | # # etc...
90 | #
91 | # You can set the default filename for that a browser will use for 'save as' by
92 | # setting @filename instance variable in your controller's action method
93 | # e.g.
94 | #
95 | # @filename = 'report.csv'
96 | #
97 | # You can also set the input encoding and output encoding by setting
98 | # @input_encoding and @output_encoding instance variables.
99 | # These default to 'UTF-8' and 'LATIN1' respectively. e.g.
100 | #
101 | # @output_encoding = 'UTF-8'
102 |
103 | class CsvBuilder < TemplateHandler
104 |
105 | include Compilable
106 |
107 | attr_reader :csv_builder_options
108 |
109 | def self.line_offset
110 | 9
111 | end
112 |
113 | def compile(template)
114 | <<-EOV
115 | begin
116 |
117 | unless defined?(ActionMailer) && defined?(ActionMailer::Base) && controller.is_a?(ActionMailer::Base)
118 | @filename ||= "\#{controller.action_name}.csv"
119 | controller.response.headers["Content-Type"] ||= 'text/csv'
120 | controller.response.headers['Content-Disposition'] = "attachment; filename=\#{@filename}"
121 | end
122 |
123 | result = FasterCSV.generate do |csv|
124 | #{template.source}
125 | end
126 |
127 | # Transliterate into the required encoding if necessary
128 | # TODO: make defaults configurable
129 | @input_encoding ||= 'UTF-8'
130 | @output_encoding ||= 'LATIN1'
131 |
132 | if @input_encoding == @output_encoding
133 | result
134 | else
135 | # TODO: do some checking to make sure iconv works correctly in
136 | # current environment. See ActiveSupport::Inflector#transliterate
137 | # definition for details
138 | #
139 | # Not using the more standard //IGNORE//TRANLIST because it raises
140 | # Iconv::IllegalSequence for some inputs
141 | c = Iconv.new("\#{@output_encoding}//TRANSLIT//IGNORE", @input_encoding)
142 | c.iconv(result)
143 | end
144 |
145 | rescue Exception => e
146 | RAILS_DEFAULT_LOGGER.warn("Exception \#{e} \#{e.message} with class \#{e.class.name} thrown when rendering CSV")
147 | raise e
148 | end
149 | EOV
150 | end
151 |
152 | end
153 | end
154 | end
155 |
--------------------------------------------------------------------------------