datagrid 0.8.4 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.8.4
1
+ 0.9.0
@@ -1,10 +1,10 @@
1
1
  <div class="order">
2
2
  <%= link_to(
3
3
  I18n.t("datagrid.table.order.asc", :default => "&uarr;".html_safe).html_safe,
4
- url_for(grid.param_name => grid.attributes.merge(:order => column.name, :descending => false)),
4
+ url_for(grid.param_name => grid.as_query.merge(:order => column.name, :descending => false)),
5
5
  :class => "asc") %>
6
6
  <%= link_to(
7
7
  I18n.t("datagrid.table.order.desc", :default => "&darr;".html_safe).html_safe,
8
- url_for(grid.param_name => grid.attributes.merge(:order => column.name, :descending => true )),
8
+ url_for(grid.param_name => grid.as_query.merge(:order => column.name, :descending => true )),
9
9
  :class => "desc") %>
10
10
  </div>
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "datagrid"
8
- s.version = "0.8.4"
8
+ s.version = "0.9.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 = "2013-05-22"
12
+ s.date = "2013-06-06"
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 = [
@@ -31,6 +31,7 @@ Gem::Specification.new do |s|
31
31
  "datagrid.gemspec",
32
32
  "lib/datagrid.rb",
33
33
  "lib/datagrid/active_model.rb",
34
+ "lib/datagrid/column_names_attribute.rb",
34
35
  "lib/datagrid/columns.rb",
35
36
  "lib/datagrid/columns/column.rb",
36
37
  "lib/datagrid/configuration.rb",
@@ -63,6 +64,7 @@ Gem::Specification.new do |s|
63
64
  "lib/datagrid/utils.rb",
64
65
  "lib/tasks/datagrid_tasks.rake",
65
66
  "spec/datagrid/active_model_spec.rb",
67
+ "spec/datagrid/column_names_attribute_spec.rb",
66
68
  "spec/datagrid/columns_spec.rb",
67
69
  "spec/datagrid/core_spec.rb",
68
70
  "spec/datagrid/drivers/active_record_spec.rb",
@@ -9,6 +9,7 @@ module Datagrid
9
9
  autoload :ActiveModel
10
10
  autoload :Filters
11
11
  autoload :Columns
12
+ autoload :ColumnNamesAttribute
12
13
  autoload :Ordering
13
14
  autoload :Configuration
14
15
 
@@ -30,6 +31,7 @@ module Datagrid
30
31
  include ::Datagrid::ActiveModel
31
32
  include ::Datagrid::Filters
32
33
  include ::Datagrid::Columns
34
+ include ::Datagrid::ColumnNamesAttribute
33
35
  include ::Datagrid::Ordering
34
36
 
35
37
  end
@@ -0,0 +1,47 @@
1
+ module Datagrid
2
+ module ColumnNamesAttribute
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ class_attribute :columns_array
7
+ self.columns_array = []
8
+
9
+ datagrid_attribute :column_names do |names|
10
+ names = Array(names).reject(&:blank?)
11
+ if names.reject(&:blank?).blank?
12
+ columns.map(&:name)
13
+ else
14
+ names
15
+ end
16
+ end
17
+ end
18
+
19
+ module ClassMethods
20
+ def column_names_filter
21
+ filter(:column_names, :enum, :select => proc { |grid| grid.class.columns.map {|c| [c.header, c.name] }}, :multiple => true ) do |value|
22
+ scoped
23
+ end
24
+ end
25
+ end
26
+
27
+ def columns(*args)
28
+ options = args.extract_options!
29
+ column_names = selected_column_names(*args)
30
+ column_names << options
31
+ super(*column_names)
32
+ end
33
+
34
+ protected
35
+
36
+ def selected_column_names(*args)
37
+ if args.any?
38
+ args.compact!
39
+ args.map!(&:to_sym)
40
+ args
41
+ else
42
+ column_names ? column_names.clone : []
43
+ end
44
+ end
45
+ end
46
+ end
47
+
@@ -11,8 +11,6 @@ module Datagrid
11
11
  base.class_eval do
12
12
 
13
13
  include Datagrid::Core
14
- class_attribute :columns_array
15
- self.columns_array = []
16
14
 
17
15
  end
18
16
  base.send :include, InstanceMethods
@@ -47,13 +45,14 @@ module Datagrid
47
45
  columns_array << Datagrid::Columns::Column.new(self, name, options, &block)
48
46
  end
49
47
 
48
+ # Returns column definition with given name
50
49
  def column_by_name(name)
51
50
  self.columns.find do |col|
52
51
  col.name.to_sym == name.to_sym
53
52
  end
54
53
  end
55
54
 
56
- def inherited(child_class)
55
+ def inherited(child_class) #:nodoc:
57
56
  super(child_class)
58
57
  child_class.columns_array = self.columns_array.clone
59
58
  end
@@ -133,19 +132,29 @@ module Datagrid
133
132
  end
134
133
  end
135
134
 
135
+
136
+ # Returns all columns selected in grid instance
137
+ #
138
+ # Examples:
139
+ #
140
+ # MyGrid.new.columns # => all defined columns
141
+ # grid = MyGrid.new(:column_names => [:id, :name])
142
+ # grid.columns # => id and name columsn
143
+ # grid.columns(:id, :category) # => id and category column
136
144
  def columns(*args)
137
145
  self.class.columns(*args)
138
146
  end
139
147
 
140
148
  def data_columns(*names)
141
- names << {:data => true}
149
+ options = names.extract_options!
150
+ options[:data] = true
151
+ names << options
142
152
  self.columns(*names)
143
153
  end
144
154
 
145
155
  def column_by_name(name)
146
156
  self.class.column_by_name(name)
147
157
  end
148
-
149
158
  end # InstanceMethods
150
159
 
151
160
  end
@@ -94,6 +94,14 @@ module Datagrid
94
94
  end
95
95
  end
96
96
 
97
+ def as_query
98
+ attributes = self.attributes.clone
99
+ attributes.each do |key, value|
100
+ attributes.delete(key) if value.nil?
101
+ end
102
+ attributes
103
+ end
104
+
97
105
  def paginate(*args, &block)
98
106
  ::Datagrid::Utils.warn_once("#paginate is deprecated. Call it like object.assets.paginate(...).")
99
107
  self.assets.paginate(*args, &block)
@@ -20,7 +20,9 @@ class Datagrid::Filters::EnumFilter < Datagrid::Filters::BaseFilter
20
20
  end
21
21
 
22
22
  def include_blank
23
- self.options.has_key?(:include_blank) ? options[:include_blank] : true unless self.prompt
23
+ unless self.prompt
24
+ self.options.has_key?(:include_blank) ? options[:include_blank] : !multiple
25
+ end
24
26
  end
25
27
 
26
28
  def prompt
@@ -4,30 +4,93 @@ require "action_view"
4
4
  module Datagrid
5
5
  module Helper
6
6
 
7
- def datagrid_format_value(report, column, asset)
8
- datagrid_renderer.format_value(report, column, asset)
7
+ # Format an value from datagrid column with given name and for given model
8
+ def datagrid_format_value(report, column_name, model)
9
+ datagrid_renderer.format_value(report, column_name, model)
9
10
  end
10
11
 
12
+ # Renders html table with columns defined in grid class.
13
+ # In the most common used you need to pass paginated collection
14
+ # to datagrid table because datagrid do not have pagination compatibilities:
15
+ #
16
+ # assets = grid.assets.page(params[:page])
17
+ # datagrid_table(grid, assets, options)
18
+ #
19
+ # Supported options:
20
+ #
21
+ # * <tt>:html</tt> - hash of attributes for <table> tag
22
+ # * <tt>:order</tt> - If false do not generate ordering controlls.
23
+ # Default: true.
24
+ # * <tt>:cycle</tt> - Used as arguments for cycle for each row.
25
+ # Default: false. Example: <tt>["odd", "even"]</tt>.
26
+ # * <tt>:columns</tt> - Array of column names to display.
27
+ # Used in case when same grid class is used in different places
28
+ # and needs different columns. Default: all defined columns.
11
29
  def datagrid_table(report, *args)
12
30
  datagrid_renderer.table(report, *args)
13
31
  end
14
32
 
33
+ # Renders HTML table header for given grid instance using columns defined in it
34
+ #
35
+ # Supported options:
36
+ #
37
+ # * <tt>:order</tt> - display ordering controls built-in into header
38
+ # Default: true
39
+ #
15
40
  def datagrid_header(grid, options = {})
16
41
  datagrid_renderer.header(grid, options)
17
42
  end
18
43
 
44
+
45
+ # Renders HTML table rows using given grid definition using columns defined in it
19
46
  def datagrid_rows(report, assets, options = {})
20
47
  datagrid_renderer.rows(report, assets, options)
21
48
  end
22
49
 
50
+ # Renders ordering controls for the given column name
23
51
  def datagrid_order_for(grid, column)
24
52
  datagrid_renderer.order_for(grid, column)
25
53
  end
26
54
 
55
+ # Renders HTML for for grid with all filters inputs and lables defined in it
27
56
  def datagrid_form_for(grid, options = {})
28
57
  datagrid_renderer.form_for(grid, options)
29
58
  end
30
59
 
60
+ # Provides access to datagrid column data.
61
+ #
62
+ # <%= datagrid_row(grid, user) do |row| %>
63
+ # <tr>
64
+ # <td><%= row.first_name %></td>
65
+ # <td><%= row.last_name %></td>
66
+ # </tr>
67
+ # <% end %>
68
+ #
69
+ # Used in case you want to build datagrid table completelly manually
70
+ def datagrid_row(grid, asset, &block)
71
+ HtmlRow.new(self, grid, asset).tap do |row|
72
+ if block_given?
73
+ return capture(row, &block)
74
+ end
75
+ end
76
+ end
77
+
78
+ class HtmlRow
79
+ def initialize(context, grid, asset)
80
+ @context = context
81
+ @grid = grid
82
+ @asset = asset
83
+ end
84
+
85
+ def method_missing(method, *args, &blk)
86
+ if column = @grid.column_by_name(method)
87
+ @context.datagrid_format_value(@grid, column, @asset)
88
+ else
89
+ super
90
+ end
91
+ end
92
+ end
93
+
31
94
  protected
32
95
 
33
96
  def datagrid_renderer
@@ -12,6 +12,9 @@ module Datagrid
12
12
  end
13
13
 
14
14
  def format_value(grid, column, asset)
15
+ if column.is_a?(String) || column.is_a?(Symbol)
16
+ column = grid.column_by_name(column)
17
+ end
15
18
 
16
19
  value = if column.html?
17
20
  args = []
@@ -0,0 +1,7 @@
1
+ require "spec_helper"
2
+
3
+ describe Datagrid::ColumnNamesAttribute do
4
+
5
+ describe ".column_names_filter" do
6
+ end
7
+ end
@@ -53,7 +53,7 @@ describe Datagrid::Columns do
53
53
  it "should support csv export of particular columns" do
54
54
  subject.to_csv(:name).should == "Name\nStar\n"
55
55
  end
56
-
56
+
57
57
  it "should support csv export options" do
58
58
  subject.to_csv(:col_sep => ";").should == "Group;Name;Access level;Pet\nPop;Star;admin;ROTTWEILER\n"
59
59
  end
@@ -92,4 +92,33 @@ describe Datagrid::Columns do
92
92
  child.column_by_name(:group_id).should_not be_nil
93
93
  end
94
94
 
95
+ describe ".column_names attributes" do
96
+ let(:grid) do
97
+ test_report(:column_names => ["id", "name"]) do
98
+ scope { Entry }
99
+ column(:id)
100
+ column(:name)
101
+ column(:category)
102
+ end
103
+ end
104
+ let!(:entry) do
105
+ Entry.create!(:name => 'hello')
106
+ end
107
+ it "should be suppored in header" do
108
+ grid.header.should == ["Id", "Name"]
109
+ end
110
+ it "should be suppored in rows" do
111
+ grid.rows.should == [[entry.id, "hello"]]
112
+ end
113
+
114
+ it "should be suppored in csv" do
115
+ grid.to_csv.should == "Id,Name\n#{entry.id},hello\n"
116
+ end
117
+
118
+ it "should support explicit overwrite" do
119
+ grid.header(:id, :name, :category).should == %w(Id Name Category)
120
+ end
121
+
122
+ end
123
+
95
124
  end
@@ -32,4 +32,5 @@ describe Datagrid::Filters::EnumFilter do
32
32
  filter(:group_id, :enum, :select => proc { raise 'hello' })
33
33
  end
34
34
  end
35
+
35
36
  end
@@ -262,6 +262,41 @@ describe Datagrid::FormBuilder do
262
262
  )}
