cheveret 1.1.3 → 2.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2010 RateCity
1
+ Copyright (c) 2010 RateCity Pty. Ltd.
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/Rakefile CHANGED
@@ -1,6 +1,8 @@
1
1
  require 'rubygems'
2
2
  require 'rake'
3
3
 
4
+ require File.expand_path('../lib/cheveret/version', __FILE__)
5
+
4
6
  begin
5
7
  require 'jeweler'
6
8
  Jeweler::Tasks.new do |gem|
@@ -12,8 +14,9 @@ clearly separate logic and templating and reduce the amount of code in your view
12
14
  gem.email = "aulankz@gmail.com"
13
15
  gem.homepage = "http://github.com/ratecity/cheveret"
14
16
  gem.authors = ["Ben Caldwell"]
17
+ gem.version = Cheveret::VERSION::STRING
18
+
15
19
  gem.add_development_dependency "rspec", ">= 1.2.9"
16
- # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
17
20
  end
18
21
  Jeweler::GemcutterTasks.new
19
22
  rescue LoadError
data/cheveret.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{cheveret}
8
- s.version = "1.1.3"
8
+ s.version = "2.0.0.rc1"
9
9
 
10
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
10
+ s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Ben Caldwell"]
12
- s.date = %q{2010-09-21}
12
+ s.date = %q{2010-09-29}
13
13
  s.description = %q{Generating HTML tables of data in the views of your Rails
14
14
  application is not very DRY even for the simpler of cases. Cheveret allows you to more
15
15
  clearly separate logic and templating and reduce the amount of code in your views.}
@@ -24,10 +24,18 @@ clearly separate logic and templating and reduce the amount of code in your view
24
24
  "LICENSE",
25
25
  "README.md",
26
26
  "Rakefile",
27
- "VERSION",
28
27
  "cheveret.gemspec",
29
28
  "init.rb",
30
29
  "lib/cheveret.rb",
30
+ "lib/cheveret/base.rb",
31
+ "lib/cheveret/column.rb",
32
+ "lib/cheveret/config.rb",
33
+ "lib/cheveret/dsl.rb",
34
+ "lib/cheveret/filtering.rb",
35
+ "lib/cheveret/helper.rb",
36
+ "lib/cheveret/rendering.rb",
37
+ "lib/cheveret/resizing.rb",
38
+ "lib/cheveret/version.rb",
31
39
  "rails/init.rb",
32
40
  "spec/cheveret_spec.rb",
33
41
  "spec/spec.opts",
data/init.rb CHANGED
@@ -1,2 +1,2 @@
1
1
  require 'cheveret'
2
- ActionView::Base.send :include, Cheveret::Helpers
2
+ ActionView::Base.send :include, Cheveret::Helper
data/lib/cheveret.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2010 RateCity
2
+ # Copyright (c) 2010 RateCity Pty. Ltd.
3
3
  #
4
4
  # Permission is hereby granted, free of charge, to any person obtaining
5
5
  # a copy of this software and associated documentation files (the
@@ -21,262 +21,14 @@
21
21
  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
22
  #++
23
23
 
24
- require 'forwardable'
25
-
26
24
  module Cheveret
