datagrid 0.8.4 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
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: