Skip to content

Commit

Permalink
pass options to FasterCSV
Browse files Browse the repository at this point in the history
  • Loading branch information
did committed May 26, 2009
1 parent eb15b10 commit 33d696d
Show file tree
Hide file tree
Showing 5 changed files with 191 additions and 74 deletions.
6 changes: 6 additions & 0 deletions README
Expand Up @@ -48,5 +48,11 @@ including a snippet like the following in your mailer method
attachment.filename = 'report.csv'
end

You can change the separator character and that is as simple as writing this in your controller's
action method:

csv_builder :sep => ';'

Actually, all default FasterCSV options can be overriden thanks to the previous statement.

Copyright (c) 2008 Econsultancy.com, released under the MIT license
2 changes: 1 addition & 1 deletion init.rb
@@ -1,3 +1,3 @@
require 'csv_builder'

ActionView::Template.register_template_handler 'csvbuilder', ActionView::TemplateHandlers::CsvBuilder
ActionView::Template.register_template_handler 'csvbuilder', CsvBuilder::TemplateHandler::Base
81 changes: 8 additions & 73 deletions lib/csv_builder.rb
@@ -1,77 +1,12 @@
require 'action_controller'
require 'action_view'

require 'fastercsv'
require 'iconv'

module ActionView # :nodoc:
module TemplateHandlers
# Template handler for csv templates
#
# Add rows to your CSV file in the template by pushing arrays of columns into csv
#
# # First row
# csv << [ 'cell 1', 'cell 2' ]
# # Second row
# csv << [ 'another cell value', 'and another' ]
# # etc...
#
# You can set the default filename for that a browser will use for 'save as' by
# setting <tt>@filename</tt> instance variable in your controller's action method
# e.g.
#
# @filename = 'report.csv'
#
# You can also set the input encoding and output encoding by setting
# <tt>@input_encoding</tt> and <tt>@output_encoding</tt> instance variables.
# These default to 'UTF-8' and 'LATIN1' respectively. e.g.
#
# @output_encoding = 'UTF-8'

class CsvBuilder < TemplateHandler

include Compilable

def self.line_offset
9
end

def compile(template)
<<-EOV
begin
unless defined?(ActionMailer) && defined?(ActionMailer::Base) && controller.is_a?(ActionMailer::Base)
@filename ||= "\#{controller.action_name}.csv"
controller.response.headers["Content-Type"] ||= 'text/csv'
controller.response.headers['Content-Disposition'] = "attachment; filename=\#{@filename}"
end
result = FasterCSV.generate do |csv|
#{template.source}
end
# Transliterate into the required encoding if necessary
# TODO: make defaults configurable
@input_encoding ||= 'UTF-8'
@output_encoding ||= 'LATIN1'
if @input_encoding == @output_encoding
result
else
# TODO: do some checking to make sure iconv works correctly in
# current environment. See ActiveSupport::Inflector#transliterate
# definition for details
#
# Not using the more standard //IGNORE//TRANLIST because it raises
# Iconv::IllegalSequence for some inputs
c = Iconv.new("\#{@output_encoding}//TRANSLIT//IGNORE", @input_encoding)
c.iconv(result)
end
rescue Exception => e
RAILS_DEFAULT_LOGGER.warn("Exception \#{e} \#{e.message} with class \#{e.class.name} thrown when rendering CSV")
raise e
end
EOV
end
require 'csv_builder/action_controller'
require 'csv_builder/template_handler/base'

end
end
end
class ActionController::Base
include CsvBuilder::ActionController
end
22 changes: 22 additions & 0 deletions lib/csv_builder/action_controller.rb
@@ -0,0 +1,22 @@
module CsvBuilder
module ActionController

DEFAULT_CSV_BUILDER_OPTIONS = { :col_sep => ';' }

def csv_builder(options)
@csv_builder_options = options
end

private

def compute_csv_builder_options
options = DEFAULT_CSV_BUILDER_OPTIONS.dup
options.merge!(@csv_builder_options || {})
options
end

end

end


154 changes: 154 additions & 0 deletions lib/csv_builder/template_handler/base.rb
@@ -0,0 +1,154 @@
module CsvBuilder
module TemplateHandler