27
- class Table
28
- attr_accessor :columns
29
-
30
- def initialize(&block)
31
- @columns = ::ActiveSupport::OrderedHash.new
32
- yield self if block_given?
33
- end
34
-
35
- def columns(*args, &block)
36
- return @columns.values unless block_given?
37
- instance_eval(&block)
38
- # todo: support populating columns from an array
39
- # todo: attempt to automatically resolve columns from activerecord etc.
40
- end
41
-
42
- def add_column(column_name, config={})
43
- @columns[column_name] = Column.new(column_name, config)
44
- end
45
-
46
- alias_method :column, :add_column
47
-
48
- def fixed(column_name, config={})
49
- add_column(column_name, config.merge({ :flexible => false }))
50
- end
51
-
52
- def flexible(column_name, config={})
53
- add_column(column_name, config.merge({ :flexible => true }))
54
- end
55
-
56
- def hidden(column_name, config={})
57
- add_column(column_name, config.merge({ :visible => false }))
58
- end
59
-
60
- def remove_column(column_name)
61
- # todo: allow columns to be removed, not sure why you'd want to do this. maybe
62
- # just set :visible => false instead?
63
- raise NotImplementedError
64
- end
65
-
66
- def resize!(new_width)
67
- return true if new_width == @width
68
- @width = new_width
69
-
70
- columns_width = 0
71
- flexibles = []
72
-
73
- self.columns.each do |column|
74
- if column.visible?
75
- columns_width += column.width
76
- flexibles << column.name if column.flexible?
77
- end
78
- end
79
-
80
- # todo: handle too-many/too-wide columns
81
- raise "uh-oh spaghettio-s" if columns_width > new_width
82
-
83
- # todo: fix rounding in with calculation
84
- # todo: trim last column that fits into table width if necessary
85
- if columns_width < new_width && !flexibles.empty?
86
- padding = (new_width - columns_width) / flexibles.length
87
- flexibles.each { |name| @columns[name].width += padding }
88
- end
89
- end
90
- end
91
-
92
- class Column
93
- extend ::Forwardable
94
-
95
- [ :width, :visible, :flexible, :label, :sortable ].each do |attr|
96
- class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
97
- def_delegator :@config, :#{attr}, :#{attr}
98
- def_delegator :@config, :#{attr}=, :#{attr}=
99
- RUBY_EVAL
100
- end
101
-
102
- attr_accessor :name
103
-
104
- def initialize(column_name, config={})
105
- @name = column_name
106
-
107
- @config = ::ActiveSupport::OrderedOptions.new
108
- config.each { |k, v| send("#{k}=", v) if respond_to?(k) }
109
- end
110
-
111
- # sets the column to be visible. columns are visible by default. use this when
112
- # you've defined hidden columns that should only be displayed on some condition
113
- def show
114
- self.visible = true
115
- end
116
-
117
- # hides the column, prevents it from being rendered in the table. acts as a
118
- # helper for setting <tt>:visible => false</tt>
119
- def hide
120
- self.visible = false
121
- end
122
-
123
- # returns +true+ for columns that have <tt>:visible => true</tt> or #show called
124
- # on them. columns are visible by default
125
- def visible?
126
- self.visible != false
127
- end
128
-
129
- def flexible?
130
- self.flexible != false
131
- end
132
-
133
- # returns +true+ unless a column has explicitly set <tt>:sortable => false</tt>
134
- def sortable?
135
- self.sortable != false
136
- end
137
-
138
- def label
139
- case @config.label
140
- when nil then @name.to_s.humanize # todo: support i18n for column labels
141
- when false then nil
142
- else @config.label
143
- end
144
- end
145
-
146
- def data(object)
147
- object.send(self.name) if object.respond_to?(self.name)
148
- end
149
-
150
- def width
151
- @config.width || 0
152
- end
153
- end
154
-
155
- module Helpers
156
- # view helper that facilities the rendering of tables for a collection of similar
157
- # objects
158
- #
159
- # behaves much in the same way as Rails +form_for+ helper in that it takes a proc
160
- # and provides access to a table builder object. the entire block is captured, so
161
- # additional markup can be output at any point
162
- #
163
- # <% table_for @books, :width => 480 do |t| %>
164
- # <% t.columns :title, :author, :publisher, :price %>
165
- # <% t.header %>
166
- # <% t.body %>
167
- # <% end %>
168
- #
169
- # === Options
170
- # * <tt>:width</tt> - the total width of the table in pixels
171
- # * <tt>:html</tt> - a hash of html attributes used for the form container
172
- # * <tt>:url</tt> - used to generate urls for sortable columns
173
- # * <tt>:table</tt> - specify a pre-configured table to render
174
- #
175
- # === Examples
176
- def table_for(collection, options={}, &block)
177
- builder = options.delete(:builder) || ActionView::Base.default_table_builder
178
- table = options.delete(:table) || Table.new
179
-
180
- options.merge!({ :collection => collection })
181
- builder.render(table, self, options, &block)
182
- end
183
-
184
- # the default #TableBuilder class generates an HTML table using div tags
185
- class TableBuilder
186
- extend ::Forwardable
187
- def_delegators :@table, :columns
188
-
189
- def self.render(table, template, options={}, &block)
190
- html_attrs = options.delete(:html) || {}
191
- html_attrs.merge!({ :class => "table",
192
- :style => "width: #{options[:width]}px;" })
193
-
194
- template.content_tag(:div, html_attrs) do
195
- template.capture(self.new(table, template, options), &block)
196
- end
197
- end
198
-
199
- def initialize(table, template, options={})
200
- @table, @template, = table, template
201
-
202
- @width = options.delete(:width)
203
- @collection = options.delete(:collection)
204
- @url = options.delete(:url)
205
- end
206
-
207
- def header(*args, &block)
208
- @table.resize!(@width)
209
-
210
- row = content_tag(:div, :class => "tr") do
211
- map_columns(:th) do |column|
212
- # todo: prevent output of empty <a> tag for header label
213
- output = nil_capture(column, &block) if block_given?
214
- output ||= sort_tag(column) if column.sortable?
215
- output ||= content_tag(:span, column.label)
216
- end
217
- end
218
-
219
- content_tag(:div, row, :class => "thead")
220
- end
221
-
222
- def body(&block)
223
- @table.resize!(@width)
224
- alt = false
225
-
226
- rows = @collection.map do |object|
227
- object_name = object.class.to_s.split('::').last.underscore || ''
228
- klass = [ 'tr', object_name, (alt = !alt) ? nil : 'alt' ].compact
229
- content_tag(:div, :class => klass.join(' ')) do
230
- map_columns(:td) do |column|
231
- output = nil_capture(column, object, &block) if block_given?
232
- output ||= content_tag(:span, column.data(object))
233
- end
234
- end
235
- end
236
-
237
- content_tag(:div, rows.join, :class => "tbody")
238
- end
239
-
240
- private
241
-
242
- def map_columns(type, &block) #:nodoc:
243
- @table.columns.map do |column|
244
- attrs = { :class => [type, column.name].join(' '),
245
- :style => "width: #{column.width}px;" }
246
- attrs[:class] << ' sortable' if column.sortable?
247
-
248
- content_tag(:div, attrs) do
249
- yield(column)
250
- end if column.visible?
251
- end
252
- end
253
-
254
- def nil_capture(*args, &block) #:nodoc:
255
- custom = capture(*args, &block).strip
256
- output = custom.empty? ? nil : custom
257
- end
258
-
259
- def sort_tag(column) #:nodoc:
260
- return nil unless column.sortable? && @url.present?
261
-
262
- sort = column.name
263
- order = "desc" if params[:sort].to_s == column.name.to_s && params[:order] == "asc"
264
- attrs = { :href => url_for(@url.merge({ :sort => sort, :order => order || "desc" })) }
265
-
266
- attrs[:class] = "sorted #{params[:order]}" if params[:sort].to_s == column.name.to_s
267
-
268
- content_tag(:a, column.label, attrs)
269
- end
270
-
271
- def method_missing(method_name, *args, &block) #:nodoc:
272
- return @template.send(method_name, *args, &block) if @template.respond_to?(method_name)
273
- super
274
- end
275
- end
276
- end
25
+ autoload :Base, 'cheveret/base'
26
+ autoload :Column, 'cheveret/column'
27
+ autoload :Config, 'cheveret/config'
28
+ autoload :DSL, 'cheveret/dsl'
29
+ autoload :Filtering, 'cheveret/filtering'
30
+ autoload :Helper, 'cheveret/helper'
31
+ autoload :Rendering, 'cheveret/rendering'
32
+ autoload :Resizing, 'cheveret/resizing'
277
33
 
