datagrid 0.4.1 → 0.5.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.
@@ -1,91 +1,105 @@
1
1
  GEM
2
2
  remote: http://rubygems.org/
3
3
  specs:
4
- abstract (1.0.0)
5
4
  accept_values_for (0.4.3)
6
5
  activemodel (>= 3.0.0)
7
6
  rspec
8
- actionmailer (3.0.7)
9
- actionpack (= 3.0.7)
10
- mail (~> 2.2.15)
11
- actionpack (3.0.7)
12
- activemodel (= 3.0.7)
13
- activesupport (= 3.0.7)
14
- builder (~> 2.1.2)
15
- erubis (~> 2.6.6)
16
- i18n (~> 0.5.0)
17
- rack (~> 1.2.1)
18
- rack-mount (~> 0.6.14)
19
- rack-test (~> 0.5.7)
20
- tzinfo (~> 0.3.23)
21
- activemodel (3.0.7)
22
- activesupport (= 3.0.7)
23
- builder (~> 2.1.2)
24
- i18n (~> 0.5.0)
25
- activerecord (3.0.7)
26
- activemodel (= 3.0.7)
27
- activesupport (= 3.0.7)
28
- arel (~> 2.0.2)
29
- tzinfo (~> 0.3.23)
30
- activeresource (3.0.7)
31
- activemodel (= 3.0.7)
32
- activesupport (= 3.0.7)
33
- activesupport (3.0.7)
34
- arel (2.0.10)
7
+ actionmailer (3.1.3)
8
+ actionpack (= 3.1.3)
9
+ mail (~> 2.3.0)
10
+ actionpack (3.1.3)
11
+ activemodel (= 3.1.3)
12
+ activesupport (= 3.1.3)
13
+ builder (~> 3.0.0)
14
+ erubis (~> 2.7.0)
15
+ i18n (~> 0.6)
16
+ rack (~> 1.3.5)
17
+ rack-cache (~> 1.1)
18
+ rack-mount (~> 0.8.2)
19
+ rack-test (~> 0.6.1)
20
+ sprockets (~> 2.0.3)
21
+ activemodel (3.1.3)
22
+ activesupport (= 3.1.3)
23
+ builder (~> 3.0.0)
24
+ i18n (~> 0.6)
25
+ activerecord (3.1.3)
26
+ activemodel (= 3.1.3)
27
+ activesupport (= 3.1.3)
28
+ arel (~> 2.2.1)
29
+ tzinfo (~> 0.3.29)
30
+ activeresource (3.1.3)
31
+ activemodel (= 3.1.3)
32
+ activesupport (= 3.1.3)
33
+ activesupport (3.1.3)
34
+ multi_json (~> 1.0)
35
+ arel (2.2.1)
35
36
  bson (1.4.0)
36
37
  bson_ext (1.4.0)
37
- builder (2.1.2)
38
- columnize (0.3.2)
39
- diff-lcs (1.1.2)
40
- erubis (2.6.6)
41
- abstract (>= 1.0.0)
42
- fastercsv (1.5.3)
38
+ builder (3.0.0)
39
+ columnize (0.3.5)
40
+ diff-lcs (1.1.3)
41
+ erubis (2.7.0)
42
+ fastercsv (1.5.4)
43
43
  git (1.2.5)
44
- i18n (0.5.0)
45
- jeweler (1.6.1)
46
- bundler (~> 1.0.0)
44
+ hike (1.2.1)
45
+ i18n (0.6.0)
46
+ jeweler (1.6.4)
47
+ bundler (~> 1.0)
47
48
  git (>= 1.2.5)
48
49
  rake
49
- linecache (0.43)
50
- mail (2.2.19)
51
- activesupport (>= 2.3.6)
50
+ json (1.6.3)
51
+ linecache (0.46)
52
+ rbx-require-relative (> 0.0.4)
53
+ mail (2.3.0)
52
54
  i18n (>= 0.4.0)
53
55
  mime-types (~> 1.16)
54
56
  treetop (~> 1.4.8)
55
- mime-types (1.16)
56
- mocha (0.9.12)
57
+ metaclass (0.0.1)
58
+ mime-types (1.17.2)
59
+ mocha (0.10.0)
60
+ metaclass (~> 0.0.1)
57
61
  mongo (1.4.0)
58
62
  bson (= 1.4.0)
59
63
  mongoid (2.2.2)
60
64
  activemodel (~> 3.0)
61
65
  mongo (~> 1.3)
62
66
  tzinfo (~> 0.3.22)
63
- nokogiri (1.4.4)
64
- polyglot (0.3.1)
65
- rack (1.2.3)
66
- rack-mount (0.6.14)
67
+ multi_json (1.0.4)
68
+ nokogiri (1.5.0)
69
+ polyglot (0.3.3)
70
+ rack (1.3.5)
71
+ rack-cache (1.1)
72
+ rack (>= 0.4)
73
+ rack-mount (0.8.3)
67
74
  rack (>= 1.0.0)
68
- rack-test (0.5.7)
75
+ rack-ssl (1.3.2)
76
+ rack
77
+ rack-test (0.6.1)
69
78
  rack (>= 1.0)
70
- rails (3.0.7)
71
- actionmailer (= 3.0.7)
72
- actionpack (= 3.0.7)
73
- activerecord (= 3.0.7)
74
- activeresource (= 3.0.7)
75
- activesupport (= 3.0.7)
79
+ rails (3.1.3)
80
+ actionmailer (= 3.1.3)
81
+ actionpack (= 3.1.3)
82
+ activerecord (= 3.1.3)
83
+ activeresource (= 3.1.3)
84
+ activesupport (= 3.1.3)
76
85
  bundler (~> 1.0)