# Template handler for csv templates
#
# Add rows to your CSV file in the template by pushing arrays of columns into csv
#
# # First row
# csv << [ 'cell 1', 'cell 2' ]
# # Second row
# csv << [ 'another cell value', 'and another' ]
# # etc...
#
# You can set the default filename for that a browser will use for 'save as' by
# setting <tt>@filename</tt> instance variable in your controller's action method
# e.g.
#
# @filename = 'report.csv'
#
# You can also set the input encoding and output encoding by setting
# <tt>@input_encoding</tt> and <tt>@output_encoding</tt> instance variables.
# These default to 'UTF-8' and 'LATIN1' respectively. e.g.
#
# @output_encoding = 'UTF-8'

class Base < ActionView::TemplateHandler

include ActionView::TemplateHandlers::Compilable

def self.line_offset
9
end

def compile(template)
<<-EOV
begin
unless defined?(ActionMailer) && defined?(ActionMailer::Base) && controller.is_a?(ActionMailer::Base)
@filename ||= "\#{controller.action_name}.csv"
controller.response.headers["Content-Type"] ||= 'text/csv'
controller.response.headers['Content-Disposition'] = "attachment; filename=\#{@filename}"
end
result = FasterCSV.generate(controller.send(:compute_csv_builder_options)) do |csv|
#{template.source}
end
# Transliterate into the required encoding if necessary
# TODO: make defaults configurable
@input_encoding ||= 'UTF-8'
@output_encoding ||= 'LATIN1'
if @input_encoding == @output_encoding
result
else
# TODO: do some checking to make sure iconv works correctly in
# current environment. See ActiveSupport::Inflector#transliterate
# definition for details
#
# Not using the more standard //IGNORE//TRANLIST because it raises
# Iconv::IllegalSequence for some inputs
c = Iconv.new("\#{@output_encoding}//TRANSLIT//IGNORE", @input_encoding)
c.iconv(result)
end
rescue Exception => e
RAILS_DEFAULT_LOGGER.warn("Exception \#{e} \#{e.message} with class \#{e.class.name} thrown when rendering CSV")
raise e
end
EOV
end


end
end
end


module ActionView # :nodoc:
module TemplateHandlers
# Template handler for csv templates
#
# Add rows to your CSV file in the template by pushing arrays of columns into csv
#
# # First row
# csv << [ 'cell 1', 'cell 2' ]
# # Second row
# csv << [ 'another cell value', 'and another' ]
# # etc...
#
# You can set the default filename for that a browser will use for 'save as' by
# setting <tt>@filename</tt> instance variable in your controller's action method
# e.g.
#
# @filename = 'report.csv'
#
# You can also set the input encoding and output encoding by setting
# <tt>@input_encoding</tt> and <tt>@output_encoding</tt> instance variables.
# These default to 'UTF-8' and 'LATIN1' respectively. e.g.
#
# @output_encoding = 'UTF-8'

class CsvBuilder < TemplateHandler

include Compilable

attr_reader :csv_builder_options

def self.line_offset
9
end

def compile(template)
<<-EOV
begin
unless defined?(ActionMailer) && defined?(ActionMailer::Base) && controller.is_a?(ActionMailer::Base)
@filename ||= "\#{controller.action_name}.csv"
controller.response.headers["Content-Type"] ||= 'text/csv'
controller.response.headers['Content-Disposition'] = "attachment; filename=\#{@filename}"
end
result = FasterCSV.generate do |csv|
#{template.source}
end
# Transliterate into the required encoding if necessary
# TODO: make defaults configurable
@input_encoding ||= 'UTF-8'
@output_encoding ||= 'LATIN1'
if @input_encoding == @output_encoding
result
else
# TODO: do some checking to make sure iconv works correctly in
# current environment. See ActiveSupport::Inflector#transliterate
# definition for details
#
# Not using the more standard //IGNORE//TRANLIST because it raises
# Iconv::IllegalSequence for some inputs
c = Iconv.new("\#{@output_encoding}//TRANSLIT//IGNORE", @input_encoding)
c.iconv(result)
end
rescue Exception => e
RAILS_DEFAULT_LOGGER.warn("Exception \#{e} \#{e.message} with class \#{e.class.name} thrown when rendering CSV")
raise e
end
EOV
end

end
end
end

0 comments on commit 33d696d

Please sign in to comment.