table_cloth 0.3.1.alpha1 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -2,3 +2,5 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in tablecloth.gemspec
4
4
  gemspec
5
+
6
+ gem 'actionpack', '>= 3.0', '< 4.1', github: 'rails/rails', branch: 'master'
data/README.md CHANGED
@@ -1,7 +1,9 @@
1
1
  # Table Cloth
2
2
 
3
3
  Table Cloth gives you an easy to use DSL for creating and rendering tables in rails.
4
- It's new, so if you want a feature or have an improvement? Make an issue!
4
+
5
+ The primary goal of Table Cloth is to remove the complexity that usually comes with making tables with dynamic content.
6
+ HTML Tables frequently can get out of hand when you start to add conditionals, removing columns, etc..
5
7
 
6
8
  Follow me! [@robertoross](http://twitter.com/robertoross)
7
9
 
@@ -147,7 +149,7 @@ class UserTable < TableCloth::Base
147
149
  actions do
148
150
  action {|object| link_to "Edit", edit_object_path(object) }
149
151
  end
150
-
152
+
151
153
  config.table.class = ''
152
154
  config.thead.class = ''
153
155
  config.th.class = ''
@@ -192,7 +194,6 @@ This would render something alow the lines of:
192
194
  ## Thanks
193
195
 
194
196
  - TableCloth was built during my open source time at [philosophie](http://gophilosophie.com)
195
- - simple_form for the idea of ```simple_table_for```
196
197
 
197
198
  ## Contributing
198
199
 
@@ -13,7 +13,7 @@ class <%= class_name %>Table < TableCloth::Base
13
13
  #
14
14
  # Columns can also have conditionals if you want.
15
15
  # The conditions are checked against the table's methods.
16
- # As a convience, the table has a #view method which will return the current view context.
16
+ # As a convenience, the table has a #view method which will return the current view context.
17
17
  # This gives you access to current user, params, etc...
18
18
  #
19
19
  # column :email, if: :admin?
@@ -31,6 +31,6 @@ class <%= class_name %>Table < TableCloth::Base
31
31
  # action {|object| link_to "Edit", edit_object_path(object) }
32
32
  # action(if: :valid?) {|object| link_to "Invalidate", invalidate_object_path(object) }
33
33
  # end
34
- #
34
+ #
35
35
  # If action provides an "if:" option, it will call that method on the object. It can also take a block with an arity of 1.
36
36
  end
data/lib/table_cloth.rb CHANGED
@@ -1,7 +1,6 @@
1
1
  require "action_view"
2
2
  require "active_support/core_ext/class"
3
3
  require "table_cloth/version"
4
- require "table_cloth/configurable_elements"
5
4
 
6
5
  module TableCloth
7
6
  autoload :Base, "table_cloth/base"
@@ -28,6 +27,9 @@ module TableCloth
28
27
  end
29
28
  end
30
29
 
31
- TableCloth::Base.presenter ::TableCloth::Presenters::Default
30
+ # Set the default presenter
31
+ TableCloth::Base.presenter(TableCloth::Presenters::Default)
32
32
 
33
- ActionView::Base.send(:include, TableCloth::ActionViewExtension)
33
+ ActiveSupport.on_load(:action_view) do
34
+ include TableCloth::ActionViewExtension
35
+ end
@@ -51,7 +51,11 @@ module TableCloth
51
51
  end
52
52
 
53
53
  def config
54
- @config ||= Configuration.new
54
+ @config ||= if superclass.respond_to?(:config)
55
+ superclass.config.dup
56
+ else
57
+ Configuration.new
58
+ end
55
59
  end
56
60
  end
57
61
  end
@@ -19,9 +19,6 @@ module TableCloth
19
19
  end
20
20
  end
21
21
 
22
- def initialize
23
- end
24
-
25
22
  def to_s
26
23
  presenter.render_table
27
24
  end
@@ -3,12 +3,12 @@ module TableCloth
3
3
  attr_reader :options, :name
4
4
 
5
5
  def initialize(name, options={})
6
- @name = name
6
+ @name = name
7
7
  @options = options
8
8
  end
9
9
 
10
10
  def value(object, view, table=nil)
11
- if options[:proc] && options[:proc].respond_to?(:call)
11
+ if options[:proc].respond_to?(:call)
12
12
  view.instance_exec(object, view, &options[:proc])
13
13
  else
14
14
  object.send(name)
@@ -1,8 +1,11 @@
1
1
  module TableCloth
2
2
  class Configuration
3
- OPTIONS = %w(table thead th tbody tr td).map(&:to_sym)
3
+ ELEMENT_OPTIONS = %w(table thead th tbody tr td).map(&:to_sym)
4
4
 
5
- OPTIONS.each do |option|
5
+ GENERAL_OPTIONS = %w(alternating_rows).map(&:to_sym)
6
+ attr_accessor *GENERAL_OPTIONS
7
+
8
+ ELEMENT_OPTIONS.each do |option|
6
9
  class_eval <<-OPTION, __FILE__, __LINE__+1
7
10
  def #{option}
8
11
  @#{option}_option ||= ActiveSupport::OrderedOptions.new
@@ -17,7 +20,8 @@ module TableCloth
17
20
  end
18
21
 
19
22
  def config_for(type)
20
- send(type).to_hash
23
+ value = send(type)
24
+ value.respond_to?(:to_hash) ? value.to_hash : value
21
25
  end
22
26
  alias [] config_for
23
27
  end
@@ -17,7 +17,11 @@ module TableCloth
17
17
  private
18
18
 
19
19
  def action_collection
20
- @action_collection ||= ActionCollection.new
20
+ @action_collection ||= if superclass.respond_to? :action_collection
21
+ superclass.action_collection.dup
22
+ else
23
+ ActionCollection.new
24
+ end
21
25
  end
22
26
  end
23
27
  end
@@ -1,13 +1,11 @@
1
1
  module TableCloth
2
2
  class Presenter
3
- attr_reader :view_context, :table_definition, :objects,
4
- :table
3
+ attr_reader :view_context, :objects, :table
5
4
 
6
5
  def initialize(objects, table, view)
7
6
  @objects = objects
8
- @table_definition = table
9
7
  @view_context = view
10
- @table = table_definition.new(objects, view)
8
+ @table = table.new(objects, view)
11
9
  end
12
10
 
13
11
  def render_table
@@ -23,14 +21,9 @@ module TableCloth
23
21
  end
24
22
 
25
23
  def columns
26
- @columns ||= table.class.columns.map do |name, options|
27
- column = options[:class].new(name, options[:options])
28
-
29
- if ColumnJury.new(column, table).available?
30
- column
31
- else
32
- nil
33
- end
24
+ @columns ||= table.class.columns.map do |name, column_hash|
25
+ column = column_hash[:class].new(name, column_hash[:options])
26
+ ColumnJury.new(column, table).available? ? column : nil
34
27
  end.compact
35
28
  end
36
29
 
@@ -55,10 +48,10 @@ module TableCloth
55
48
  def wrapper_tag(type, value=nil, options={}, &block)
56
49
  options = tag_options(type, options)
57
50
 
58
- content = if block_given?
59
- v.content_tag(type, options, &block)
51
+ if block_given?
52
+ view_context.content_tag(type, options, &block)
60
53
  else
61
- v.content_tag(type, value, options)
54
+ view_context.content_tag(type, value, options)
62
55
  end
63
56
  end
64
57
 
@@ -9,13 +9,13 @@ module TableCloth
9
9
 
10
10
  def render_rows
11
11
  wrapper_tag :tbody do
12
- v.raw objects.inject('') {|r, object| r + render_row(object) }
12
+ v.raw objects.inject("") {|r, object| r + render_row(object) }
13
13
  end
14
14
  end
15
15
 
16
16
  def render_row(object)
17
17
  wrapper_tag :tr do
18
- v.raw columns.inject('') {|tds, column| tds + render_td(column, object) }
18
+ v.raw columns.inject("") {|tds, column| tds + render_td(column, object) }
19
19
  end
20
20
  end
21
21
 
@@ -36,7 +36,7 @@ module TableCloth
36
36
  def render_header
37
37
  wrapper_tag :thead do
38
38
  wrapper_tag :tr do
39
- v.raw column_names.inject('') {|tags, name| tags + wrapper_tag(:th, name) }
39
+ v.raw column_names.inject("") {|tags, name| tags + wrapper_tag(:th, name) }
40
40
  end
41
41
  end
42
42
  end
@@ -1,3 +1,3 @@
1
1
  module TableCloth
2
- VERSION = "0.3.1.alpha1"
2
+ VERSION = "0.3.2"
3
3
  end
@@ -58,6 +58,17 @@ describe TableCloth::Base do
58
58
  expect(table_instance.config).to be_kind_of TableCloth::Configuration
59
59
  end
60
60
  end
61
+
62
+ context "inheritance" do
63
+ let(:parent_class) { Class.new(TableCloth::Base) }
64
+ let(:child_class) { Class.new(parent_class) }
65
+
66
+ before { parent_class.config.table.class = "inherit-me" }
67
+
68
+ it "inherits from a parent class's configuration" do
69
+ expect(child_class.config.table[:class]).to eq "inherit-me"
70
+ end
71
+ end
61
72
  end
62
73
 
63
74
  context 'presenters' do
@@ -2,11 +2,20 @@ require 'spec_helper'
2
2
 
3
3
  describe TableCloth::Configuration do
4
4
  subject { TableCloth::Configuration.new }
5
- let(:options) { TableCloth::Configuration::OPTIONS }
6
5
 
7
- it "has accessors for all options" do
8
- options.each do |option|
9
- expect(subject).to respond_to option
6
+ context "element options" do
7
+ TableCloth::Configuration::ELEMENT_OPTIONS.each do |option|
8
+ it "has an accessor for #{option}" do
9
+ expect(subject).to respond_to option
10
+ end
11
+ end
12
+ end
13
+
14
+ context "general options" do
15
+ TableCloth::Configuration::GENERAL_OPTIONS.each do |option|
16
+ it "has an accessor for #{option}" do
17
+ expect(subject).to respond_to option
18
+ end
10
19
  end
11
20
  end
12
21
 
@@ -4,11 +4,8 @@ describe TableCloth::Presenter do
4
4
  subject { TableCloth::Presenter.new(objects, dummy_table, view_context) }
5
5
  let(:dummy_table) { Class.new(DummyTable) }
6
6
  let(:dummy_model) { FactoryGirl.build(:dummy_model) }
7
-
8
7
  let(:objects) { 3.times.map { FactoryGirl.build(:dummy_model) } }
9
-
10
8
  let(:view_context) { ActionView::Base.new }
11
- subject { TableCloth::Presenter.new(objects, dummy_table, view_context) }
12
9
 
13
10
  context ".columns" do
14
11
  it "returns all columns from the table" do
@@ -24,7 +21,7 @@ describe TableCloth::Presenter do
24
21
  context "that are unavaialble" do
25
22
  let(:dummy_table) { FactoryGirl.build(:dummy_table, email: {if: :admin?}) }
26
23
  let(:table_instance) { dummy_table.new(objects, view_context) }
27
- before(:each) do
24
+ before(:each) do
28
25
  table_instance.stub admin?: false
29
26
  subject.stub table: table_instance
30
27
  end
@@ -44,14 +41,14 @@ describe TableCloth::Presenter do
44
41
  before(:each) { table_instance.stub admin?: false, awesome?: true }
45
42
 
46
43
  it 'returns all names' do
47
- subject.column_names.should == ["Id", "Name", "Email"]
44
+ expect(subject.column_names).to eq ["Id", "Name", "Email"]
48
45
  end
49
46
  end
50
47
 
51
48
  it 'returns all values for a row' do
52
- subject.row_values(dummy_model).should == [dummy_model.id, dummy_model.name, dummy_model.email]
49
+ expect(subject.row_values(dummy_model)).to eq [dummy_model.id, dummy_model.name, dummy_model.email]
53
50
  end
54
-
51
+
55
52
  it 'generates the values for all of the rows' do
56
53
  expected = objects.map {|o| [o.id, o.name, o.email] }
57
54
  expect(subject.rows).to eq(expected)
data/table_cloth.gemspec CHANGED
@@ -8,8 +8,8 @@ Gem::Specification.new do |gem|
8
8
  gem.version = TableCloth::VERSION
9
9
  gem.authors = ["Robert Ross"]
10
10
  gem.email = ["robert@creativequeries.com"]
11
- gem.description = %q{Table Cloth helps you create a table easily.}
12
- gem.summary = %q{Table Cloth provides an easy and intuitive DSL for creating tables in rails views.}
11
+ gem.description = %q{Table Cloth helps you create tables easily.}
12
+ gem.summary = %q{Table Cloth provides an easy and intuitive DSL for creating tables for Rails views.}
13
13
  gem.homepage = "http://www.github.com/bobbytables/table_cloth"
14
14
 
15
15
  gem.files = `git ls-files`.split($/)
@@ -27,5 +27,5 @@ Gem::Specification.new do |gem|
27
27
  gem.add_development_dependency('rake')
28
28
  gem.add_development_dependency('rb-fsevent', '~> 0.9.1')
29
29
 
30
- gem.add_dependency('actionpack', '~> 3.2')
30
+ gem.add_dependency('actionpack', '>= 3.1', '< 4.1')
31
31
  end
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: table_cloth
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1.alpha1
5
- prerelease: 6
4
+ version: 0.3.2
5
+ prerelease:
6
6
  platform: ruby
7
7
  authors:
8
8
  - Robert Ross
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-01-11 00:00:00.000000000 Z
12
+ date: 2013-04-29 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
@@ -160,18 +160,24 @@ dependencies:
160
160
  requirement: !ruby/object:Gem::Requirement
161
161
  none: false
162
162
  requirements:
163
- - - ~>
163
+ - - ! '>='
164
164
  - !ruby/object:Gem::Version
165
- version: '3.2'
165
+ version: '3.1'
166
+ - - <
167
+ - !ruby/object:Gem::Version
168
+ version: '4.1'
166
169
  type: :runtime
167
170
  prerelease: false
168
171
  version_requirements: !ruby/object:Gem::Requirement
169
172
  none: false
170
173
  requirements:
171
- - - ~>
174
+ - - ! '>='
175
+ - !ruby/object:Gem::Version
176
+ version: '3.1'
177
+ - - <
172
178
  - !ruby/object:Gem::Version
173
- version: '3.2'
174
- description: Table Cloth helps you create a table easily.
179
+ version: '4.1'
180
+ description: Table Cloth helps you create tables easily.
175
181
  email:
176
182
  - robert@creativequeries.com
177
183
  executables: []
@@ -194,7 +200,6 @@ files:
194
200
  - lib/table_cloth/builder.rb
195
201
  - lib/table_cloth/column.rb
196
202
  - lib/table_cloth/column_jury.rb
197
- - lib/table_cloth/configurable_elements.rb
198
203
  - lib/table_cloth/configuration.rb
199
204
  - lib/table_cloth/extensions/actions.rb
200
205
  - lib/table_cloth/extensions/actions/action.rb
@@ -203,7 +208,6 @@ files:
203
208
  - lib/table_cloth/extensions/actions/jury.rb
204
209
  - lib/table_cloth/presenter.rb
205
210
  - lib/table_cloth/presenters/default.rb
206
- - lib/table_cloth/presenters/sortable.rb
207
211
  - lib/table_cloth/version.rb
208
212
  - spec/factories/actions.rb
209
213
  - spec/factories/columns.rb
@@ -222,7 +226,6 @@ files:
222
226
  - spec/lib/extensions/actions_spec.rb
223
227
  - spec/lib/presenter_spec.rb
224
228
  - spec/lib/presenters/default_spec.rb
225
- - spec/lib/presenters/sortable_spec.rb
226
229
  - spec/spec_helper.rb
227
230
  - spec/support/dummy_model.rb
228
231
  - spec/support/dummy_table.rb
@@ -247,15 +250,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
247
250
  required_rubygems_version: !ruby/object:Gem::Requirement
248
251
  none: false
249
252
  requirements:
250
- - - ! '>'
253
+ - - ! '>='
251
254
  - !ruby/object:Gem::Version
252
- version: 1.3.1
255
+ version: '0'
253
256
  requirements: []
254
257
  rubyforge_project:
255
258
  rubygems_version: 1.8.23
256
259
  signing_key:
257
260
  specification_version: 3
258
- summary: Table Cloth provides an easy and intuitive DSL for creating tables in rails
261
+ summary: Table Cloth provides an easy and intuitive DSL for creating tables for Rails
259
262
  views.
260
263
  test_files:
261
264
  - spec/factories/actions.rb
@@ -275,7 +278,6 @@ test_files:
275
278
  - spec/lib/extensions/actions_spec.rb
276
279
  - spec/lib/presenter_spec.rb
277
280
  - spec/lib/presenters/default_spec.rb
278
- - spec/lib/presenters/sortable_spec.rb
279
281
  - spec/spec_helper.rb
280
282
  - spec/support/dummy_model.rb
281
283
  - spec/support/dummy_table.rb
@@ -284,3 +286,4 @@ test_files:
284
286
  - spec/support/matchers/element_matchers.rb
285
287
  - spec/support/shared_config_examples.rb
286
288
  - spec/support/view_mocks.rb
289
+ has_rdoc:
@@ -1,14 +0,0 @@
1
- module TableCloth
2
- module ConfigurableElements
3
- OPTIONS = %w(table thead th tbody tr td).map(&:to_sym)
4
-
5
- extend ActiveSupport::Concern
6
-
7
- included do
8
- OPTIONS.each do |option|
9
- class_attribute option
10
- self.send "#{option}=", ActiveSupport::OrderedOptions.new
11
- end
12
- end
13
- end
14
- end
@@ -1,49 +0,0 @@
1
- module TableCloth
2
- module Presenters
3
- class Sortable < Default
4
- def render_header
5
- wrapper_tag :thead do
6
- wrapper_tag :tr, v.raw(row_headers.join("\n"))
7
- end
8
- end
9
-
10
- def render_sortable(column)
11
- query_string = sort_query(sort_params_for(column))
12
- wrapper_tag(:a, column.human_name, href: "?#{query_string}")
13
- end
14
-
15
- def row_headers
16
- columns.map do |column|
17
- if !!column.options[:sortable]
18
- wrapper_tag :th, render_sortable(column), class: "sortable-column"
19
- else
20
- column.human_name
21
- end
22
- end
23
- end
24
-
25
- private
26
-
27
- def sort_params_for(column)
28
- direction = params[:direction]
29
- new_direction = (direction == "asc") ? "desc" : "asc"
30
-
31
- params.update({sort_by: column.name.to_s, direction: new_direction})
32
- end
33
-
34
- def sort_query(params)
35
- params.stringify_keys.map{|k,v| "#{CGI.escape(k)}=#{CGI.escape(v)}" }.join("&")
36
- end
37
-
38
- def header_values
39
- columns.map do |column|
40
- if !!column.options[:sortable]
41
- render_sortable(column)
42
- else
43
- column.human_name
44
- end
45
- end
46
- end
47
- end
48
- end
49
- end
@@ -1,55 +0,0 @@
1
- require "spec_helper"
2
-
3
- describe TableCloth::Presenters::Sortable do
4
- let(:dummy_table) { FactoryGirl.build(:dummy_table, name: {sortable: true} ) }
5
- let(:dummy_model) { FactoryGirl.build(:dummy_model) }
6
- let(:objects) { FactoryGirl.build_list(:dummy_model, 3) }
7
- let(:view_context) { ActionView::Base.new }
8
- subject { TableCloth::Presenters::Sortable.new(objects, dummy_table, view_context) }
9
- let(:params) { {sort_by: "", direction: "asc"} }
10
- let(:column) { subject.columns.first }
11
-
12
- before do
13
- dummy_table.presenter(described_class)
14
- subject.stub params: params
15
- column.options[:sortable] = true
16
- end
17
-
18
- it "inherits from default" do
19
- expect(described_class).to be < TableCloth::Presenters::Default
20
- end
21
-
22
- context ".render_sortable" do
23
- before do
24
- column.stub human_name: "Header"
25
- end
26
-
27
- it "renders an a tag" do
28
- element = to_element(subject.render_sortable(column), "a")
29
- expect(element.node_name).to eq("a")
30
- end
31
-
32
- it "renders an a tag with href direction keys" do
33
- params[:direction] = "desc"
34
- element = to_element(subject.render_sortable(column), "a")
35
- query_string = element[:href]
36
-
37
- expect(query_string).to include "direction=asc"
38
- end
39
-
40
- it "renders an a tag with href sort by keys" do
41
- params[:sort_by] = "desc"
42
- element = to_element(subject.render_sortable(column), "a")
43
- query_string = element[:href]
44
-
45
- expect(query_string).to include "sort_by=#{column.name}"
46
- end
47
- end
48
-
49
- context "thead" do
50
- it "includes a css class for a sortable column" do
51
- header = to_element(subject.render_header, "thead")
52
- expect(header.at_css("th.sortable-column")).to be_present
53
- end
54
- end
55
- end