263
263
 
264
264
  end
265
+
266
+ context "with enum multiple filter" do
267
+ let(:_grid) do
268
+ test_report do
269
+ scope {Entry}
270
+ filter(:group_id, :enum, :select => ['hello'], :multiple => true)
271
+ end
272
+ end
273
+ let(:_filter) { :group_id }
274
+ it { should equal_to_dom(<<HTML) }
275
+ <input name="report[group_id][]" type="hidden" value=""><select class="group_id enum_filter" id="report_group_id" multiple name="report[group_id][]">
276
+ <option value="hello">hello</option></select>
277
+ HTML
278
+
279
+ end
280
+
281
+ context "with column names filter" do
282
+ let(:_grid) do
283
+ test_report(:column_names => [:id, :name]) do
284
+ scope {Entry}
285
+
286
+ column_names_filter
287
+
288
+ column(:id)
289
+ column(:name)
290
+ column(:category)
291
+ end
292
+ end
293
+ let(:_filter) { :column_names }
294
+ it { should equal_to_dom(<<HTML)}
295
+ <input name="report[column_names][]" type="hidden" value=""><select class="column_names enum_filter" id="report_column_names" multiple name="report[column_names][]"><option value="id" selected>Id</option>
296
+ <option value="name" selected>Name</option>
297
+ <option value="category">Category</option></select>
298
+ HTML
299
+ end
265
300
  end