77
- railties (= 3.0.7)
78
- railties (3.0.7)
79
- actionpack (= 3.0.7)
80
- activesupport (= 3.0.7)
86
+ railties (= 3.1.3)
87
+ railties (3.1.3)
88
+ actionpack (= 3.1.3)
89
+ activesupport (= 3.1.3)
90
+ rack-ssl (~> 1.3.2)
81
91
  rake (>= 0.8.7)
82
- thor (~> 0.14.4)
92
+ rdoc (~> 3.4)
93
+ thor (~> 0.14.6)
83
94
  rake (0.9.2.2)
95
+ rbx-require-relative (0.0.5)
96
+ rdoc (3.11)
97
+ json (~> 1.4)
84
98
  rspec (2.6.0)
85
99
  rspec-core (~> 2.6.0)
86
100
  rspec-expectations (~> 2.6.0)
87
101
  rspec-mocks (~> 2.6.0)
88
- rspec-core (2.6.0)
102
+ rspec-core (2.6.4)
89
103
  rspec-expectations (2.6.0)
90
104
  diff-lcs (~> 1.1.2)
91
105
  rspec-mocks (2.6.0)
@@ -94,13 +108,19 @@ GEM
94
108
  ruby-debug-base (~> 0.10.4.0)
95
109
  ruby-debug-base (0.10.4)
96
110
  linecache (>= 0.3)
97
- sqlite3 (1.3.3)
111
+ sprockets (2.0.3)
112
+ hike (~> 1.2)
113
+ rack (~> 1.0)
114
+ tilt (~> 1.1, != 1.3.0)
115
+ sqlite3 (1.3.5)
98
116
  sqlite3-ruby (1.3.3)
99
117
  sqlite3 (>= 1.3.3)
100
118
  thor (0.14.6)
101
- treetop (1.4.9)
119
+ tilt (1.3.3)
120
+ treetop (1.4.10)
121
+ polyglot
102
122
  polyglot (>= 0.3.1)
103
- tzinfo (0.3.27)
123
+ tzinfo (0.3.31)
104
124
  will_paginate (2.3.15)
105
125
 
106
126
  PLATFORMS
@@ -67,8 +67,6 @@ Basic grid api:
67
67
 
