table_cloth 0.2.3 → 0.3.0.beta1
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/.gitignore +1 -0
- data/lib/generators/templates/table.rb +7 -0
- data/lib/table_cloth.rb +14 -15
- data/lib/table_cloth/base.rb +3 -26
- data/lib/table_cloth/column.rb +0 -12
- data/lib/table_cloth/{action.rb → column_jury.rb} +10 -6
- data/lib/table_cloth/configurable_elements.rb +6 -13
- data/lib/table_cloth/extensions/actions.rb +25 -0
- data/lib/table_cloth/extensions/actions/action.rb +21 -0
- data/lib/table_cloth/extensions/actions/action_collection.rb +11 -0
- data/lib/table_cloth/extensions/actions/column.rb +21 -0
- data/lib/table_cloth/extensions/actions/jury.rb +37 -0
- data/lib/table_cloth/presenter.rb +16 -5
- data/lib/table_cloth/presenters/default.rb +1 -1
- data/lib/table_cloth/version.rb +1 -1
- data/spec/factories/actions.rb +6 -0
- data/spec/factories/columns.rb +18 -0
- data/spec/factories/dummy_tables.rb +11 -0
- data/spec/lib/base_spec.rb +6 -22
- data/spec/lib/column_jury_spec.rb +35 -0
- data/spec/lib/column_spec.rb +9 -14
- data/spec/lib/extensions/actions/action_collection_spec.rb +29 -0
- data/spec/lib/extensions/actions/action_spec.rb +57 -0
- data/spec/lib/extensions/actions/column_spec.rb +23 -0
- data/spec/lib/extensions/actions/jury_spec.rb +67 -0
- data/spec/lib/extensions/actions_spec.rb +42 -0
- data/spec/lib/presenter_spec.rb +29 -31
- data/spec/lib/presenters/default_spec.rb +61 -124
- data/spec/spec_helper.rb +7 -0
- data/spec/support/dummy_table.rb +0 -4
- data/spec/support/dummy_table_with_value_options.rb +1 -1
- data/spec/support/matchers/element_matchers.rb +6 -0
- data/table_cloth.gemspec +2 -0
- metadata +63 -14
- data/lib/table_cloth/actions.rb +0 -23
- data/lib/table_cloth/columns/action.rb +0 -24
- data/spec/lib/actions_spec.rb +0 -28
- data/spec/lib/columns/action_spec.rb +0 -73
- data/spec/support/dummy_table_with_actions.rb +0 -7
data/.gitignore
CHANGED
@@ -1,4 +1,7 @@
|
|
1
1
|
class <%= class_name %>Table < TableCloth::Base
|
2
|
+
# To include actions on this table, uncomment this line
|
3
|
+
# include TableCloth::Extensions::Actions
|
4
|
+
|
2
5
|
# Define columns with the #column method
|
3
6
|
# column :name, :email
|
4
7
|
|
@@ -22,8 +25,12 @@ class <%= class_name %>Table < TableCloth::Base
|
|
22
25
|
# Actions give you the ability to create a column for any actions you'd like to provide.
|
23
26
|
# Pass a block with an arity of 2, (object, view context).
|
24
27
|
# You can add as many actions as you want.
|
28
|
+
# Make sure you include the actions extension.
|
25
29
|
#
|
26
30
|
# actions do
|
27
31
|
# action {|object| link_to "Edit", edit_object_path(object) }
|
32
|
+
# action(if: :valid?) {|object| link_to "Invalidate", invalidate_object_path(object) }
|
28
33
|
# end
|
34
|
+
#
|
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.
|
29
36
|
end
|
data/lib/table_cloth.rb
CHANGED
@@ -1,24 +1,23 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
1
|
+
require "action_view"
|
2
|
+
require "active_support/core_ext/class"
|
3
|
+
require "table_cloth/version"
|
4
|
+
require "table_cloth/configurable_elements"
|
5
|
+
require "table_cloth/base"
|
6
6
|
|
7
7
|
module TableCloth
|
8
|
-
autoload :Configuration,
|
9
|
-
autoload :Builder,
|
10
|
-
autoload :Column,
|
11
|
-
autoload :
|
12
|
-
autoload :
|
13
|
-
autoload :
|
14
|
-
autoload :ActionViewExtension, 'table_cloth/action_view_extension'
|
8
|
+
autoload :Configuration, "table_cloth/configuration"
|
9
|
+
autoload :Builder, "table_cloth/builder"
|
10
|
+
autoload :Column, "table_cloth/column"
|
11
|
+
autoload :ColumnJury, "table_cloth/column_jury"
|
12
|
+
autoload :Presenter, "table_cloth/presenter"
|
13
|
+
autoload :ActionViewExtension, "table_cloth/action_view_extension"
|
15
14
|
|
16
15
|
module Presenters
|
17
|
-
autoload :Default,
|
16
|
+
autoload :Default, "table_cloth/presenters/default"
|
18
17
|
end
|
19
18
|
|
20
|
-
module
|
21
|
-
autoload :
|
19
|
+
module Extensions
|
20
|
+
autoload :Actions, "table_cloth/extensions/actions"
|
22
21
|
end
|
23
22
|
|
24
23
|
def config_for(type)
|
data/lib/table_cloth/base.rb
CHANGED
@@ -11,16 +11,6 @@ module TableCloth
|
|
11
11
|
@view = view
|
12
12
|
end
|
13
13
|
|
14
|
-
def columns
|
15
|
-
@columns ||= self.class.columns.each_with_object({}) do |(column_name, column), columns|
|
16
|
-
columns[column_name] = column if column.available?(self)
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
def has_actions?
|
21
|
-
self.class.has_actions?
|
22
|
-
end
|
23
|
-
|
24
14
|
class << self
|
25
15
|
def presenter(klass=nil)
|
26
16
|
return @presenter = klass if klass
|
@@ -40,7 +30,7 @@ module TableCloth
|
|
40
30
|
column_class = options.delete(:using) || Column
|
41
31
|
|
42
32
|
args.each do |name|
|
43
|
-
add_column
|
33
|
+
add_column(class: column_class, options: options, name: name)
|
44
34
|
end
|
45
35
|
end
|
46
36
|
|
@@ -53,22 +43,9 @@ module TableCloth
|
|
53
43
|
@columns
|
54
44
|
end
|
55
45
|
|
56
|
-
def add_column(
|
46
|
+
def add_column(options)
|
57
47
|
@columns ||= {}
|
58
|
-
@columns[name] =
|
59
|
-
end
|
60
|
-
|
61
|
-
def actions(options={}, &block)
|
62
|
-
if block_given?
|
63
|
-
actions = Actions.new(options, &block)
|
64
|
-
columns[:actions] = actions.column
|
65
|
-
end
|
66
|
-
|
67
|
-
columns[:actions].actions
|
68
|
-
end
|
69
|
-
|
70
|
-
def has_actions?
|
71
|
-
columns[:actions].present?
|
48
|
+
@columns[options[:name]] = options
|
72
49
|
end
|
73
50
|
end
|
74
51
|
end
|
data/lib/table_cloth/column.rb
CHANGED
@@ -18,17 +18,5 @@ module TableCloth
|
|
18
18
|
def human_name
|
19
19
|
options[:label] || name.to_s.humanize
|
20
20
|
end
|
21
|
-
|
22
|
-
def available?(table)
|
23
|
-
if options[:if] && options[:if].is_a?(Symbol)
|
24
|
-
return !!table.send(options[:if])
|
25
|
-
end
|
26
|
-
|
27
|
-
if options[:unless] && options[:unless].is_a?(Symbol)
|
28
|
-
return !table.send(options[:unless])
|
29
|
-
end
|
30
|
-
|
31
|
-
true
|
32
|
-
end
|
33
21
|
end
|
34
22
|
end
|
@@ -1,12 +1,12 @@
|
|
1
1
|
module TableCloth
|
2
|
-
class
|
3
|
-
attr_reader :
|
4
|
-
|
5
|
-
def initialize(
|
6
|
-
@
|
2
|
+
class ColumnJury
|
3
|
+
attr_reader :column, :table
|
4
|
+
|
5
|
+
def initialize(column, table)
|
6
|
+
@column, @table = column, table
|
7
7
|
end
|
8
8
|
|
9
|
-
def available?
|
9
|
+
def available?
|
10
10
|
if options[:if] && options[:if].is_a?(Symbol)
|
11
11
|
return !!table.send(options[:if])
|
12
12
|
end
|
@@ -17,5 +17,9 @@ module TableCloth
|
|
17
17
|
|
18
18
|
true
|
19
19
|
end
|
20
|
+
|
21
|
+
def options
|
22
|
+
column.options
|
23
|
+
end
|
20
24
|
end
|
21
25
|
end
|
@@ -1,21 +1,14 @@
|
|
1
1
|
module TableCloth
|
2
2
|
module ConfigurableElements
|
3
|
+
OPTIONS = %w(table thead th tbody tr td).map(&:to_sym)
|
4
|
+
|
3
5
|
extend ActiveSupport::Concern
|
4
6
|
|
5
7
|
included do
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
cattr_accessor :tr
|
11
|
-
cattr_accessor :td
|
12
|
-
|
13
|
-
self.table = ActiveSupport::OrderedOptions.new
|
14
|
-
self.thead = ActiveSupport::OrderedOptions.new
|
15
|
-
self.th = ActiveSupport::OrderedOptions.new
|
16
|
-
self.tbody = ActiveSupport::OrderedOptions.new
|
17
|
-
self.tr = ActiveSupport::OrderedOptions.new
|
18
|
-
self.td = ActiveSupport::OrderedOptions.new
|
8
|
+
OPTIONS.each do |option|
|
9
|
+
cattr_accessor option
|
10
|
+
self.send "#{option}=", ActiveSupport::OrderedOptions.new
|
11
|
+
end
|
19
12
|
end
|
20
13
|
end
|
21
14
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module TableCloth
|
2
|
+
module Extensions
|
3
|
+
module Actions
|
4
|
+
autoload :Action, "table_cloth/extensions/actions/action"
|
5
|
+
autoload :Column, "table_cloth/extensions/actions/column"
|
6
|
+
autoload :ActionCollection, "table_cloth/extensions/actions/action_collection"
|
7
|
+
autoload :Jury, "table_cloth/extensions/actions/jury"
|
8
|
+
extend ActiveSupport::Concern
|
9
|
+
|
10
|
+
module ClassMethods
|
11
|
+
def actions(options={}, &block)
|
12
|
+
action_collection.instance_eval(&block)
|
13
|
+
|
14
|
+
column :actions, options.update(collection: action_collection, using: Column)
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def action_collection
|
20
|
+
@action_collection ||= ActionCollection.new
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module TableCloth::Extensions::Actions
|
2
|
+
class Action
|
3
|
+
attr_reader :options
|
4
|
+
|
5
|
+
def initialize(options={})
|
6
|
+
@options = options
|
7
|
+
end
|
8
|
+
|
9
|
+
def jury
|
10
|
+
@jury ||= Jury.new(self)
|
11
|
+
end
|
12
|
+
|
13
|
+
def value(object, view)
|
14
|
+
if jury.available?(object)
|
15
|
+
view.instance_exec(object, &options[:proc])
|
16
|
+
else
|
17
|
+
""
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module TableCloth::Extensions::Actions
|
2
|
+
class Column < ::TableCloth::Column
|
3
|
+
def value(object, view, table=nil)
|
4
|
+
actions = action_collection.actions.map do |action|
|
5
|
+
action.value(object, view)
|
6
|
+
end
|
7
|
+
|
8
|
+
view.raw(actions.join(separator))
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def separator
|
14
|
+
options[:separator] || " "
|
15
|
+
end
|
16
|
+
|
17
|
+
def action_collection
|
18
|
+
@action_collection ||= options[:collection]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module TableCloth::Extensions::Actions
|
2
|
+
class Jury
|
3
|
+
attr_reader :action
|
4
|
+
|
5
|
+
def initialize(action)
|
6
|
+
@action = action
|
7
|
+
end
|
8
|
+
|
9
|
+
def available?(object)
|
10
|
+
case action_if
|
11
|
+
when Proc
|
12
|
+
return !!action_if.call(object)
|
13
|
+
when Symbol
|
14
|
+
return !!object.send(action_if)
|
15
|
+
end
|
16
|
+
|
17
|
+
case action_unless
|
18
|
+
when Proc
|
19
|
+
return !action_unless.call(object)
|
20
|
+
when Symbol
|
21
|
+
return !object.send(action_unless)
|
22
|
+
end
|
23
|
+
|
24
|
+
return true
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def action_if
|
30
|
+
action.options[:if]
|
31
|
+
end
|
32
|
+
|
33
|
+
def action_unless
|
34
|
+
action.options[:unless]
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -4,13 +4,12 @@ module TableCloth
|
|
4
4
|
:table
|
5
5
|
|
6
6
|
def initialize(objects, table, view)
|
7
|
-
@view_context = view
|
8
|
-
@table_definition = table
|
9
7
|
@objects = objects
|
8
|
+
@table_definition = table
|
9
|
+
@view_context = view
|
10
10
|
@table = table_definition.new(objects, view)
|
11
11
|
end
|
12
12
|
|
13
|
-
# Short hand so your fingers don't hurt
|
14
13
|
def v
|
15
14
|
view_context
|
16
15
|
end
|
@@ -27,14 +26,26 @@ module TableCloth
|
|
27
26
|
raise NoMethodError, "You must override the .rows method"
|
28
27
|
end
|
29
28
|
|
29
|
+
def columns
|
30
|
+
@columns ||= table.class.columns.map do |name, options|
|
31
|
+
column = options[:class].new(name, options[:options])
|
32
|
+
|
33
|
+
if ColumnJury.new(column, table).available?
|
34
|
+
column
|
35
|
+
else
|
36
|
+
nil
|
37
|
+
end
|
38
|
+
end.compact
|
39
|
+
end
|
40
|
+
|
30
41
|
def column_names
|
31
|
-
@column_names ||=
|
42
|
+
@column_names ||= columns.each_with_object([]) do |column, names|
|
32
43
|
names << column.human_name
|
33
44
|
end
|
34
45
|
end
|
35
46
|
|
36
47
|
def row_values(object)
|
37
|
-
|
48
|
+
columns.each_with_object([]) do |column, values|
|
38
49
|
values << column.value(object, view_context, table)
|
39
50
|
end
|
40
51
|
end
|
data/lib/table_cloth/version.rb
CHANGED
@@ -0,0 +1,18 @@
|
|
1
|
+
FactoryGirl.define do
|
2
|
+
factory :column, class: "TableCloth::Column" do
|
3
|
+
name :name
|
4
|
+
options({})
|
5
|
+
|
6
|
+
factory :if_column do
|
7
|
+
name :name
|
8
|
+
options({ if: :admin? })
|
9
|
+
end
|
10
|
+
|
11
|
+
factory :unless_column do
|
12
|
+
name :name
|
13
|
+
options({ unless: :moderator? })
|
14
|
+
end
|
15
|
+
|
16
|
+
initialize_with { new(name, options) }
|
17
|
+
end
|
18
|
+
end
|
data/spec/lib/base_spec.rb
CHANGED
@@ -16,7 +16,8 @@ describe TableCloth::Base do
|
|
16
16
|
end
|
17
17
|
|
18
18
|
it 'column accepts options' do
|
19
|
-
|
19
|
+
subject.column :name, option: "value"
|
20
|
+
expect(subject.columns[:name][:options][:option]).to eq("value")
|
20
21
|
end
|
21
22
|
|
22
23
|
it '.columns returns all columns' do
|
@@ -33,22 +34,16 @@ describe TableCloth::Base do
|
|
33
34
|
subject.column(:name) { 'Wee' }
|
34
35
|
|
35
36
|
column = subject.columns[:name]
|
36
|
-
expect(column
|
37
|
-
expect(column
|
37
|
+
expect(column[:options][:proc]).to be_present
|
38
|
+
expect(column[:options][:proc]).to be_kind_of(Proc)
|
38
39
|
end
|
39
40
|
|
40
41
|
context "custom" do
|
41
|
-
let(:custom_column)
|
42
|
-
Class.new(TableCloth::Column) do
|
43
|
-
def value(object, view)
|
44
|
-
"AN EMAIL!"
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
42
|
+
let(:custom_column) { stub(:custom, value: "AN EMAIL") }
|
48
43
|
|
49
44
|
it '.column can take a custom column' do
|
50
45
|
subject.column :email, using: custom_column
|
51
|
-
subject.columns[:email].
|
46
|
+
expect(subject.columns[:email][:class]).to eq(custom_column)
|
52
47
|
end
|
53
48
|
end
|
54
49
|
end
|
@@ -59,17 +54,6 @@ describe TableCloth::Base do
|
|
59
54
|
end
|
60
55
|
end
|
61
56
|
|
62
|
-
context 'actions' do
|
63
|
-
it "takes a block" do
|
64
|
-
subject.actions do
|
65
|
-
action { 'Edit' }
|
66
|
-
action { 'Delete' }
|
67
|
-
end
|
68
|
-
|
69
|
-
expect(subject.columns[:actions]).to be_kind_of TableCloth::Columns::Action
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
57
|
context "configuration" do
|
74
58
|
subject { Class.new(TableCloth::Base) }
|
75
59
|
let(:sibling1_class) { Class.new(subject) }
|