tabl 0.1.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.
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
+