68
68
  ``` ruby
69
69
  report = SimpleReport.new(
70
- :order => "group",
71
- :descending => true,
72
70
  :group_id => [1,2], :from_logins_count => 1,
73
71
  :category => "first",
74
72
  :order => :group,
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.4.1
1
+ 0.5.0
@@ -0,0 +1,8 @@
1
+ <tr>
2
+ <% grid.columns.each do |column| %>
3
+ <th class="<%= datagrid_column_classes(grid, column) %>">
4
+ <%= column.header %>
5
+ <%= datagrid_order_for(grid, column) if column.order && options[:order]%>
6
+ </th>
7
+ <% end %>
8
+ </tr>
@@ -0,0 +1,7 @@
1
+ <tr class="<%= options[:cycle] && cycle(*options[:cycle]) %>">
2
+ <% grid.columns.each do |column| %>
3
+ <td class="<%= datagrid_column_classes(grid, column) %>">
4
+ <%= datagrid_format_value(grid, column, asset) %>
5
+ </td>
6
+ <% end %>
7
+ </tr>
@@ -0,0 +1,10 @@
1
+ <!--
2
+ Local variables:
3
+ * grid - instance of Datagrid
4
+ * assets - Array of database Entities
5
+ * options - passed options Hash
6
+ -->
7
+ <%= content_tag :table, options[:html] do %>
8
+ <%= datagrid_header(grid, options) %>
9
+ <%= datagrid_rows(grid, assets, options) %>
10
+ <% end %>
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "datagrid"
8
- s.version = "0.4.1"
8
+ s.version = "0.5.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Bogdan Gusiev"]
12
- s.date = "2011-12-06"
12
+ s.date = "2012-01-03"
13
13
  s.description = "This allows you to easily build datagrid aka data tables with sortable columns and filters"
14
14
  s.email = "agresso@gmail.com"
15
15
  s.extra_rdoc_files = [
@@ -24,6 +24,9 @@ Gem::Specification.new do |s|
24
24
  "Rakefile",
25
25
  "Readme.markdown",
26
26
  "VERSION",
27
+ "app/views/datagrid/_head.html.erb",
28
+ "app/views/datagrid/_row.html.erb",
29
+ "app/views/datagrid/_table.html.erb",
27
30
  "datagrid.gemspec",
28
31
  "lib/datagrid.rb",
29
32
  "lib/datagrid/active_model.rb",
@@ -34,6 +37,7 @@ Gem::Specification.new do |s|
34
37
  "lib/datagrid/drivers/abstract_driver.rb",
35
38
  "lib/datagrid/drivers/active_record.rb",
36
39
  "lib/datagrid/drivers/mongoid.rb",
40
+ "lib/datagrid/engine.rb",
37
41
  "lib/datagrid/filters.rb",
38
42
  "lib/datagrid/filters/base_filter.rb",
39
43
  "lib/datagrid/filters/boolean_enum_filter.rb",
@@ -48,8 +52,10 @@ Gem::Specification.new do |s|
48
52
  "lib/datagrid/form_builder.rb",
49
53
  "lib/datagrid/helper.rb",
50
54
  "lib/datagrid/ordering.rb",
55
+ "lib/datagrid/renderer.rb",
51
56
  "lib/datagrid/rspec.rb",
52
57
  "lib/datagrid/utils.rb",
58
+ "lib/tasks/datagrid_tasks.rake",
53
59
  "spec/datagrid/active_model_spec.rb",
54
60
  "spec/datagrid/columns_spec.rb",
55
61
  "spec/datagrid/drivers/active_record_spec.rb",
@@ -61,12 +67,14 @@ Gem::Specification.new do |s|
61
67
  "spec/datagrid/form_builder_spec.rb",
62
68
  "spec/datagrid/helper_spec.rb",
63
69
  "spec/datagrid/ordering_spec.rb",
70
+ "spec/datagrid/utils_spec.rb",
64
71
  "spec/datagrid_spec.rb",
65
72
  "spec/spec_helper.rb",
66
- "spec/support/equal_to_dom.rb",
73
+ "spec/support/active_record.rb",
74
+ "spec/support/matchers.rb",
67
75
  "spec/support/mongoid.rb",
68
- "spec/support/schema.rb",
69
- "spec/support/simple_report.rb"
76
+ "spec/support/simple_report.rb",
77
+ "spec/support/test_partials/_actions.html.erb"
70
78
  ]
71
79
  s.homepage = "http://github.com/bogdan/datagrid"
72
80
  s.licenses = ["MIT"]
@@ -6,6 +6,9 @@ require "datagrid/ordering"
6
6
 
7
7
  require "datagrid/helper"
8
8
  require "datagrid/form_builder"
9
+ require "datagrid/renderer"
10
+
11
+ require "datagrid/engine"
9
12
 
10
13
  module Datagrid
11
14
 
@@ -12,15 +12,16 @@ module Datagrid
12
12
 
13
13
  include Datagrid::Core
14
14
 
15
-
16
15
  end
17
16
  base.send :include, InstanceMethods
18
17
  end # self.included
19
18
 
20
19
  module ClassMethods
21
20
 
22
- def columns
23
- @columns ||= []
21
+ def columns(options = {})
22
+ (@columns ||= []).reject do |column|
23
+ options[:data] && column.html?
24
+ end
24
25
  end
25
26
 
26
27
  def column(name, options = {}, &block)
@@ -28,7 +29,8 @@ module Datagrid
28
29
  block ||= lambda do |model|
29
30
  model.send(name)
30
31
  end
31
- self.columns << Datagrid::Columns::Column.new(self, name, options, &block)
32
+ @columns ||= []
33
+ @columns << Datagrid::Columns::Column.new(self, name, options, &block)
32
34
  end
33
35
 
34
36
  def column_by_name(name)
@@ -42,12 +44,12 @@ module Datagrid
42
44
 
43
45
  # Returns <tt>Array</tt> of human readable column names. See also "Localization" section
44
46
  def header
45
- self.class.columns.map(&:header)
47
+ self.data_columns.map(&:header)
46
48
  end
47
49
 
48
50
  # Returns <tt>Array</tt> column values for given asset
49
51
  def row_for(asset)
50
- self.class.columns.map do |column|
52
+ self.data_columns.map do |column|
51
53
  column.value(asset, self)
52
54
  end
53
55
  end
@@ -55,7 +57,7 @@ module Datagrid
55
57
  # Returns <tt>Hash</tt> where keys are column names and values are column values for the given asset
56
58
  def hash_for(asset)
57
59
  result = {}
58
- self.class.columns.each do |column|
60
+ self.data_columns.each do |column|
59
61
  result[column.name] = column.value(asset, self)
60
62
  end
61
63
  result
@@ -94,8 +96,12 @@ module Datagrid
94
96
  end
95
97
  end
96
98
 
97
- def columns
98
- self.class.columns
99
+ def columns(options ={})
100
+ self.class.columns(options)
101
+ end
102
+
103
+ def data_columns
104
+ self.columns(:data => true)
99
105
  end
100
106
 
101
107
  def column_by_name(name)
@@ -7,17 +7,20 @@ class Datagrid::Columns::Column
7
7
  self.name = name.to_sym
8
8
  self.options = options
9
9
  self.block = block
10
+ if format
11
+ ::Datagrid::Utils.warn_once(":format column option is deprecated. Use :url or :html option instead.")
12
+ end
10
13
  end
11
14
 
12
- def value(model, report)
13
- value_for(model, report)
15
+ def value(model, grid)
16
+ value_for(model, grid)
14
17
  end
15
18
 
16
- def value_for(model, report)
19
+ def value_for(model, grid)
17
20
  if self.block.arity == 1
18
21
  self.block.call(model)
19
22
  elsif self.block.arity == 2
20
- self.block.call(model, report)
23
+ self.block.call(model, grid)
21
24
  else
22
25
  model.instance_eval(&self.block)
23
26
  end
@@ -49,4 +52,10 @@ class Datagrid::Columns::Column
49
52
  self.options[:order_desc]
50
53
  end
51
54
 
55
+
56
+ def html?
57
+ !! self.options[:html]
58
+ end
59
+
60
+
52
61
  end
@@ -3,6 +3,7 @@ module Datagrid
3
3
  class ActiveRecord < AbstractDriver
4
4
 
5
5
  def self.match?(scope)
6
+ return false unless defined?(::ActiveRecord)
6
7
  if scope.is_a?(Class)
7
8
  scope.ancestors.include?(::ActiveRecord::Base)
8
9
  else
@@ -3,6 +3,7 @@ module Datagrid
3
3
  class Mongoid < AbstractDriver
4
4
 
5
5
  def self.match?(scope)
6
+ return false unless defined?(::Mongoid)
6
7
  if scope.is_a?(Class)
7
8
  scope.ancestors.include?(::Mongoid::Document)
8
9
  else
@@ -0,0 +1,12 @@
1
+ require "rails/engine"
2
+
3
+ module Datagrid
4
+ class Engine < ::Rails::Engine
5
+ initializer "datagrid.helpers" do
6
+ #TODO: check why it doesn't work
7
+ ActiveSupport.on_load :action_view do
8
+ include Datagrid::Helper
9
+ end
10
+ end
11
+ end
12
+ end
@@ -7,7 +7,7 @@ module Datagrid
7
7
  filter = get_filter(filter_or_attribute)
8
8
  options[:class] ||= ""
9
9
  options[:class] += " " unless options[:class].blank?
10
- options[:class] += "#{filter.name} #{datagrid_html_class(filter.class)}"
10
+ options[:class] += "#{filter.name} #{datagrid_filter_html_class(filter)}"
11
11
  self.send(datagrid_filter_method(filter), filter, options)
12
12
  end
13
13
 
@@ -67,12 +67,12 @@ module Datagrid
67
67
  end
68
68
  end
69
69
 
70
- def datagrid_html_class(klass)
71
- klass.to_s.split("::").last.underscore
70
+ def datagrid_filter_html_class(filter)
71
+ filter.class.to_s.demodulize.underscore
72
72
  end
73
73
 
74
74
  def datagrid_filter_method(filter)
75
- :"datagrid_#{filter.class.to_s.underscore.split('/').last}"
75
+ :"datagrid_#{filter.class.to_s.demodulize.underscore}"
76
76
  end
77
77
 
78
78
  class Error < StandardError
@@ -1,83 +1,39 @@
1
+ require "datagrid/engine"
1
2
  require "action_view"
2
3
 
3
4
  module Datagrid
4
5
  module Helper
5
6
 
6
7
  def datagrid_format_value(report, column, asset)
7
- value = column.value(asset, report)
8
- url = column.options[:url] && column.options[:url].call(asset)
9
- if url
10
- link_to(value, url)
11
- else
12
- case column.format
13
- when :url
14
- link_to(column.label ? asset.send(column.label) : I18n.t("datagrid.table.url_label", :default => "URL"), value)
15
- else
16
- _safe(value)
17
- end
18
- end
8
+ datagrid_renderer.format_value(report, column, asset)
19
9
  end
20
10
 
21
11
  def datagrid_table(report, *args)
22
- options = args.extract_options!
23
- html = options[:html] || {}
24
- html[:class] ||= "datagrid"
25
- assets = args.any? ? args.shift : report.assets
26
- paginate = options[:paginate]
27
- assets = assets.paginate(paginate) if paginate
28
- content = content_tag(:tr, datagrid_header(report, options)) + datagrid_rows(report, assets, options)
29
- content_tag(:table, content, html)
12
+ datagrid_renderer.table(report, *args)
30
13
  end
31
14
 
32
-
33
15
  def datagrid_header(grid, options = {})
34
- header = empty_string
35
- options[:order] = true unless options.has_key?(:order)
36
- grid.columns.each do |column|
37
- data = _safe(column.header)
38
- if options[:order] && column.order
39
- data << datagrid_order_for(grid, column)
40
- end
41
- header << content_tag(:th, data, :class => column.name)
42
- end
43
- header
16
+ datagrid_renderer.header(grid, options)
44
17
  end
45
18
 
46
- def datagrid_rows(report, assets, options)
47
- columns = report.columns
48
- result = assets.map do |asset|
49
- content = columns.map do |column|
50
- content_tag(:td, datagrid_format_value(report, column, asset), :class => column.name)
51
- end.join(empty_string)
52
- content_tag(:tr, _safe(content), :class => options[:cycle] && cycle(*options[:cycle]))
53
- end.join(empty_string)
54
- _safe(result)
19
+ def datagrid_rows(report, assets, options = {})
20
+ datagrid_renderer.rows(report, assets, options)
55
21
  end
56
22
 
57
23
  def datagrid_order_for(grid, column)
58
- content_tag(:div, :class => "order") do
59
- link_to(
60
- I18n.t("datagrid.table.order.asc", :default => "ASC"),
61
- url_for(grid.param_name => grid.attributes.merge(:order => column.name, :descending => false)),
62
- :class => "order asc"
63
- ) + " " + link_to(
64
- I18n.t("datagrid.table.order.desc", :default => "DESC"),
65
- url_for(grid.param_name => grid.attributes.merge(:order => column.name, :descending => true )),
66
- :class => "order desc"
67
- )
68
- end
24
+ datagrid_renderer.order_for(grid, column)
69
25
  end
70
26
 
71
27
  protected
72
- def empty_string
73
- _safe("")
28
+
29
+ def datagrid_renderer
30
+ Renderer.for(self)
74
31
  end
75
32
 
76
- def _safe(string)
77
- string.respond_to?(:html_safe) ? string.html_safe : string
33
+ def datagrid_column_classes(grid, column)
34
+ order_class = grid.order == column.name ? ["ordered", grid.descending ? "desc" : "asc"] : nil
35
+ [column.name, order_class].compact.join(" ")
78
36
  end
79
37
  end
80
-
81
- ::ActionView::Base.send(:include, ::Datagrid::Helper)
82
-
83
38
  end
39
+ ActionView::Base.send(:include, Datagrid::Helper)
@@ -0,0 +1,73 @@
1
+ require "action_view"
2
+
3
+ module Datagrid
4
+ class Renderer
5
+
6
+ def self.for(template)
7
+ new(template)
8
+ end
9
+
10
+ def initialize(template)
11
+ @template = template
12
+ end
13
+
14
+ def format_value(grid, column, asset)
15
+ value = column.html? ? @template.instance_exec(asset, &column.block) : column.value(asset, grid)
16
+ url = column.options[:url] && column.options[:url].call(asset)
17
+ if url
18
+ @template.link_to(value, url)
19
+ else
20
+ case column.format
21
+ when :url
22
+ @template.link_to(column.label ? asset.send(column.label) : I18n.t("datagrid.table.url_label", :default => "URL"), value)
23
+ else
24
+ _safe(value)
25
+ end
26
+ end
27
+ end
28
+
29
+ def table(grid, *args)
30
+ options = args.extract_options!
31
+ options[:html] ||= {}
32
+ options[:html][:class] ||= "datagrid #{grid.class.to_s.underscore.demodulize}"
33
+ assets = args.any? ? args.shift : grid.assets
34
+ paginate = options[:paginate]
35
+ assets = assets.paginate(paginate) if paginate
36
+
37
+ @template.render :partial => "datagrid/table", :locals => {:grid => grid, :options => options, :assets => assets}
38
+ end
39
+
40
+ def header(grid, options = {})
41
+ options[:order] = true unless options.has_key?(:order)
42
+
43
+ @template.render :partial => "datagrid/head", :locals => {:grid => grid, :options => options}
44
+ end
45
+
46
+ def rows(grid, assets, options = {})
47
+ result = assets.map do |asset|
48
+ @template.render :partial => "datagrid/row", :locals => {:grid => grid, :options => options, :asset => asset}
49
+ end.join
50
+
51
+ _safe(result)
52
+ end
53
+
54
+ def order_for(grid, column)
55
+ @template.content_tag(:div, :class => "order") do
56
+ @template.link_to(
57
+ I18n.t("datagrid.table.order.asc", :default => "ASC"),
58
+ @template.url_for(grid.param_name => grid.attributes.merge(:order => column.name, :descending => false)),
59
+ :class => "order asc"
60
+ ) + " " + @template.link_to(
61
+ I18n.t("datagrid.table.order.desc", :default => "DESC"),
62
+ @template.url_for(grid.param_name => grid.attributes.merge(:order => column.name, :descending => true )),
63
+ :class => "order desc"
64
+ )
65
+ end
66
+ end
67
+
68
+
69
+ def _safe(string)
70
+ string.respond_to?(:html_safe) ? string.html_safe : string
71
+ end
72
+ end
73
+ end
@@ -1,5 +1,6 @@
1
1
  require "datagrid"
2
2
 
3
+ #TODO: refactor this experimental shit
3
4
  shared_examples_for "Datagrid" do
4
5
  describe "as Datagrid" do
5
6
 
@@ -9,7 +10,7 @@ shared_examples_for "Datagrid" do
9
10
 
10
11
  its(:data) {should_not be_empty}
11
12
 
12
- described_class.columns.each do |column|
13
+ described_class.columns(:data => true).each do |column|
13
14
  describe "column ##{column.name}" do
14
15
 
15
16
  it "should has value in #data_hash" do
@@ -7,6 +7,16 @@ module Datagrid
7
7
  def booleanize(value)
8
8
  TRUTH.include?(value)
9
9
  end
10
+
11
+ def warn_once(message)
12
+ @warnings ||= {}
13
+ if @warnings[message]
14
+ false
15
+ else
16
+ warn message
17
+ @warnings[message] = true
18
+ end
19
+ end
10
20
  end
11
21
  end
12
22
  end
@@ -0,0 +1,19 @@
1
+ namespace :datagrid do
2
+
3
+ desc "Copy table partials into rails application"
4
+ task :copy_partials do
5
+ require "fileutils"
6
+ def copy_template(path)
7
+ gem_app = File.expand_path("../../../app", __FILE__)
8
+ rails_app = (Rails.root + "app").to_s
9
+ full_path = "#{rails_app}/#{File.dirname path}"
10
+ puts "* copy #{full_path}"
11
+ FileUtils.mkdir_p full_path
12
+ FileUtils.cp "#{gem_app}/#{path}", full_path
13
+ end
14
+ copy_template "views/datagrid/_table.html.erb"
15
+ copy_template "views/datagrid/_head.html.erb"
16
+ copy_template "views/datagrid/_row.html.erb"
17
+ end
18
+
19
+ end
@@ -13,6 +13,10 @@ describe Datagrid::Columns do
13
13
  let!(:entry) { Entry.create!(
14
14
  :group => group, :name => "Star", :disabled => false, :confirmed => false, :category => "first"
15
15
  ) }
16
+
17
+ it "should have data columns without html columns" do
18
+ subject.data_columns.size.should == subject.columns.size - 1
19
+ end
16
20
  it "should build rows of data" do
17
21
  subject.rows.should == [["Pop", "Star"]]
18
22
  end
@@ -34,9 +38,9 @@ describe Datagrid::Columns do
34
38
  }
35
39
  end
36
40
 
37
- it "should support csv export" do
38
- subject.to_csv.should == "Group,Name\nPop,Star\n"
39
- end
41
+ it "should support csv export" do
42
+ subject.to_csv.should == "Group,Name\nPop,Star\n"
43
+ end
40
44
  end
41
45
 
42
46
  it "should support columns with model and report arguments" do
@@ -16,13 +16,4 @@ describe Datagrid::Filters::EnumFilter do
16
16
  end.class.filter_by_name(:group_id).select.should == [1,2]
17
17
  end
18
18
 
19
- it "should stack with other filters" do
20
- Entry.create(:name => "ZZ", :category => "first")
21
- report = test_report(:name => "Pop", :category => "first") do
22
- scope { Entry }
23
- filter(:name)
24
- filter(:category, :enum, :select => ["first", "second"])
25
- end
26
- report.assets.should be_empty
27
- end
28
19
  end
@@ -9,6 +9,16 @@ describe Datagrid::Filters do
9
9
  end.created_at.should == Date.today
10
10
  end
11
11
 
12
+ it "should stack with other filters" do
13
+ Entry.create(:name => "ZZ", :category => "first")
14
+ report = test_report(:name => "Pop", :category => "first") do
15
+ scope { Entry }
16
+ filter(:name)
17
+ filter(:category, :enum, :select => ["first", "second"])
18
+ end
19
+ report.assets.should be_empty
20
+ end
21
+
12
22
  it "should not support array argument for not multiple filter" do
13
23
  report = test_report do
14
24
  scope {Entry}
@@ -20,7 +30,7 @@ describe Datagrid::Filters do
20
30
  end
21
31
 
22
32
 
23
- it "should initialize report Scope table not exists" do
33
+ it "should initialize when report Scope table not exists" do
24
34
  class ModelWithoutTable < ActiveRecord::Base; end
25
35
  ModelWithoutTable.should_not be_table_exists
26
36
  class TheReport
@@ -3,15 +3,22 @@ require "will_paginate"
3
3
  require "active_support/core_ext/hash"
4
4
  require "active_support/core_ext/object"
5
5
 
6
+ require 'datagrid/renderer'
7
+
6
8
  describe Datagrid::Helper do
7
- subject {ActionView::Base.new}
9
+ subject do
10
+ template = ActionView::Base.new
11
+ template.view_paths << File.expand_path("../../../app/views", __FILE__)
12
+ template.view_paths << File.expand_path("../../support/test_partials", __FILE__)
13
+ template
14
+ end
8
15
 
9
16
  before(:each) do
10
17
  subject.stub!(:params).and_return({})
11
18
  subject.stub(:url_for) do |options|
12
19
  options.to_param
13
20
  end
14
-
21
+
15
22
  end
16
23
 
17
24
  let(:group) { Group.create!(:name => "Pop") }
@@ -21,108 +28,119 @@ describe Datagrid::Helper do
21
28
  let(:grid) { SimpleReport.new }
22
29
 
23
30
  describe ".datagrid_table" do
24
- before(:each) do
25
- subject.stub!(:datagrid_order_for).and_return(subject.content_tag(:div, "", :class => "order"))
31
+ it "should have grid class as html class on table" do
32
+ subject.datagrid_table(grid).should match_css_pattern(
33
+ "table.datagrid.simple_report" => 1
34
+ )
26
35
  end
27
36
  it "should return data table html" do
28
- subject.datagrid_table(grid).should equal_to_dom(<<-HTML)
29
- <table class="datagrid">
30
- <tr>
31
- <th class="group">Group<div class="order"></div>
32
- </th>
33
- <th class="name">Name<div class="order"></div>
34
- </th>
35
- </tr>
36
-
37
- <tr>
38
- <td class="group">Pop</td>
39
- <td class="name">Star</td>
40
- </tr>
41
- </table>
42
- HTML
37
+ datagrid_table = subject.datagrid_table(grid)
38
+
39
+ datagrid_table.should match_css_pattern({
40
+ "table.datagrid tr th.group div.order" => 1,
41
+ "table.datagrid tr th.group" => /Group.*/,
42
+ "table.datagrid tr th.name div.order" => 1,
43
+ "table.datagrid tr th.name" => /Name.*/,
44
+ "table.datagrid tr td.group" => "Pop",
45
+ "table.datagrid tr td.name" => "Star"
46
+ })
43
47
  end
48
+
44
49
  it "should support giving assets explicitly" do
45
50
  other_entry = Entry.create!(entry.attributes)
46
- subject.datagrid_table(grid, [entry]).should equal_to_dom(<<-HTML)
47
- <table class="datagrid">
48
- <tr>
49
- <th class="group">Group<div class="order"></div>
50
- </th>
51
- <th class="name">Name<div class="order"></div>
52
- </th>
53
- </tr>
54
-
55
- <tr>
56
- <td class="group">Pop</td>
57
- <td class="name">Star</td>
58
- </tr>
59
- </table>
60
- HTML
61
- end
62
- it "should support giving assets implicitly" do
63
- other_entry = Entry.create!(entry.attributes)
64
- subject.datagrid_table(grid, [entry]).should equal_to_dom(<<-HTML)
65
- <table class="datagrid">
66
- <tr>
67
- <th class="group">Group<div class="order"></div>
68
- </th>
69
- <th class="name">Name<div class="order"></div>
70
- </th>
71
- </tr>
72
-
73
- <tr>
74
- <td class="group">Pop</td>
75
- <td class="name">Star</td>
76
- </tr>
77
- </table>
78
- HTML
51
+ datagrid_table = subject.datagrid_table(grid, [entry])
52
+
53
+ datagrid_table.should match_css_pattern({
54
+ "table.datagrid tr th.group div.order" => 1,
55
+ "table.datagrid tr th.group" => /Group.*/,
56
+ "table.datagrid tr th.name div.order" => 1,
57
+ "table.datagrid tr th.name" => /Name.*/,
58
+ "table.datagrid tr td.group" => "Pop",
59
+ "table.datagrid tr td.name" => "Star"
60
+ })
79
61
  end
80
62
 
81
63
  it "should support cycle option" do
82
- subject.datagrid_rows(grid, [entry], :cycle => ["odd", "even"]).should equal_to_dom(<<-HTML)
83
- <tr class="odd">
84
- <td class="group">Pop</td>
85
- <td class="name">Star</td>
86
- </tr>
87
- HTML
64
+ subject.datagrid_rows(grid, [entry], :cycle => ["odd", "even"]).should match_css_pattern({
65
+ "tr.odd td.group" => "Pop",
66
+ "tr.odd td.name" => "Star"
67
+ })
68
+
88
69
  end
89
70
 
90
- it "should support urls" do
91
- rp = test_report do
92
- scope { Entry }
93
- column(:name, :url => lambda {|model| model.name})
94
- end
95
- subject.datagrid_rows(rp, [entry], {}).should equal_to_dom(<<-HTML)
96
- <tr><td class="name"><a href="Star">Star</a></td></tr>
97
- HTML
71
+ it "should support no order given" do
72
+ subject.datagrid_table(grid, [entry], :order => false).should match_css_pattern("table.datagrid th .order" => 0)
98
73
  end
99
- it "should support conditional urls" do
100
- rp = test_report do
101
- scope { Entry }
102
- column(:name, :url => lambda {false})
74
+
75
+ describe ".datagrid_rows" do
76
+
77
+ it "should support urls" do
78
+ rp = test_report do
79
+ scope { Entry }
80
+ column(:name, :url => lambda {|model| model.name})
81
+ end
82
+ subject.datagrid_rows(rp, [entry]).should match_css_pattern(
83
+ "tr td.name a[href=Star]" => "Star"
84
+ )
85
+ end
86
+ it "should support conditional urls" do
87
+ rp = test_report do
88
+ scope { Entry }
89
+ column(:name, :url => lambda {|model| false})
90
+ end
91
+ subject.datagrid_rows(rp, [entry]).should match_css_pattern(
92
+ "tr td.name" => "Star"
93
+ )
94
+
95
+ end
96
+ it "should add ordering classes to column" do
97
+ rp = test_report(:order => :name) do
98
+ scope { Entry }
99
+ column(:name)
100
+ end
101
+ subject.datagrid_rows(rp, [entry]).should match_css_pattern(
102
+ "tr td.name.ordered.asc" => "Star"
103
+ )
104
+
105
+ end
106
+ it "should add ordering classes to column" do
107
+ rp = test_report(:order => :name, :descending => true) do
108
+ scope { Entry }
109
+ column(:name)
110
+ end
111
+ subject.datagrid_rows(rp, [entry]).should match_css_pattern(
112
+ "tr td.name.ordered.desc" => "Star"
113
+ )
103
114
  end
104
- subject.datagrid_rows(rp, [entry], {}).should equal_to_dom(<<-HTML)
105
- <tr><td class="name">Star</td></tr>
106
- HTML
107
- end
108
- end
109
115
 
110
- describe ".datagrid_order_for" do
111
- it "should render ordreing layout" do
112
- class OrderedGrid
113
- include Datagrid
114
- scope { Entry }
115
- column(:category)
116
+ it "should render html columns" do
117
+
118
+ rp = test_report do
119
+ scope { Entry }
120
+ column(:name, :html => true) do |model|
121
+ content_tag(:span, model.name)
122
+ end
123
+ end
124
+ subject.datagrid_rows(rp, [entry]).should match_css_pattern(
125
+ "tr td.name span" => "Star"
126
+ )
116
127
  end
117
- report = OrderedGrid.new(:descending => true, :order => :category)
118
- subject.datagrid_order_for(report, report.column_by_name(:category)).should equal_to_dom(<<-HTML)
128
+ end
129
+
130
+ describe ".datagrid_order_for" do
131
+ it "should render ordreing layout" do
132
+ class OrderedGrid
133
+ include Datagrid
134
+ scope { Entry }
135
+ column(:category)
136
+ end
137
+ grid = OrderedGrid.new(:descending => true, :order => :category)
138
+ subject.datagrid_order_for(grid, grid.column_by_name(:category)).should equal_to_dom(<<-HTML)
119
139
  <div class="order">
120
140
  <a href="ordered_grid%5Bdescending%5D=false&amp;ordered_grid%5Border%5D=category" class="order asc">ASC</a> <a href="ordered_grid%5Bdescending%5D=true&amp;ordered_grid%5Border%5D=category" class="order desc">DESC</a>
121
141
  </div>
122
- HTML
142
+ HTML
143
+ end
123
144
  end
124
-
125
145
  end
126
-
127
-
128
146
  end
@@ -0,0 +1,14 @@
1
+ require 'spec_helper'
2
+
3
+ describe Datagrid::Utils do
4
+
5
+
6
+ describe ".warn_once" do
7
+ it "should work" do
8
+ silence_warnings do
9
+ Datagrid::Utils.warn_once("hello").should be_true
10
+ end
11
+ Datagrid::Utils.warn_once("hello").should be_false
12
+ end
13
+ end
14
+ end
@@ -19,7 +19,7 @@ require 'datagrid'
19
19
  require "discover"
20
20
  begin
21
21
  require 'ruby-debug'
22
- rescue
22
+ rescue LoadError
23
23
  end
24
24
  require 'rspec'
25
25
  require "logger"
@@ -27,6 +27,7 @@ require "logger"
27
27
  File.open('spec.log', "w").close
28
28
  TEST_LOGGER = Logger.new('spec.log')
29
29
 
30
+
30
31
  RSpec.configure do |config|
31
32
 
32
33
 
@@ -0,0 +1,93 @@
1
+ require "nokogiri"
2
+
3
+ def equal_to_dom(text)
4
+ EqualToDom.new(text)
5
+ end
6
+
7
+
8
+ def include_dom(text)
9
+ IncludeDom.new(text)
10
+ end
11
+
12
+ def match_css_pattern(pattern)
13
+ CssPattern.new(pattern)
14
+ end
15
+
16
+
17
+ class IncludeDom
18
+ def initialize(expectation)
19
+ @expectation = Nokogiri::HTML::DocumentFragment.parse(expectation.strip).to_s
20
+ end
21
+
22
+ def matches?(text)
23
+ @matcher = Nokogiri::HTML::DocumentFragment.parse(text.strip).to_s
24
+ @matcher == @expectation
25
+ end
26
+
27
+ def failure_message
28
+ "Expected dom \n#{@matcher.inspect}\n to include \n#{@expectation.inspect}\n, but it wasn't"
29
+ end
30
+ end
31
+
32
+
33
+ class EqualToDom
34
+
35
+ def initialize(expectation)
36
+ @expectation = Nokogiri::HTML::DocumentFragment.parse(expectation.strip).to_s
37
+ end
38
+
39
+ def matches?(text)
40
+ @matcher = Nokogiri::HTML::DocumentFragment.parse(text.strip).to_s
41
+ @matcher == @expectation
42
+ end
43
+
44
+ def failure_message
45
+ "Expected dom #{@matcher} to match #{@expectation}, but it wasn't"
46
+ end
47
+ end
48
+
49
+
50
+ class CssPattern
51
+ def initialize(pattern)
52
+ @css_pattern = pattern
53
+ end
54
+
55
+ def error!(message)
56
+ @error_message = message
57
+ false
58
+ end
59
+
60
+ def failure_message
61
+ @error_message || ""
62
+ end
63
+
64
+ def matches?(text)
65
+ text = text.clone.force_encoding("UTF-8") if "1.9.3".respond_to? :force_encoding
66
+
67
+ @matcher = Nokogiri::HTML::DocumentFragment.parse(text)
68
+ @css_pattern.each do |css, amount_or_pattern_or_string_or_proc|
69
+ path = @matcher.css(css)
70
+ if amount_or_pattern_or_string_or_proc.is_a?(String) or amount_or_pattern_or_string_or_proc.is_a?(Regexp)
71
+ pattern_or_string = amount_or_pattern_or_string_or_proc
72
+ html = path.inner_html
73
+ if !html.match(pattern_or_string)
74
+ return error!("#{css.inspect} did not match #{pattern_or_string.inspect}. It was \n:#{html.inspect}")
75
+ end
76
+ elsif amount_or_pattern_or_string_or_proc.is_a? Fixnum
77
+ expected_amount = amount_or_pattern_or_string_or_proc
78
+ amount = path.size
79
+ if amount != expected_amount
80
+ return error!("did not find #{css.inspect} #{expected_amount.inspect} times. It was #{amount.inspect}")
81
+ end
82
+ elsif amount_or_pattern_or_string_or_proc.is_a? Proc
83
+ if !amount_or_pattern_or_string_or_proc.call(path)
84
+ return error!("#{css.inspect} did not validate (proc must not return a falsy value)")
85
+ end
86
+ else
87
+ raise "Instance of String, Rexexp, Proc or Fixnum required"
88
+ end
89
+ true
90
+ end
91
+ end
92
+
93
+ end
@@ -36,6 +36,10 @@ class SimpleReport
36
36
  user.name
37
37
  end
38
38
 
39
+ column(:actions, :html => true) do |model|
40
+ render :partial => "actions", :locals => {:model => model}
41
+ end
42
+
39
43
  def param_name
40
44
  :report
41
45
  end
@@ -0,0 +1 @@
1
+ <%= "No action for #{model.name}" -%>
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: datagrid
3
3
  version: !ruby/object:Gem::Version
4
- hash: 13
4
+ hash: 11
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 4
9
- - 1
10
- version: 0.4.1
8
+ - 5
9
+ - 0
10
+ version: 0.5.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Bogdan Gusiev
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-12-06 00:00:00 Z
18
+ date: 2012-01-03 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  type: :runtime
@@ -259,6 +259,9 @@ files:
259
259
  - Rakefile
260
260
  - Readme.markdown
261
261
  - VERSION
262
+ - app/views/datagrid/_head.html.erb
263
+ - app/views/datagrid/_row.html.erb
264
+ - app/views/datagrid/_table.html.erb
262
265
  - datagrid.gemspec
263
266
  - lib/datagrid.rb
264
267
  - lib/datagrid/active_model.rb
@@ -269,6 +272,7 @@ files:
269
272
  - lib/datagrid/drivers/abstract_driver.rb
270
273
  - lib/datagrid/drivers/active_record.rb
271
274
  - lib/datagrid/drivers/mongoid.rb
275
+ - lib/datagrid/engine.rb
272
276
  - lib/datagrid/filters.rb
273
277
  - lib/datagrid/filters/base_filter.rb
274
278
  - lib/datagrid/filters/boolean_enum_filter.rb
@@ -283,8 +287,10 @@ files:
283
287
  - lib/datagrid/form_builder.rb
284
288
  - lib/datagrid/helper.rb
285
289
  - lib/datagrid/ordering.rb
290
+ - lib/datagrid/renderer.rb
286
291
  - lib/datagrid/rspec.rb
287
292
  - lib/datagrid/utils.rb
293
+ - lib/tasks/datagrid_tasks.rake
288
294
  - spec/datagrid/active_model_spec.rb
289
295
  - spec/datagrid/columns_spec.rb
290
296
  - spec/datagrid/drivers/active_record_spec.rb
@@ -296,12 +302,14 @@ files:
296
302
  - spec/datagrid/form_builder_spec.rb
297
303
  - spec/datagrid/helper_spec.rb
298
304
  - spec/datagrid/ordering_spec.rb
305
+ - spec/datagrid/utils_spec.rb
299
306
  - spec/datagrid_spec.rb
300
307
  - spec/spec_helper.rb
301
- - spec/support/equal_to_dom.rb
308
+ - spec/support/active_record.rb
309
+ - spec/support/matchers.rb
302
310
  - spec/support/mongoid.rb
303
- - spec/support/schema.rb
304
311
  - spec/support/simple_report.rb
312
+ - spec/support/test_partials/_actions.html.erb
305
313
  homepage: http://github.com/bogdan/datagrid
306
314
  licenses:
307
315
  - MIT
@@ -1,42 +0,0 @@
1
- require "nokogiri"
2
-
3
- def equal_to_dom(text)
4
- EqualToDom.new(text)
5
- end
6
-
7
-
8
- def include_dom(text)
9
- IncludeDom.new(text)
10
- end
11
-
12
- class IncludeDom
13
- def initialize(expectation)
14
- @expectation = Nokogiri::HTML::DocumentFragment.parse(expectation).to_s
15
- end
16
-
17
- def matches?(text)
18
- @matcher = Nokogiri::HTML::DocumentFragment.parse(text).to_s
19
- @matcher == @expectation
20
- end
21
-
22
- def failure_message
23
- "Expected dom \n#{@matcher.inspect}\n to include \n#{@expectation.inspect}\n, but it wasn't"
24
- end
25
- end
26
-
27
-
28
- class EqualToDom
29
-
30
- def initialize(expectation)
31
- @expectation = Nokogiri::HTML::DocumentFragment.parse(expectation).to_s
32
- end
33
-
34
- def matches?(text)
35
- @matcher = Nokogiri::HTML::DocumentFragment.parse(text).to_s
36
- @matcher == @expectation
37
- end
38
-
39
- def failure_message
40
- "Expected dom #{@matcher} to match #{@expectation}, but it wasn't"
41
- end
42
- end