266
301
 
267
302
  describe ".datagrid_label" do
@@ -95,6 +95,25 @@ describe Datagrid::Helper do
95
95
  "table.datagrid td.group" => 0
96
96
  )
97
97
  end
98
+ context "with column_names attribute" do
99
+ let(:grid) do
100
+ test_report(:column_names => "name") do
101
+ scope { Entry }
102
+ column(:name)
103
+ column(:category)
104
+ end
105
+ end
106
+
107
+ it "should output only given column names" do
108
+ subject.datagrid_table(grid, [entry]).should match_css_pattern(
109
+ "table.datagrid th.name" => 1,
110
+ "table.datagrid td.name" => 1,
111
+ "table.datagrid th.category" => 0,
112
+ "table.datagrid td.category" => 0
113
+ )
114
+ end
115
+ end
116
+
98
117
 
99
118
  describe ".datagrid_rows" do
100
119
  it "should support urls" do
@@ -114,7 +133,7 @@ describe Datagrid::Helper do
114
133
  end
115
134
  subject.datagrid_rows(rp, [entry]).should match_css_pattern(
116
135
  "tr td.name" => "Star"
117
- )
136
+ )
118
137
  end
119
138
 
120
139
  it "should add ordering classes to column" do
@@ -186,9 +205,9 @@ describe Datagrid::Helper do
186
205
  it "should render argument-based html blocks with double arguments" do
