make_exportable 1.0.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.
@@ -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