tabl 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --colour
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem 'activesupport'
4
+ gem 'fastercsv'
5
+
6
+ group :development do
7
+ gem "rspec", "~> 2.6.0"
8
+ gem "bundler", "~> 1.0.0"
9
+ gem "jeweler", "~> 1.6.4"
10
+
11
+ gem 'libnotify'
12
+ gem 'guard-rspec'
13
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,40 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ activesupport (3.0.10)
5
+ diff-lcs (1.1.3)
6
+ fastercsv (1.5.4)
7
+ ffi (1.0.9)
8
+ git (1.2.5)
9
+ guard (0.6.3)
10
+ thor (~> 0.14.6)
11
+ guard-rspec (0.4.5)
12
+ guard (>= 0.4.0)
13
+ jeweler (1.6.4)
14
+ bundler (~> 1.0)
15
+ git (>= 1.2.5)
16
+ rake
17
+ libnotify (0.5.7)
18
+ ffi (= 1.0.9)
19
+ rake (0.9.2)
20
+ rspec (2.6.0)
21
+ rspec-core (~> 2.6.0)
22
+ rspec-expectations (~> 2.6.0)
23
+ rspec-mocks (~> 2.6.0)
24
+ rspec-core (2.6.4)
25
+ rspec-expectations (2.6.0)
26
+ diff-lcs (~> 1.1.2)
27
+ rspec-mocks (2.6.0)
28
+ thor (0.14.6)
29
+
30
+ PLATFORMS
31
+ ruby
32
+
33
+ DEPENDENCIES
34
+ activesupport
35
+ bundler (~> 1.0.0)
36
+ fastercsv
37
+ guard-rspec
38
+ jeweler (~> 1.6.4)
39
+ libnotify
40
+ rspec (~> 2.6.0)
data/Guardfile ADDED
@@ -0,0 +1,21 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard 'rspec', :version => 2 do
5
+ watch(%r{^spec/.+_spec\.rb$})
6
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
7
+ watch('spec/spec_helper.rb') { "spec" }
8
+
9
+ # Rails example
10
+ # watch(%r{^spec/.+_spec\\.rb$})
11
+ # watch(%r{^app/(.+)\\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
12
+ # watch(%r{^lib/(.+)\\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
13
+ # watch(%r{^app/controllers/(.+)_(controller)\\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
14
+ # watch(%r{^spec/support/(.+)\\.rb$}) { "spec" }
15
+ # watch('spec/spec_helper.rb') { "spec" }
16
+ # watch('config/routes.rb') { "spec/routing" }
17
+ # watch('app/controllers/application_controller.rb') { "spec/controllers" }
18
+ # # Capybara request specs
19
+ # watch(%r{^app/views/(.+)/.*\\.(erb|haml)$}) { |m| "spec/requests/#{m[1]}_spec.rb" }
20
+ end
21
+
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Liehann Loots
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.
data/README.md ADDED
@@ -0,0 +1,150 @@
1
+ # Tabl - Creating Tables and Reports the Easy Way
2
+
3
+ ## Table Definitions
4
+
5
+ Create a table definition:
6
+ class UserTables
7
+ table :table do |config|
8
+ config.columns = [
9
+ :name,
10
+ :email,
11
+ :phone_number
12
+ ]
13
+ end
14
+ end
15
+
16
+ By default this creates a table with the columns specified. The column labels are the symbols titleized. Eg:
17
+ * Name
18
+ * Email
19
+ * Phone Number
20
+
21
+ The values will evaluate to calling column method on the record:
22
+ * `user.name`
23
+ * `user.email`
24
+ * `user.phone_number`
25
+
26
+ Both of these can be overridden:
27
+ class UserTables
28
+ table :table do |config|
29
+ config.columns = [
30
+ :name,
31
+ :email,
32
+ :phone_number
33
+ ]
34
+
35
+ config.labels[:name] = 'Full Name'
36
+
37
+ config.values[:name] = lambda { |user| user.name.upcase }
38
+ end
39
+ end
40
+
41
+
42
+ ## Outputting
43
+
44
+ Tabl outputs to CSV:
45
+ users = Users.all
46
+ UserTables.table.to_csv(users)
47
+
48
+ Currently html output needs to be done manually:
49
+ %table
50
+ %thead
51
+ %tr
52
+ - UserTables.table.labels.each do |label|
53
+ %th&= label
54
+ %tbody
55
+ - users.each do |user|
56
+ %tr
57
+ - UserTables.table.values.each do |value|
58
+ %td&= value
59
+
60
+ ## Default Value
61
+
62
+ A default value can be used if values are null. For example it may be preferable to display a dash instead of an empty column.
63
+ fmt = UserTables.table.format do |config|
64
+ config.default_value = '-'
65
+ end
66
+
67
+
68
+ ## Formatting
69
+
70
+ Different formats can be defined for the same table definition. This allows the values to be computed differently. For example for html by default values should be escaped.
71
+ fmt = UserTables.table.format do |config|
72
+ config.default_format = lambda { |v| h(v) }
73
+ end
74
+
75
+ This can be overridden per column, allowing some columns to be formatted as links.
76
+ fmt = UserTables.table.format do |config|
77
+ # The second parameter is optional.
78
+ config.format[:name] = lambda { |name, line| link_to v, line }
79
+ end
80
+
81
+ ## Shared Definitions
82
+
83
+ Sometimes definitions are common over several tables. In this case a definition can be configured in a module and included into table definitions.
84
+ module UserColumns
85
+ # Specify what part of the record is required. This is typically an association.
86
+ record :user
87
+
88
+ # Columns can be configured using a hash.
89
+ column :name, :label => 'User', :value => lambda {|v| user.name.upcase}
90
+
91
+ # Or using a block.
92
+ column :name do |config|
93
+ config.label = 'User'
94
+ config.value = lambda { |user| user.name.upcase }
95
+ config.format.html = lambda { |name, user| link_to name, user }
96
+ end
97
+ end
98
+
99
+ This shared definition can then be used in other tables. The shared definition is only invoked if the record returns a non-nil object. If the record is not defined the base object is assumed to be the record.
100
+ module JobTables
101
+ include UserColumns
102
+
103
+ table :jobs_report do |config|
104
+ config.records[:user] = lambda { |job| job.user }
105
+ end
106
+ end
107
+
108
+ module UserTables
109
+ table :users_report do |config|
110
+ # Implicitly equivalent to:
111
+ # config.records[:user] => lambda { |user| user }
112
+ end
113
+ end
114
+
115
+ ## More Formatting
116
+
117
+ Default format objects can be created. HTML is a default built in format.
118
+ module UserTables
119
+ table :user_report do |config|
120
+ config.format(:html) do |format|
121
+ format.format[:name] = lambda { |name, line| link_to v, line }
122
+ end
123
+ end
124
+ end
125
+
126
+ This format can be accessed from the table.
127
+ fmt = UserTables.user_report.format(:html)
128
+
129
+ To define formatting on shared definitions:
130
+ module UserColumns
131
+ column :name do |config|
132
+ config.format[:html] = lambda { |name, line| link_to v, line }
133
+ end
134
+ end
135
+
136
+ To create a custom built in format:
137
+ class HtmlFormatter
138
+ Tabl::Formatters.register(:html, HtmlFormatter)
139
+
140
+ def default_value
141
+ '-'
142
+ end
143
+
144
+ def default_format(value)
145
+ h(value)
146
+ end
147
+ end
148
+
149
+ UserTables.user_report.html.formatted_values(user)
150
+
data/Rakefile ADDED
@@ -0,0 +1,33 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17
+ gem.name = "tabl"
18
+ gem.homepage = "http://github.com/liehann/tabl"
19
+ gem.license = "MIT"
20
+ gem.summary = %Q{Gem for creating tables in Rails or any other system.}
21
+ gem.description = %Q{Gem for creating tables in Rails or any other system.}
22
+ gem.email = "liehannl@gmail.com"
23
+ gem.authors = ["Liehann Loots"]
24
+ # dependencies defined in Gemfile
25
+ end
26
+ Jeweler::RubygemsDotOrgTasks.new
27
+
28
+ require 'rspec/core'
29
+ require 'rspec/core/rake_task'
30
+ RSpec::Core::RakeTask.new(:spec) do |spec|
31
+ spec.pattern = FileList['spec/**/*_spec.rb']
32
+ end
33
+
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,63 @@
1
+ module Tabl
2
+ class Column
3
+ attr_reader :name
4
+ attr_accessor :label
5
+ attr_writer :value
6
+
7
+ def initialize(name, args = {})
8
+ @name = name
9
+ @label = args[:label] || @name.to_s.titleize
10
+ @value = args[:value] || lambda { |record| record.send(@name) }
11
+ @formats = Formats.new
12
+ yield self if block_given?
13
+ end
14
+
15
+ def value(record)
16
+ @value.call(record)
17
+ end
18
+
19
+ def format(name = nil)
20
+ @formats
21
+ end
22
+
23
+ class Formats
24
+ def initialize
25
+ @formats = {}
26
+ end
27
+
28
+ def [](name)
29
+ @formats[name]
30
+ end
31
+
32
+ def method_missing(name, *args)
33
+ name = name.to_s
34
+ assign = (name =~ /=$/)
35
+ key = name.gsub(/=$/, '').to_sym
36
+
37
+ # super unless Tabl.formats.include?(key)
38
+
39
+ if (assign)
40
+ write(key, *args)
41
+ else
42
+ read(key, *args)
43
+ end
44
+ end
45
+
46
+ def write(key, proc)
47
+ @formats[key] = proc
48
+ end
49
+
50
+ def read(key, value = nil, record = nil)
51
+ format = @formats[key]
52
+ return format unless value
53
+ if (format.arity == 1)
54
+ return format.call(value)
55
+ else
56
+ return format.call(value, record)
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+
63
+
@@ -0,0 +1,56 @@
1
+ module Tabl
2
+ class Definition
3
+ attr_reader :columns
4
+ attr_reader :labels
5
+ attr_reader :values
6
+
7
+ attr_reader :format
8
+ attr_accessor :default_format
9
+ attr_accessor :default_value
10
+
11
+ def initialize(values_override = nil, &block)
12
+ @columns = []
13
+ @labels = {}
14
+ @values = {}
15
+ @format = {}
16
+ @values_override = values_override
17
+ @default_format = lambda { |v| v }
18
+ @default_value = nil
19
+ configure(&block)
20
+ format = Hash.new { Format.new }
21
+ end
22
+
23
+ def configure(&block)
24
+ yield(self) if block_given?
25
+ end
26
+
27
+ def columns=(columns)
28
+ @columns = columns.clone
29
+ @columns.each do |key|
30
+ @values[key] ||= default_value_proc(key)
31
+ @labels[key] ||= key.to_s.titleize
32
+ end
33
+ end
34
+
35
+ def clone
36
+ other = super
37
+ other.instance_variable_set(:@columns, @columns.clone)
38
+ other.instance_variable_set(:@labels, @labels.clone)
39
+ other.instance_variable_set(:@values, @values.clone)
40
+ other.instance_variable_set(:@format, @format.clone)
41
+ other
42
+ end
43
+
44
+ private
45
+
46
+ def default_value_proc(key)
47
+ if @values_override && @values_override.respond_to?(key)
48
+ @values_override.method(key)
49
+ else
50
+ lambda { |row| row.send(key) }
51
+ end
52
+ end
53
+
54
+ end
55
+ end
56
+
@@ -0,0 +1,29 @@
1
+ module Tabl
2
+ class DerefColumn
3
+ attr_reader :column
4
+
5
+ def initialize(column, deref)
6
+ @column = column
7
+ @callback = deref
8
+ @callback = lambda { |record| record.send(deref) } if Symbol === deref
9
+ end
10
+
11
+ def value(record)
12
+ super(deref(record))
13
+ end
14
+
15
+ def deref(record)
16
+ @callback.call(record)
17
+ end
18
+
19
+ def method_missing(name, *args)
20
+ @column.send(name, *args)
21
+ end
22
+
23
+ def clone
24
+ DerefColumn.new(@column.clone, @callback.clone)
25
+ end
26
+ end
27
+ end
28
+
29
+
data/lib/tabl/dsl.rb ADDED
@@ -0,0 +1,64 @@
1
+ module Tabl
2
+ module Dsl
3
+ def Dsl.included(mod)
4
+ mod.extend(ClassMethods)
5
+ end
6
+
7
+ # Defines a dsl to create tables.
8
+ module ClassMethods
9
+
10
+ def column(name, args = {}, &block)
11
+ columns_hash[name] = column = Column.new(name, args, &block)
12
+ self.send(:define_method, name) { return column }
13
+ singleton_class.send(:define_method, name) { return column }
14
+ end
15
+
16
+ def columns
17
+ columns_hash.values
18
+ end
19
+
20
+ # Define a new table.
21
+ # module UserTables
22
+ # include Tabl::Dsl
23
+ #
24
+ # table :users, [:name, :email, :phone]
25
+ # end
26
+ #
27
+ # MyTables.foo
28
+ # # => <Table name:foo>
29
+ def table(name, args = {}, &block)
30
+ args[:base_columns] ||= columns
31
+ table = Table.new(args, &block)
32
+ tables << table
33
+ singleton_class.send(:define_method, name) { return table }
34
+ end
35
+
36
+ def tables
37
+ @tables ||= []
38
+ end
39
+
40
+ # Includes column definitions. These column definitions will be available
41
+ # to any tables defined in the module.
42
+ #
43
+ # module UserTables
44
+ # include Tabl::Dsl
45
+ #
46
+ # include_columns(UserColumns)
47
+ # end
48
+ def include_columns(mod, args = {})
49
+ mod.columns.each do |column|
50
+ column = args[:record] ? DerefColumn.new(column, args[:record]) : column
51
+ columns_hash[column.name] = column
52
+ end
53
+ end
54
+
55
+ private
56
+
57
+ def columns_hash
58
+ @columns_hash ||= {}
59
+ end
60
+
61
+ end
62
+ end
63
+ end
64
+
@@ -0,0 +1,17 @@
1
+ module Tabl
2
+ module Formats
3
+ module Html
4
+ Formats.register(:html, Html)
5
+
6
+ def self.default_value
7
+ '-'
8
+ end
9
+
10
+ def self.format(value)
11
+ ERB::Util.h(value)
12
+ end
13
+
14
+ end
15
+ end
16
+ end
17
+
@@ -0,0 +1,22 @@
1
+ module Tabl
2
+ module Formats
3
+ @@formats = {}
4
+
5
+ def self.register(key, mod)
6
+ @@formats[key] = mod
7
+ end
8
+
9
+ def self.exist?(key)
10
+ @@formats.exist?(key)
11
+ end
12
+
13
+ def self.method_missing(key, *args)
14
+ @@formats[key] || super
15
+ end
16
+
17
+ def self.[](key)
18
+ @@formats[key]
19
+ end
20
+ end
21
+ end
22
+
data/lib/tabl/table.rb ADDED
@@ -0,0 +1,109 @@
1
+ module Tabl
2
+ class Table
3
+ attr_reader :keys
4
+ attr_reader :columns
5
+
6
+ def initialize(args = {})
7
+ @base_columns = {}
8
+ add_base_columns(args[:base_columns] || {})
9
+ @formats = {}
10
+ @columns = {}
11
+ self.columns=(args[:columns] || [])
12
+ yield self if block_given?
13
+ end
14
+
15
+ def add_base_columns(columns)
16
+ columns.each do |column|
17
+ @base_columns[column.name] = column
18
+ end
19
+ end
20
+
21
+ def columns
22
+ @columns_cache ||= @keys.map { |key| column(key) }
23
+ end
24
+
25
+ def base_columns
26
+ @base_columns.values
27
+ end
28
+
29
+ def columns=(keys)
30
+ @keys = keys
31
+ @columns_cache = nil
32
+ @keys.each do |key|
33
+ @columns[key] ||= Column.new(key) unless @base_columns.include?(key)
34
+ end
35
+ end
36
+
37
+ def labels
38
+ @keys.map { |key| column(key).label }
39
+ end
40
+
41
+ def values(record)
42
+ @keys.map { |key| value(key, record) }
43
+ end
44
+
45
+ def value(key, record)
46
+ column(key).value(record)
47
+ end
48
+
49
+ def column(key)
50
+ @columns[key] || @base_columns[key]
51
+ end
52
+
53
+ def method_missing(name, *args)
54
+ # Check columns first, creating an override if one doesn't exist already.
55
+ column = @columns[name] || (@base_columns.include?(name) && @columns[name] = @base_columns[name].clone)
56
+ if column
57
+ yield column if block_given?
58
+ return column
59
+ end
60
+
61
+ # Check formats next
62
+ format = @formats[name]
63
+ return format if format
64
+
65
+ # Create a new format object
66
+ format_base = Formats.send(name) || super
67
+ @formats[name] = Format.new(name, self, format_base)
68
+ end
69
+
70
+ def to_csv(records)
71
+ FasterCSV.generate do |csv|
72
+ csv << labels
73
+ records.each do |record|
74
+ csv << values(record)
75
+ end
76
+ end
77
+ end
78
+
79
+ class Format
80
+ def initialize(name, table, base)
81
+ @name = name
82
+ @table = table
83
+ @base = base
84
+ end
85
+
86
+ def values(record)
87
+ @table.keys.map do |key|
88
+ value = @table.value(key, record)
89
+ if value
90
+ format(key, value, record)
91
+ else
92
+ @base.default_value unless value
93
+ end
94
+ end
95
+ end
96
+
97
+ def format(key, value, record)
98
+ column = @table.column(key)
99
+
100
+ if column.format[@name]
101
+ column.format.read(@name, value, record)
102
+ else
103
+ @base.format(value)
104
+ end
105
+ end
106
+ end
107
+ end
108
+ end
109
+
data/lib/tabl.rb ADDED
@@ -0,0 +1,22 @@
1
+ require 'rubygems'
2
+ require 'active_support/inflector'
3
+ require 'active_support/core_ext/class/inheritable_attributes'
4
+ require 'active_support/core_ext/kernel/singleton_class'
5
+ require 'active_support/core_ext/module/remove_method'
6
+ require 'active_support/core_ext/string/output_safety'
7
+ require 'fastercsv'
8
+
9
+ require 'tabl/formats'
10
+ require 'tabl/formats/html'
11
+
12
+ require 'tabl/column'
13
+ require 'tabl/deref_column'
14
+ require 'tabl/table'
15
+
16
+ require 'tabl/dsl'
17
+
18
+ # require 'tabl/definition'
19
+ # require 'tabl/format'
20
+ # require 'tabl/table'
21
+ # require 'tabl/base'
22
+
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+ require 'lib/user_columns'
3
+ require 'lib/post_tables'
4
+
5
+ describe PostTables do
6
+ it 'should return csv' do
7
+ post = OpenStruct.new(:post => 'foo', :user => OpenStruct.new(:first_name => 'John', :last_name => 'Smith'))
8
+ PostTables.posts.to_csv([post]).should == <<CSV
9
+ Post,User
10
+ foo,John Smith
11
+ CSV
12
+ end
13
+ end
14
+
15
+
@@ -0,0 +1,11 @@
1
+ module PostTables
2
+ include Tabl::Dsl
3
+
4
+ include_columns UserColumns, :record => :user
5
+
6
+ table :posts do |table|
7
+ table.columns = [ :post, :user ]
8
+ end
9
+
10
+ end
11
+
@@ -0,0 +1,8 @@
1
+ class UserColumns
2
+ include Tabl::Dsl
3
+
4
+ column :user do |column|
5
+ column.value = lambda { |user| [ user.first_name, user.last_name ].join(' ') }
6
+ end
7
+ end
8
+
@@ -0,0 +1,9 @@
1
+ require 'rspec'
2
+ require 'tabl'
3
+ require 'ostruct'
4
+
5
+ $: << File.join(File.dirname(File.expand_path(__FILE__)), 'lib')
6
+
7
+ RSpec.configure do |config|
8
+ end
9
+
@@ -0,0 +1,49 @@
1
+ require 'spec_helper'
2
+
3
+ describe Tabl::Column do
4
+ it 'should have a label' do
5
+ column = Tabl::Column.new(:foo)
6
+ column.label.should == 'Foo'
7
+ end
8
+
9
+ it 'should product a value' do
10
+ foo = OpenStruct.new(:foo => 'foo')
11
+ column = Tabl::Column.new(:foo)
12
+ column.value(foo).should == 'foo'
13
+ end
14
+
15
+ it 'should allow setting the label' do
16
+ column = Tabl::Column.new(:foo)
17
+ column.label = 'Bar'
18
+ column.label.should == 'Bar'
19
+ end
20
+
21
+ it 'should allow overriding the value function' do
22
+ foo = OpenStruct.new(:bar => 'bar')
23
+ column = Tabl::Column.new(:foo)
24
+ column.value = lambda { |foo| foo.bar }
25
+ column.value(foo).should == 'bar'
26
+ end
27
+
28
+ it 'should allow setting the format' do
29
+ foo = OpenStruct.new(:foo => 'foo')
30
+ column = Tabl::Column.new(:foo)
31
+ column.format.html = lambda { |v| v.upcase }
32
+ column.format.html('foo', foo).should == 'FOO'
33
+ end
34
+
35
+ it 'should yield a configuration block' do
36
+ column = Tabl::Column.new(:foo) do |config|
37
+ config.label = 'Foo'
38
+ config.value = lambda { |foo| foo.bar }
39
+ config.format.html = lambda { |v| v.upcase }
40
+ end
41
+
42
+ foo = OpenStruct.new(:bar => 'bar')
43
+
44
+ column.label.should == 'Foo'
45
+ column.value(foo).should == 'bar'
46
+ column.format.html('bar').should == 'BAR'
47
+ end
48
+ end
49
+
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+
3
+ describe Tabl::DerefColumn do
4
+ before do
5
+ @column = Tabl::Column.new(:foo)
6
+ @deref_column = Tabl::DerefColumn.new(@column, :bar)
7
+ @bar = OpenStruct.new(:bar => OpenStruct.new(:foo => 'foo'))
8
+ end
9
+
10
+ it 'should dereference the object' do
11
+ @deref_column.value(@bar).should == 'foo'
12
+ end
13
+
14
+ it 'should delegate the label' do
15
+ @column.label = 'FOO'
16
+ @deref_column.label.should == 'FOO'
17
+ end
18
+
19
+ it 'should delegate the value' do
20
+ @column.value = lambda { |o| o.foo.upcase }
21
+ @deref_column.value(@bar).should == 'FOO'
22
+ end
23
+ end
24
+
@@ -0,0 +1,67 @@
1
+ require 'spec_helper'
2
+
3
+ describe Tabl::Dsl do
4
+ before do
5
+ @module = Module.new
6
+ @module.send(:include, Tabl::Dsl)
7
+ end
8
+
9
+ it 'should define a column method' do
10
+ @module.should respond_to(:column)
11
+ end
12
+
13
+ it 'should define a table method' do
14
+ @module.should respond_to(:table)
15
+ end
16
+
17
+ it 'should define a columns method' do
18
+ @module.should respond_to(:columns)
19
+ end
20
+
21
+ it 'should define a tables method' do
22
+ @module.should respond_to(:tables)
23
+ end
24
+
25
+ it 'should define columns' do
26
+ @module.column :foo
27
+ @module.columns[0].name.should == :foo
28
+ end
29
+
30
+ it 'should define an include_columns method' do
31
+ @module.should respond_to(:include_columns)
32
+ end
33
+
34
+ describe '.table' do
35
+ it 'should define a table' do
36
+ @module.table :foo
37
+ @module.foo.should be_a(Tabl::Table)
38
+ end
39
+
40
+ it 'should set base columns' do
41
+ @module.column :foo
42
+
43
+ @module.table :foo
44
+ @module.foo.base_columns.should == @module.columns
45
+ end
46
+ end
47
+
48
+ describe '.include_columns' do
49
+ before do
50
+ @columns_mod = Module.new
51
+ @columns_mod.send(:include, Tabl::Dsl)
52
+ @columns_mod.column(:foo)
53
+ end
54
+
55
+ it 'should include columns' do
56
+ @module.include_columns @columns_mod
57
+ @module.columns.should == @columns_mod.columns
58
+ end
59
+
60
+ it 'should take a a deref parameter' do
61
+ @module.include_columns @columns_mod, :record => :bar
62
+ @module.columns[0].should be_a Tabl::DerefColumn
63
+ @module.columns[0].column.should == @columns_mod.columns[0]
64
+ end
65
+ end
66
+ end
67
+
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+
3
+ describe Tabl::Formats::Html do
4
+ it 'should register under :html' do
5
+ Tabl::Formats.html.should == Tabl::Formats::Html
6
+ end
7
+
8
+ it 'should escape html' do
9
+ Tabl::Formats::Html.format('<').should == '&lt;'
10
+ end
11
+ end
@@ -0,0 +1,52 @@
1
+ require 'spec_helper'
2
+
3
+ describe Tabl::Table do
4
+ it 'should yield a configure block' do
5
+ yielded = false
6
+ table = Tabl::Table.new do |config|
7
+ yielded = true
8
+ end
9
+ yielded.should == true
10
+ end
11
+
12
+ it 'should return labels' do
13
+ table = Tabl::Table.new do |config|
14
+ config.columns = [ :user, :email, :phone_number ]
15
+ end
16
+ table.labels.should == ['User', 'Email', 'Phone Number']
17
+ end
18
+
19
+ it 'should return values' do
20
+ table = Tabl::Table.new do |config|
21
+ config.columns = [ :user, :email, :phone_number ]
22
+ end
23
+ user = OpenStruct.new(:user => 'fred', :email => 'fred@foo.com', :phone_number => '12345678')
24
+ table.values(user).should == ['fred', 'fred@foo.com', '12345678']
25
+ end
26
+
27
+ it 'should format values' do
28
+ table = Tabl::Table.new do |config|
29
+ config.columns = [ :user, :email, :phone_number ]
30
+ end
31
+ user = OpenStruct.new(:user => '<>', :email => 'fred@foo.com', :phone_number => '12345678')
32
+ table.html.values(user).should == ['&lt;&gt;', 'fred@foo.com', '12345678']
33
+ end
34
+
35
+ it 'should override formats' do
36
+ table = Tabl::Table.new do |config|
37
+ config.columns = [ :user, :email, :phone_number ]
38
+ config.email.format.html = lambda { |v| v.upcase }
39
+ end
40
+ user = OpenStruct.new(:user => '<>', :email => 'fred@foo.com', :phone_number => '12345678')
41
+ table.html.values(user).should == ['&lt;&gt;', 'FRED@FOO.COM', '12345678']
42
+ end
43
+
44
+ it 'should have base columns' do
45
+ base_columns = [ Tabl::Column.new(:foo, :value => lambda { |record| record.foo.bar }) ]
46
+ table = Tabl::Table.new(:base_columns => base_columns, :columns => [:foo])
47
+ foo = OpenStruct.new(:foo => OpenStruct.new(:bar => 'bar'))
48
+ table.values(foo).should == ['bar']
49
+ end
50
+ end
51
+
52
+
data/tabl.gemspec ADDED
@@ -0,0 +1,84 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{tabl}
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = [%q{Liehann Loots}]
12
+ s.date = %q{2011-09-16}
13
+ s.description = %q{Gem for creating tables in Rails or any other system.}
14
+ s.email = %q{liehannl@gmail.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE.txt",
17
+ "README.md"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".rspec",
22
+ "Gemfile",
23
+ "Gemfile.lock",
24
+ "Guardfile",
25
+ "LICENSE.txt",
26
+ "README.md",
27
+ "Rakefile",
28
+ "VERSION",
29
+ "lib/tabl.rb",
30
+ "lib/tabl/column.rb",
31
+ "lib/tabl/definition.rb",
32
+ "lib/tabl/deref_column.rb",
33
+ "lib/tabl/dsl.rb",
34
+ "lib/tabl/formats.rb",
35
+ "lib/tabl/formats/html.rb",
36
+ "lib/tabl/table.rb",
37
+ "spec/integration_spec.rb",
38
+ "spec/lib/post_tables.rb",
39
+ "spec/lib/user_columns.rb",
40
+ "spec/spec_helper.rb",
41
+ "spec/tabl/column_spec.rb",
42
+ "spec/tabl/deref_column_spec.rb",
43
+ "spec/tabl/dsl_spec.rb",
44
+ "spec/tabl/formats/html_spec.rb",
45
+ "spec/tabl/table_spec.rb",
46
+ "tabl.gemspec"
47
+ ]
48
+ s.homepage = %q{http://github.com/liehann/tabl}
49
+ s.licenses = [%q{MIT}]
50
+ s.require_paths = [%q{lib}]
51
+ s.rubygems_version = %q{1.8.6}
52
+ s.summary = %q{Gem for creating tables in Rails or any other system.}
53
+
54
+ if s.respond_to? :specification_version then
55
+ s.specification_version = 3
56
+
57
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
58
+ s.add_runtime_dependency(%q<activesupport>, [">= 0"])
59
+ s.add_runtime_dependency(%q<fastercsv>, [">= 0"])
60
+ s.add_development_dependency(%q<rspec>, ["~> 2.6.0"])
61
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
62
+ s.add_development_dependency(%q<jeweler>, ["~> 1.6.4"])
63
+ s.add_development_dependency(%q<libnotify>, [">= 0"])
64
+ s.add_development_dependency(%q<guard-rspec>, [">= 0"])
65
+ else
66
+ s.add_dependency(%q<activesupport>, [">= 0"])
67
+ s.add_dependency(%q<fastercsv>, [">= 0"])
68
+ s.add_dependency(%q<rspec>, ["~> 2.6.0"])
69
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
70
+ s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
71
+ s.add_dependency(%q<libnotify>, [">= 0"])
72
+ s.add_dependency(%q<guard-rspec>, [">= 0"])
73
+ end
74
+ else
75
+ s.add_dependency(%q<activesupport>, [">= 0"])
76
+ s.add_dependency(%q<fastercsv>, [">= 0"])
77
+ s.add_dependency(%q<rspec>, ["~> 2.6.0"])
78
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
79
+ s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
80
+ s.add_dependency(%q<libnotify>, [">= 0"])
81
+ s.add_dependency(%q<guard-rspec>, [">= 0"])
82
+ end
83
+ end
84
+
metadata ADDED
@@ -0,0 +1,195 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tabl
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Liehann Loots
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-09-16 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ type: :runtime
22
+ requirement: &id001 !ruby/object:Gem::Requirement
23
+ none: false
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ hash: 3
28
+ segments:
29
+ - 0
30
+ version: "0"
31
+ version_requirements: *id001
32
+ name: activesupport
33
+ prerelease: false
34
+ - !ruby/object:Gem::Dependency
35
+ type: :runtime
36
+ requirement: &id002 !ruby/object:Gem::Requirement
37
+ none: false
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ hash: 3
42
+ segments:
43
+ - 0
44
+ version: "0"
45
+ version_requirements: *id002
46
+ name: fastercsv
47
+ prerelease: false
48
+ - !ruby/object:Gem::Dependency
49
+ type: :development
50
+ requirement: &id003 !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ~>
54
+ - !ruby/object:Gem::Version
55
+ hash: 23
56
+ segments:
57
+ - 2
58
+ - 6
59
+ - 0
60
+ version: 2.6.0
61
+ version_requirements: *id003
62
+ name: rspec
63
+ prerelease: false
64
+ - !ruby/object:Gem::Dependency
65
+ type: :development
66
+ requirement: &id004 !ruby/object:Gem::Requirement
67
+ none: false
68
+ requirements:
69
+ - - ~>
70
+ - !ruby/object:Gem::Version
71
+ hash: 23
72
+ segments:
73
+ - 1
74
+ - 0
75
+ - 0
76
+ version: 1.0.0
77
+ version_requirements: *id004
78
+ name: bundler
79
+ prerelease: false
80
+ - !ruby/object:Gem::Dependency
81
+ type: :development
82
+ requirement: &id005 !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ~>
86
+ - !ruby/object:Gem::Version
87
+ hash: 7
88
+ segments:
89
+ - 1
90
+ - 6
91
+ - 4
92
+ version: 1.6.4
93
+ version_requirements: *id005
94
+ name: jeweler
95
+ prerelease: false
96
+ - !ruby/object:Gem::Dependency
97
+ type: :development
98
+ requirement: &id006 !ruby/object:Gem::Requirement
99
+ none: false
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ hash: 3
104
+ segments:
105
+ - 0
106
+ version: "0"
107
+ version_requirements: *id006
108
+ name: libnotify
109
+ prerelease: false
110
+ - !ruby/object:Gem::Dependency
111
+ type: :development
112
+ requirement: &id007 !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ hash: 3
118
+ segments:
119
+ - 0
120
+ version: "0"
121
+ version_requirements: *id007
122
+ name: guard-rspec
123
+ prerelease: false
124
+ description: Gem for creating tables in Rails or any other system.
125
+ email: liehannl@gmail.com
126
+ executables: []
127
+
128
+ extensions: []
129
+
130
+ extra_rdoc_files:
131
+ - LICENSE.txt
132
+ - README.md
133
+ files:
134
+ - .document
135
+ - .rspec
136
+ - Gemfile
137
+ - Gemfile.lock
138
+ - Guardfile
139
+ - LICENSE.txt
140
+ - README.md
141
+ - Rakefile
142
+ - VERSION
143
+ - lib/tabl.rb
144
+ - lib/tabl/column.rb
145
+ - lib/tabl/definition.rb
146
+ - lib/tabl/deref_column.rb
147
+ - lib/tabl/dsl.rb
148
+ - lib/tabl/formats.rb
149
+ - lib/tabl/formats/html.rb
150
+ - lib/tabl/table.rb
151
+ - spec/integration_spec.rb
152
+ - spec/lib/post_tables.rb
153
+ - spec/lib/user_columns.rb
154
+ - spec/spec_helper.rb
155
+ - spec/tabl/column_spec.rb
156
+ - spec/tabl/deref_column_spec.rb
157
+ - spec/tabl/dsl_spec.rb
158
+ - spec/tabl/formats/html_spec.rb
159
+ - spec/tabl/table_spec.rb
160
+ - tabl.gemspec
161
+ homepage: http://github.com/liehann/tabl
162
+ licenses:
163
+ - MIT
164
+ post_install_message:
165
+ rdoc_options: []
166
+
167
+ require_paths:
168
+ - lib
169
+ required_ruby_version: !ruby/object:Gem::Requirement
170
+ none: false
171
+ requirements:
172
+ - - ">="
173
+ - !ruby/object:Gem::Version
174
+ hash: 3
175
+ segments:
176
+ - 0
177
+ version: "0"
178
+ required_rubygems_version: !ruby/object:Gem::Requirement
179
+ none: false
180
+ requirements:
181
+ - - ">="
182
+ - !ruby/object:Gem::Version
183
+ hash: 3
184
+ segments:
185
+ - 0
186
+ version: "0"
187
+ requirements: []
188
+
189
+ rubyforge_project:
190
+ rubygems_version: 1.8.6
191
+ signing_key:
192
+ specification_version: 3
193
+ summary: Gem for creating tables in Rails or any other system.
194
+ test_files: []
195
+