187
206
  rp = test_report do
188
207
  scope { Entry }
189
- column(:name, :html => lambda { |data, model|
208
+ column(:name, :html => lambda { |data, model|
190
209
  content_tag :h1, "#{data}-#{model.name.downcase}"
191
- })
210
+ })
192
211
  end
193
212
  subject.datagrid_rows(rp, [entry]).should match_css_pattern(
194
213
  "tr td.name h1" => "Star-star"
@@ -198,9 +217,9 @@ describe Datagrid::Helper do
198
217
  it "should render argument-based html blocks with triple arguments" do
199
218
  rp = test_report do
200
219
  scope { Entry }
201
- column(:name, :html => lambda { |data, model, grid|
220
+ column(:name, :html => lambda { |data, model, grid|
202
221
  content_tag :h1, "#{data}-#{model.name.downcase}-#{grid.assets.klass}"
203
- })
222
+ })
204
223
  end
205
224
  subject.datagrid_rows(rp, [entry]).should match_css_pattern(
206
225
  "tr td.name h1" => "Star-star-Entry"
@@ -210,11 +229,11 @@ describe Datagrid::Helper do
210
229
  it "should render argument-based html blocks with double arguments and custom data" do
211
230
  rp = test_report do
212
231
  scope { Entry }
213
- column(:name, :html => lambda { |data, model|
232
+ column(:name, :html => lambda { |data, model|
214
233
  content_tag :h1, "#{data}-#{model.name}"
215
234
  }) do
216
235
  self.name.upcase
217
- end
236
+ end
218
237
  end
219
238
  subject.datagrid_rows(rp, [entry]).should match_css_pattern(
220
239
  "tr td.name h1" => "STAR-Star"
@@ -224,11 +243,11 @@ describe Datagrid::Helper do
224
243
  it "should render argument-based html blocks with triple arguments and custom data" do
225
244
  rp = test_report do
226
245
  scope { Entry }
227
- column(:name, :html => lambda { |data, model, grid|
246
+ column(:name, :html => lambda { |data, model, grid|
228
247
  content_tag :h1, "#{data}-#{model.name}-#{grid.assets.klass}"
229
248
  }) do
230
249
  self.name.upcase
231
- end
250
+ end
232
251
  end
233
252
  subject.datagrid_rows(rp, [entry]).should match_css_pattern(
234
253
  "tr td.name h1" => "STAR-Star-Entry"
@@ -295,5 +314,52 @@ describe Datagrid::Helper do
295
314
  )
296
315
  end
297
316
  end
317
+
318
+ describe ".datagrid_row" do
319
+ let(:grid) do
320
+ test_report do
321
+ scope { Entry }
322
+ column(:name)
323
+ column(:category)
324
+ end
325
+ end
326
+
327
+ let(:entry) do
328
+ Entry.create!(:name => "Hello", :category => "greetings")
329
+ end
330
+
331
+ it "should provide access to row data" do
332
+ r = subject.datagrid_row(grid, entry)
333
+ r.name.should == "Hello"
334
+ r.category.should == "greetings"
335
+ end
336
+ it "should yield block" do
337
+ subject.datagrid_row(grid, entry) do |row|
338
+ row.name.should == "Hello"
339
+ row.category.should == "greetings"
340
+ end
341
+ end
342
+
343
+ it "should output data from block" do
344
+ name = subject.datagrid_row(grid, entry) do |row|
345
+ subject.concat(row.name)
346
+ subject.concat(",")
347
+ subject.concat(row.category)
348
+ end
349
+ name.should == "Hello,greetings"
350
+ end
351
+ end
352
+ end
353
+
354
+ describe ".datagrid_format_value" do
355
+ it "should format value by column name" do
356
+ report = test_report do
357
+ scope {Entry}
358
+ column(:name) do |e|
359
+ "<b>#{e.name}</b>"
360
+ end
361
+ end
362
+ subject.datagrid_format_value(report, :name, entry).should == "<b>Star</b>"
363
+ end
298
364
  end
299
365
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: datagrid
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.4
4
+ version: 0.9.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-05-22 00:00:00.000000000 Z
12
+ date: 2013-06-06 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
@@ -258,6 +258,7 @@ files:
258
258
  - datagrid.gemspec
259
259
  - lib/datagrid.rb
260
260
  - lib/datagrid/active_model.rb
261
+ - lib/datagrid/column_names_attribute.rb
261
262
  - lib/datagrid/columns.rb
262
263
  - lib/datagrid/columns/column.rb
263
264
  - lib/datagrid/configuration.rb
@@ -290,6 +291,7 @@ files:
290
291
  - lib/datagrid/utils.rb
291
292
  - lib/tasks/datagrid_tasks.rake
292
293
  - spec/datagrid/active_model_spec.rb
294
+ - spec/datagrid/column_names_attribute_spec.rb
293
295
  - spec/datagrid/columns_spec.rb
294
296
  - spec/datagrid/core_spec.rb
295
297
  - spec/datagrid/drivers/active_record_spec.rb
@@ -335,7 +337,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
335
337
  version: '0'
336
338
  segments:
337
339
  - 0
338
- hash: -3876339943882620778
340
+ hash: 1228935778461264019
339
341
  required_rubygems_version: !ruby/object:Gem::Requirement
340
342
  none: false
341
343
  requirements: