make_exportable 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ module MakeExportable
2
+ class FormatNotFound < StandardError #:nodoc:
3
+ end
4
+
5
+ class ExportFault < StandardError #:nodoc:
6
+ end
7
+ end
@@ -0,0 +1,33 @@
1
+ module MakeExportable #:nodoc:
2
+ class ExportableFormat
3
+
4
+ class_inheritable_accessor :reference
5
+ class_inheritable_accessor :name
6
+
7
+ attr_accessor :long
8
+ attr_accessor :mime_type
9
+
10
+ class << self
11
+ # Register this format with the mothership
12
+ def register_format
13
+ unless MakeExportable.exportable_formats[self.reference]
14
+ MakeExportable.exportable_formats[self.reference] = self
15
+ end
16
+ end
17
+
18
+ end
19
+
20
+ def generate(data_set, data_headers=nil)
21
+ end
22
+
23
+ def sanitize(value)
24
+ value
25
+ end
26
+
27
+ def generate_header_option(data_headers=[])
28
+ self.mime_type += (self.data_headers.blank? || data_headers === false) ? " header=absent" : " header=present"
29
+ end
30
+
31
+ end
32
+
33
+ end
@@ -0,0 +1,34 @@
1
+ require "csv"
2
+ # for compatibility with Rails 2
3
+ require 'fastercsv' if CSV.const_defined?(:Reader)
4
+
5
+ module MakeExportable #:nodoc:
6
+ class CSV < ExportableFormat
7
+
8
+ cattr_accessor :csv_type
9
+
10
+ self.reference = :csv
11
+ self.name = 'CSV'
12
+ self.register_format
13
+ self.csv_type = ::CSV.const_defined?(:Reader) ? FasterCSV : ::CSV
14
+
15
+ attr_accessor :data_set, :data_headers
16
+
17
+ def initialize(data_set, data_headers=[])
18
+ self.long = 'Comma-separated (CSV)'
19
+ self.mime_type = 'text/csv; charset=utf-8;'
20
+ self.data_set = data_set
21
+ self.data_headers = data_headers
22
+ end
23
+
24
+
25
+ def generate
26
+ generate_header_option(data_headers)
27
+ @@csv_type.generate do |csv|
28
+ csv << data_headers.map {|h| sanitize(h.humanize.titleize)} unless data_headers.blank?
29
+ data_set.each {|row| csv << row }
30
+ end
31
+ end
32
+ end
33
+
34
+ end
@@ -0,0 +1,39 @@
1
+ module MakeExportable #:nodoc:
2
+ class Excel < ExportableFormat
3
+
4
+ self.reference = :xls
5
+ self.name = 'Excel'
6
+ self.register_format
7
+
8
+ attr_accessor :data_set, :data_headers
9
+
10
+ def initialize(data_set, data_headers=[])
11
+ self.long = 'Microsoft Excel'
12
+ self.mime_type = 'application/vnd.ms-excel; charset=utf-8;'
13
+ self.data_set = data_set
14
+ self.data_headers = data_headers
15
+ end
16
+
17
+ def generate
18
+ generate_header_option(data_headers)
19
+ output = "<table>\n"
20
+ unless data_headers.blank?
21
+ output << "\t<tr>\n"
22
+ output << data_headers.map {|h| "\t\t<th>#{sanitize(h.humanize.titleize)}</th>\n" }.join
23
+ output << "\t</tr>\n"
24
+ end
25
+ data_set.each do |row|
26
+ output << "\t<tr>\n"
27
+ output << row.map {|field| "\t\t<td>#{sanitize(field)}</td>\n"}.join
28
+ output << "\t</tr>\n"
29
+ end
30
+ output << "</table>\n"
31
+ return output
32
+ end
33
+
34
+ def sanitize(value)
35
+ value.gsub(/</, '&lt;').gsub(/>/, '&gt;')
36
+ end
37
+ end
38
+
39
+ end
@@ -0,0 +1,39 @@
1
+ module MakeExportable #:nodoc:
2
+ class HTML < ExportableFormat
3
+
4
+ self.reference = :html
5
+ self.name = 'HTML'
6
+ self.register_format
7
+
8
+ attr_accessor :data_set, :data_headers
9
+
10
+ def initialize(data_set, data_headers=[])
11
+ self.long = 'HTML'
12
+ self.mime_type = 'text/html; charset=utf-8;'
13
+ self.data_set = data_set
14
+ self.data_headers = data_headers
15
+ end
16
+
17
+ def generate
18
+ generate_header_option(data_headers)
19
+ output = "<table>\n"
20
+ unless data_headers.blank?
21
+ output << "\t<tr>\n"
22
+ output << data_headers.map {|h| "\t\t<th>#{sanitize(h.humanize.titleize)}</th>\n" }.join
23
+ output << "\t</tr>\n"
24
+ end
25
+ data_set.each do |row|
26
+ output << "\t<tr>\n"
27
+ output << row.map {|field| "\t\t<td>#{sanitize(field)}</td>\n"}.join
28
+ output << "\t</tr>\n"
29
+ end
30
+ output << "</table>\n"
31
+ return output
32
+ end
33
+
34
+ def sanitize(value)
35
+ value.gsub(/</, '&lt;').gsub(/>/, '&gt;')
36
+ end
37
+ end
38
+
39
+ end
@@ -0,0 +1,36 @@
1
+ module MakeExportable #:nodoc:
2
+ class JSON < ExportableFormat
3
+
4
+ self.reference = :json
5
+ self.name = "JSON"
6
+ self.register_format
7
+
8
+ attr_accessor :data_set, :data_headers
9
+
10
+ def initialize(data_set, data_headers=[])
11
+ self.long = "JavaScript Object Notation (JSON)"
12
+ self.mime_type = "application/json; charset=utf-8;"
13
+ self.data_set = data_set
14
+ self.data_headers = data_headers
15
+ end
16
+
17
+ def generate
18
+ output = []
19
+ unless data_headers.blank?
20
+ data_set.each do |row|
21
+ h = {}
22
+ row.each_with_index do |field, i|
23
+ h[data_headers[i]] = field
24
+ end
25
+ output << h
26
+ end
27
+ else
28
+ end
29
+ return output.to_json
30
+ end
31
+
32
+ def sanitize(value)
33
+ end
34
+
35
+ end
36
+ end
@@ -0,0 +1,34 @@
1
+ module MakeExportable #:nodoc:
2
+ class TSV < ExportableFormat
3
+
4
+ self.reference = :tsv
5
+ self.name = "TSV"
6
+ self.register_format
7
+
8
+ attr_accessor :data_set, :data_headers
9
+
10
+ def initialize(data_set, data_headers=[])
11
+ self.long = "Tab-separated (TSV)"
12
+ self.mime_type = "text/tab-separated-values; charset=utf-8;"
13
+ self.data_set = data_set
14
+ self.data_headers = data_headers
15
+ end
16
+
17
+ def generate
18
+ generate_header_option(data_headers)
19
+ output = ""
20
+ unless data_headers.blank?
21
+ output << data_headers.map {|h| sanitize(h.humanize.titleize) }.join("\t")
22
+ end
23
+ output << "\n" unless output.blank?
24
+ data_set.each do |row|
25
+ output << row.map {|field| sanitize(field)}.join("\t") << "\n"
26
+ end
27
+ return output
28
+ end
29
+
30
+ def sanitize(value)
31
+ value.gsub(/(\t|\\t)/, ' ')
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,43 @@
1
+ module MakeExportable #:nodoc:
2
+ class XML < ExportableFormat
3
+
4
+ self.reference = :xml
5
+ self.name = 'XML'
6
+ self.register_format
7
+
8
+ attr_accessor :data_set, :data_headers
9
+
10
+ def initialize(data_set, data_headers=[])
11
+ self.long = 'XML'
12
+ self.mime_type = 'application/xml;'
13
+ self.data_set = data_set
14
+ self.data_headers = data_headers
15
+ end
16
+
17
+ def generate
18
+ generate_header_option(data_headers)
19
+ xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
20
+ xml << "<records>\n"
21
+ data_set.each do |row|
22
+ xml << "\t<record>\n"
23
+ row.each_with_index do |field,i|
24
+ if !data_headers.blank?
25
+ attr_name = sanitize(data_headers[i].dasherize)
26
+ else
27
+ attr_name = "attribute_#{i}"
28
+ end
29
+ xml << "\t\t<#{attr_name}>#{sanitize(field)}</#{attr_name}>\n"
30
+ end
31
+ xml << "\t</record>\n"
32
+ end
33
+ xml << "</records>\n"
34
+ return xml
35
+ end
36
+
37
+ def sanitize(value)
38
+ value.gsub(/&/, '&amp;').gsub(/</, '&lt;').gsub(/>/, '&gt;').
39
+ gsub(/"/, '&quot;').gsub(/'/, '&apos;')
40
+ end
41
+ end
42
+
43
+ end
@@ -0,0 +1,27 @@
1
+ module MakeExportableHelper
2
+
3
+ def self.exportable_class_list
4
+ MakeExportable.exportable_classes.keys.sort {|item1, item2| item1[0] <=> item2[0] }
5
+ end
6
+
7
+ def self.exportable_table_list
8
+ MakeExportable.exportable_classes.values.map do |klass|
9
+ klass.table_name
10
+ end.sort {|item1, item2| item1[0] <=> item2[0] }
11
+ end
12
+
13
+ def self.exportable_format_list
14
+ MakeExportable.exportable_formats.map do |key, fmt|
15
+ [fmt.name, key]
16
+ end.sort {|item1, item2| item1[0] <=> item2[0] }
17
+ end
18
+
19
+ def self.exportable_units
20
+ hash = {}
21
+ MakeExportable.exportable_classes.values.map do |klass|
22
+ hash[klass] = klass.table_name
23
+ end
24
+ hash
25
+ end
26
+
27
+ end
@@ -0,0 +1,9 @@
1
+ module MakeExportable
2
+ module VERSION #:nodoc:
3
+ MAJOR = 1
4
+ MINOR = 0
5
+ TINY = 0
6
+
7
+ STRING = [MAJOR, MINOR, TINY].join('.')
8
+ end
9
+ end
data/rails/init.rb ADDED
@@ -0,0 +1 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'init')
data/spec/database.yml ADDED
@@ -0,0 +1,10 @@
1
+ sqlite3:
2
+ adapter: sqlite3
3
+ database: make_exportable.sqlite3
4
+
5
+ mysql:
6
+ adapter: mysql
7
+ hostname: localhost
8
+ username: root
9
+ password:
10
+ database: make_exportable
@@ -0,0 +1,10 @@
1
+ sqlite3:
2
+ adapter: sqlite3
3
+ database: make_exportable.sqlite3
4
+
5
+ mysql:
6
+ adapter: mysql
7
+ hostname: localhost
8
+ username: root
9
+ password:
10
+ database: make_exportable
@@ -0,0 +1,81 @@
1
+ require File.expand_path('../../spec_helper', __FILE__)
2
+
3
+ describe "Exportable Formats" do
4
+
5
+ before(:each) do
6
+ class User
7
+ make_exportable
8
+ end
9
+ clean_database!
10
+ User.create(:first_name => "user_1", :last_name => "Doe", :created_at => Time.at(0), :updated_at => Time.at(0))
11
+ User.create(:first_name => "user_2", :last_name => "Doe", :created_at => Time.at(0), :updated_at => Time.at(0))
12
+ end
13
+
14
+ context "csv format" do
15
+
16
+ it "should export the columns as csv" do
17
+ User.to_export( "csv", :only => [:first_name, "is_admin"]).should == ["First Name,Is Admin\nuser_1,false\nuser_2,false\n", "text/csv; charset=utf-8; header=present"]
18
+ end
19
+
20
+ it "should export the columns as csv and detect that there is no header" do
21
+ User.to_export( "csv", :only => [:first_name, "is_admin"], :headers => false).should == ["user_1,false\nuser_2,false\n", "text/csv; charset=utf-8; header=absent"]
22
+ end
23
+
24
+ end
25
+
26
+ context "excel format" do
27
+
28
+ it "should export the columns as xls" do
29
+ User.to_export( "xls", :only => [:first_name, "is_admin"]).should == ["<table>\n\t<tr>\n\t\t<th>First Name</th>\n\t\t<th>Is Admin</th>\n\t</tr>\n\t<tr>\n\t\t<td>user_1</td>\n\t\t<td>false</td>\n\t</tr>\n\t<tr>\n\t\t<td>user_2</td>\n\t\t<td>false</td>\n\t</tr>\n</table>\n", "application/vnd.ms-excel; charset=utf-8; header=present"]
30
+ end
31
+
32
+ it "should export the columns as xls and detect no header" do
33
+ User.to_export( "xls", :only => [:first_name, "is_admin"], :headers => false).should == ["<table>\n\t<tr>\n\t\t<td>user_1</td>\n\t\t<td>false</td>\n\t</tr>\n\t<tr>\n\t\t<td>user_2</td>\n\t\t<td>false</td>\n\t</tr>\n</table>\n", "application/vnd.ms-excel; charset=utf-8; header=absent"]
34
+ end
35
+
36
+ end
37
+
38
+ context "tsv format" do
39
+
40
+ it "should export the columns as tsv" do
41
+ User.to_export( "tsv", :only => [:first_name, "is_admin"]).should == ["First Name\tIs Admin\nuser_1\tfalse\nuser_2\tfalse\n", "text/tab-separated-values; charset=utf-8; header=present"]
42
+ end
43
+
44
+ it "should export the columns as tsv and detect no header" do
45
+ User.to_export( "tsv", :only => [:first_name, "is_admin"], :headers => false).should == ["user_1\tfalse\nuser_2\tfalse\n", "text/tab-separated-values; charset=utf-8; header=absent"]
46
+ end
47
+
48
+ end
49
+
50
+ context "html format" do
51
+
52
+ it "should export the columns as html" do
53
+ User.to_export( "html", :only => [:first_name, "is_admin"]).should == ["<table>\n\t<tr>\n\t\t<th>First Name</th>\n\t\t<th>Is Admin</th>\n\t</tr>\n\t<tr>\n\t\t<td>user_1</td>\n\t\t<td>false</td>\n\t</tr>\n\t<tr>\n\t\t<td>user_2</td>\n\t\t<td>false</td>\n\t</tr>\n</table>\n", "text/html; charset=utf-8; header=present"]
54
+ end
55
+
56
+ it "should export the columns as html and detect no header" do
57
+ User.to_export( "html", :only => [:first_name, "is_admin"], :headers => false).should == ["<table>\n\t<tr>\n\t\t<td>user_1</td>\n\t\t<td>false</td>\n\t</tr>\n\t<tr>\n\t\t<td>user_2</td>\n\t\t<td>false</td>\n\t</tr>\n</table>\n", "text/html; charset=utf-8; header=absent"]
58
+ end
59
+
60
+ end
61
+
62
+ context "xml format" do
63
+
64
+ it "should export the columns as xml" do
65
+ User.to_export( "xml", :only => [:first_name, "is_admin"]).should == ["<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<records>\n\t<record>\n\t\t<first-name>user_1</first-name>\n\t\t<is-admin>false</is-admin>\n\t</record>\n\t<record>\n\t\t<first-name>user_2</first-name>\n\t\t<is-admin>false</is-admin>\n\t</record>\n</records>\n", "application/xml; header=present"]
66
+ end
67
+
68
+ it "should export the columns as xml and detect no header" do
69
+ User.to_export( "xml", :only => [:first_name, "is_admin"], :headers => false).should == ["<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<records>\n\t<record>\n\t\t<attribute_0>user_1</attribute_0>\n\t\t<attribute_1>false</attribute_1>\n\t</record>\n\t<record>\n\t\t<attribute_0>user_2</attribute_0>\n\t\t<attribute_1>false</attribute_1>\n\t</record>\n</records>\n", "application/xml; header=absent"]
70
+ end
71
+
72
+ end
73
+
74
+ context "json format" do
75
+ it "should export the columns as json" do
76
+ User.to_export( "json", :only => [:first_name]).should ==["[{\"first_name\":\"user_1\"},{\"first_name\":\"user_2\"}]", "application/json; charset=utf-8;"]
77
+ end
78
+
79
+ end
80
+
81
+ end
@@ -0,0 +1,31 @@
1
+ require File.expand_path('../../spec_helper', __FILE__)
2
+
3
+ describe "Make Exportable Helper" do
4
+
5
+ before(:each) do
6
+ clean_database!
7
+ end
8
+
9
+ it "it should output an array of exportable classes" do
10
+ MakeExportable.exportable_classes = {}
11
+ User.class_eval("make_exportable")
12
+ Post.class_eval("make_exportable")
13
+ MakeExportableHelper.exportable_class_list.should == ["Post", "User"]
14
+ MakeExportable.exportable_classes = {}
15
+ end
16
+
17
+ it "it should output an array of exportable tables" do
18
+ User.class_eval("make_exportable")
19
+ Post.class_eval("make_exportable")
20
+ MakeExportableHelper.exportable_table_list.should ==["posts", "users"]
21
+ MakeExportable.exportable_classes = {}
22
+ end
23
+
24
+ it "it should output an array of exportable classes and tables to check against" do
25
+ User.class_eval("make_exportable")
26
+ Post.class_eval("make_exportable")
27
+ MakeExportableHelper.exportable_units.should == {User => "users", Post => "posts"}
28
+ MakeExportable.exportable_classes = {}
29
+ end
30
+
31
+ end