278
- ActionView::Base.class_eval do
279
- cattr_accessor :default_table_builder
280
- self.default_table_builder = ::Cheveret::Helpers::TableBuilder
281
- end
282
34
  end
@@ -0,0 +1,57 @@
1
+ #--
2
+ # Copyright (c) 2010 RateCity Pty. Ltd.
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #++
23
+
24
+ require 'active_support/ordered_hash'
25
+
26
+ module Cheveret
27
+ class Base
28
+ attr_accessor :columns
29
+
30
+ def initialize(template, &block)
31
+ @template = template
32
+ @columns = ::ActiveSupport::OrderedHash.new
33
+
34
+ instance_eval(&block) if block_given?
35
+ end
36
+
37
+ include DSL
38
+ include Rendering
39
+ include Config
40
+ include Resizing
41
+ include Filtering
42
+ # include Sorting
43
+
44
+ protected
45
+
46
+ # since the define_table block gets instance_eval'd in the context of this object
47
+ # we need to proxy view methods (e.g. check_box_tag) back to the template
48
+ def method_missing(method_name, *args, &block) #:nodoc:
49
+ if @template.respond_to?(method_name)
50
+ @template.send(method_name, *args, &block)
51
+ else
52
+ super
53
+ end
54
+ end
55
+
56
+ end
57
+ end
@@ -0,0 +1,57 @@
1
+ #--
2
+ # Copyright (c) 2010 RateCity Pty. Ltd.
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #++
23
+
24
+ module Cheveret
25
+ class Column
26
+ attr_accessor :name, :data, :label, :weight, :width
27
+ attr_accessor :flexible, :sortable
28
+
29
+ def initialize(name, config={})
30
+ config.merge(:name => name).each do |k, v|
31
+ instance_variable_set(:"@#{k}", v) if respond_to?(:"#{k}=")
32
+ end
33
+ end
34
+
35
+ def flexible?
36
+ @flexible == true
37
+ end
38
+
39
+ def label
40
+ case @label
41
+ when nil then @name.to_s.humanize # todo: support i18n for column labels
42
+ when false then nil
43
+ else @label
44
+ end
45
+ end
46
+
47
+ # returns +true+ unless a column has explicitly set <tt>:sortable => false</tt>
48
+ def sortable?
49
+ @sortable == true
50
+ end
51
+
52
+ def width
53
+ @width || 0
54
+ end
55
+
56
+ end
57
+ end
@@ -0,0 +1,44 @@
1
+ #--
2
+ # Copyright (c) 2010 RateCity Pty. Ltd.
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #++
23
+
24
+ module Cheveret
25
+ module Config
26
+ # dsl method for defining default configuration options for table rendering
27
+ #
28
+ # @param [Hash] new_config
29
+ # a hash of configuration options. gets merged with any existing config
30
+ def config(new_config)
31
+ if @config then @config.merge!(new_config) else @config = new_config.dup end
32
+ end
33
+
34
+ [ :render, :header, :body, :rows ].each do |renderer|
35
+ class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
36
+ def #{renderer}(*args)
37
+ config = @config.merge(args.extract_options!)
38
+ super(*args << config)
39
+ end
40
+ RUBY_EVAL
41
+ end
42
+
43
+ end
44
+ end
@@ -0,0 +1,124 @@
1
+ #--
2
+ # Copyright (c) 2010 RateCity Pty. Ltd.
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #++
23
+
24
+ module Cheveret
25
+ module DSL
26
+ def header_default(&block)
27
+ raise NotImplementedError
28
+ end
29
+
30
+ def data_default(&block)
31
+ raise NotImplementedError
32
+ end
33
+
34
+ # registers a new column with the specified options
35
+ #
36
+ # @example minimum required to define a column
37
+ # column :author
38
+ #
39
+ # @example flexible width, sortable column
40
+ # column :description => [ :flexible, :sortable ]
41
+ #
42
+ # @example fixed with column with no header label
43
+ # column :check_box, :label => false, :width => 30
44
+ #
45
+ # @example sortable column with custom header label
46
+ # column :published => [ :sortable ], :label => "Publish Date"
47
+ #
48
+ # @param [Symbol,Array] name_or_hash
49
+ # the name of the column, optionally combined with any flags that should be
50
+ # set to +true+
51
+ #
52
+ # @param [Hash] options a hash of options for the column
53
+ #
54
+ # @option options [Proc] :data
55
+ #
56
+ # @option options [Boolean] :flexible (false)
57
+ # if +true+ the column will resize automatically depending on the size of the
58
+ # table
59
+ #
60
+ # @option options [Proc] :header
61
+ #
62
+ # @option options [String,Boolean] :label
63
+ # used to determine what gets used as a label in the column header. if set to
64
+ # +false+ no lable will be rendered
65
+ #
66
+ # @option options [Boolean] :sortable (false)
67
+ #
68
+ # @option options [Integer] :width
69
+ def column(name_or_hash, options={})
70
+ if name_or_hash.is_a?(Hash)
71
+ name = name_or_hash.except(:label, :width).keys.first
72
+ name_or_hash.delete(name).each { |k| options[k] = true }
73
+ options.merge!(name_or_hash)
74
+ else
75
+ name = name_or_hash
76
+ end
77
+
78
+ if @columns[name].present?
79
+ options.each { |k, v| @column[name].send(:"#{k}=", v) }
80
+ else
81
+ @columns[name] = Column.new(name, options)
82
+ end
83
+ end
84
+
85
+ # define how to extract and render data value for a particular column
86
+ #
87
+ # chevert will call the block you define here to render the inner part of the
88
+ # table data cell for each object in the collection
89
+ #
90
+ # if you don't specify one or more column names when calling this method,
91
+ # cheveret will assume that you're defining the data block for the last column
92
+ # you registered
93
+ #
94
+ # @example format money values in the view
95
+ # - column :price
96
+ # - data do |book|
97
+ # %span= number_to_currency book.price
98
+ #
99
+ # @example define data block for multiple columns
100
+ # - column :title
101
+ # - column :author
102
+ # - data [ :title, :author ] do |column, object|
103
+ # %p{ :class => column.name }= object.send(column.name)
104
+ def data(*args, &block)
105
+ options = args.extract_options!
106
+
107
+ [ *args.first || @columns.keys.last ].each do |column_name|
108
+ column = @columns[column_name ]
109
+ column.data = block
110
+
111
+ instance_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
112
+ def data_for_#{column.name}(object)
113
+ capture(object, &@columns[:#{column.name}].data)
114
+ end
115
+ RUBY_EVAL
116
+ end
117
+ end
118
+
119
+ def header(*args, &block)
120
+ raise NotImplementedError
121
+ end
122
+
123
+ end
124
+ end
@@ -0,0 +1,39 @@
1
+ #--
2
+ # Copyright (c) 2010 RateCity Pty. Ltd.
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #++
23
+
24
+ module Cheveret
25
+ module Filtering
26
+ def config(new_config)
27
+ except, only = new_config[:except], new_config[:only]
28
+ if (except || only)
29
+ @columns.reject! { |k, v| !only.include?(k) } if only
30
+ # todo: support use of except
31
+ end
32
+
33
+ super
34
+ end
35
+
36
+ # todo: wrap around header, body, rows and allow localised :only and :except
37
+
38
+ end
39
+ end
@@ -0,0 +1,37 @@
1
+ #--
2
+ # Copyright (c) 2010 RateCity Pty. Ltd.
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #++
23
+
24
+ module Cheveret
25
+ module Helper
26
+ def define_table(options={}, &block)
27
+ builder = options.delete(:builder) || ActionView::Base.default_table_builder
28
+ builder.new(self, &block)
29
+ end
30
+
31
+ ActionView::Base.class_eval do
32
+ cattr_accessor :default_table_builder
33
+ self.default_table_builder = Cheveret::Base
34
+ end
35
+
36
+ end
37
+ end
@@ -0,0 +1,83 @@
1
+ #--
2
+ # Copyright (c) 2010 RateCity Pty. Ltd.
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #++
23
+
24
+ module Cheveret
25
+ module Rendering
26
+ def render(collection, options={})
27
+ options[:class] = [ 'table', options[:class] ].flatten.join(' ').strip
28
+
29
+ content_tag(:div, options) do
30
+ header + body(collection)
31
+ end
32
+ end
33
+
34
+ def header(options={})
35
+ row = @columns.values.map do |column|
36
+ cell(:th, column) do
37
+ if column.sortable?
38
+ content_tag(:a, column.label)
39
+ else
40
+ column.label
41
+ end
42
+ end
43
+ end
44
+
45
+ content_tag(:div, row, {
46
+ :class => 'thead'
47
+ })
48
+ end
49
+
50
+ def body(collection, options={})
51
+ content_tag(:div, rows(collection), {
52
+ :class => 'tbody'
53
+ })
54
+ end
55
+
56
+ def rows(collection, options={})
57
+ collection.map { |object| row(object) }.join
58
+ end
59
+
60
+ # render a single table row for the specified data object
61
+ #
62
+ # @param [Object] object
63
+ # @param [Hash] options
64
+ #
65
+ # @option options [Array] :only
66
+ # @option options [Array] :except
67
+ # @option options [Array,String] :class
68
+ # @option options [Integer] :width
69
+ def row(object, options={})
70
+ content_tag(:div, :class => 'tr') do
71
+ @columns.values.map do |column|
72
+ cell(:td, column) { send(:"data_for_#{column.name}", object) rescue nil }
73
+ end
74
+ end
75
+ end
76
+
77
+ def cell(type, column, options={}, &block)
78
+ options[:class] = [ type, column.name, options[:class] ].flatten.join(' ').strip
79
+ content_tag(:div, yield, options)
80
+ end
81
+
82
+ end
83
+ end
@@ -0,0 +1,95 @@
1
+ #--
2
+ # Copyright (c) 2010 RateCity Pty. Ltd.
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #++
23
+
24
+ module Cheveret
25
+ module Resizing
26
+ def width
27
+ @width || 0
28
+ end
29
+
30
+ # set width constraint for the table.
31
+ #
32
+ # if the width value is different to that previously set, cheveret will call the
33
+ # #resize! method to adjust the widths of flexible columns to fit
34
+ #
35
+ # @param [Integer] new_width the maximum width of the table in pixels
36
+ def width=(new_width)
37
+ return @width if new_width == @width
38
+
39
+ @width = new_width
40
+ resize!
41
+ end
42
+
43
+ def config(new_config={})
44
+ self.width = new_config[:width] if new_config[:width]
45
+ super
46
+ end
47
+
48
+ # some meta magic - make sure that the table is resized correctly before any of
49
+ # the render methods start generating output
50
+ [ :render, :header, :body, :rows ].each do |renderer|
51
+ class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
52
+ def #{renderer}(*args)
53
+ config = args.extract_options!
54
+
55
+ width = config.delete(:width)
56
+ super(*args << config)
57
+ end
58
+ RUBY_EVAL
59
+ end
60
+
61
+ def cell(type, column, options={}, &block)
62
+ options[:style] = "width: #{@widths[column.name] || column.width}px"
63
+ super
64
+ end
65
+
66
+ # resize flexible columns in attempt to reduce the total width, making sure it
67
+ # fits within the constraints of the table
68
+ def resize!
69
+ @widths = {}
70
+
71
+ columns_width = 0
72
+ flexibles = []
73
+
74
+ @columns.values.each do |column|
75
+ columns_width += column.width
76
+ flexibles << column if column.flexible?
77
+ end
78
+
79
+ # todo: handle too-many/too-wide columns
80
+ raise "uh-oh spaghettio-s" if columns_width > @width
81
+
82
+ # todo: fix rounding in with calculation
83
+ # todo: trim last column that fits into table width if necessary
84
+ if columns_width < @width && !flexibles.empty?
85
+ padding = (@width - columns_width) / flexibles.length
86
+ flexibles.each { |column| @widths[column.name] = column.width + padding }
87
+ end
88
+ end
89
+
90
+ def weigh!
91
+ raise NotImplementedError
92
+ end
93
+
94
+ end
95
+ end
@@ -0,0 +1,33 @@
1
+ #--
2
+ # Copyright (c) 2010 RateCity Pty. Ltd.
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #++
23
+
24
+ module Cheveret
25
+ module VERSION
26
+ MAJOR = 2
27
+ MINOR = 0
28
+ PATCH = 0
29
+ BUILD = 'rc1'
30
+
31
+ STRING = [ MAJOR, MINOR, PATCH, BUILD ].join('.')
32
+ end
33
+ end
metadata CHANGED
@@ -1,13 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cheveret
3
3
  version: !ruby/object:Gem::Version
4
- hash: 21
5
- prerelease: false
4
+ hash: 977940590
5
+ prerelease: true
6
6
  segments:
7
- - 1
8
- - 1
9
- - 3
10
- version: 1.1.3
7
+ - 2
8
+ - 0
9
+ - 0
10
+ - rc1
11
+ version: 2.0.0.rc1
11
12
  platform: ruby
12
13
  authors:
13
14
  - Ben Caldwell
@@ -15,7 +16,7 @@ autorequire:
15
16
  bindir: bin
16
17
  cert_chain: []
17
18
 
18
- date: 2010-09-21 00:00:00 +10:00
19
+ date: 2010-09-29 00:00:00 +10:00
19
20
  default_executable:
20
21
  dependencies:
21
22
  - !ruby/object:Gem::Dependency
@@ -52,10 +53,18 @@ files:
52
53
  - LICENSE
53
54
  - README.md
54
55
  - Rakefile
55
- - VERSION
56
56
  - cheveret.gemspec
57
57
  - init.rb
58
58
  - lib/cheveret.rb
59
+ - lib/cheveret/base.rb
60
+ - lib/cheveret/column.rb
61
+ - lib/cheveret/config.rb
62
+ - lib/cheveret/dsl.rb
63
+ - lib/cheveret/filtering.rb
64
+ - lib/cheveret/helper.rb
65
+ - lib/cheveret/rendering.rb
66
+ - lib/cheveret/resizing.rb
67
+ - lib/cheveret/version.rb
59
68
  - rails/init.rb
60
69
  - spec/cheveret_spec.rb
61
70
  - spec/spec.opts
@@ -81,12 +90,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
81
90
  required_rubygems_version: !ruby/object:Gem::Requirement
82
91
  none: false
83
92
  requirements:
84
- - - ">="
93
+ - - ">"
85
94
  - !ruby/object:Gem::Version
86
- hash: 3
95
+ hash: 25
87
96
  segments:
88
- - 0
89
- version: "0"
97
+ - 1
98
+ - 3
99
+ - 1
100
+ version: 1.3.1
90
101
  requirements: []
91
102
 
92
103
  rubyforge_project:
data/VERSION DELETED
@@ -1 +0,0 @@
1
- 1.1.3