datagrid 0.9.0 → 0.9.2
Sign up to get free protection for your applications and to get access to all the features.
- data/Readme.markdown +4 -3
- data/VERSION +1 -1
- data/app/views/datagrid/_head.html.erb +1 -1
- data/app/views/datagrid/_row.html.erb +1 -1
- data/datagrid.gemspec +2 -2
- data/lib/datagrid/column_names_attribute.rb +2 -1
- data/lib/datagrid/columns.rb +100 -7
- data/lib/datagrid/columns/column.rb +76 -26
- data/lib/datagrid/core.rb +16 -6
- data/lib/datagrid/filters.rb +26 -2
- data/lib/datagrid/filters/base_filter.rb +4 -4
- data/lib/datagrid/filters/date_filter.rb +1 -1
- data/lib/datagrid/filters/enum_filter.rb +6 -4
- data/lib/datagrid/form_builder.rb +3 -3
- data/lib/datagrid/helper.rb +2 -4
- data/lib/datagrid/renderer.rb +7 -24
- data/lib/datagrid/utils.rb +13 -0
- data/spec/datagrid/columns_spec.rb +45 -6
- data/spec/datagrid/core_spec.rb +32 -8
- data/spec/datagrid/filters/enum_filter_spec.rb +13 -0
- data/spec/datagrid/filters_spec.rb +24 -1
- data/spec/datagrid/form_builder_spec.rb +39 -8
- data/spec/datagrid/helper_spec.rb +30 -1
- data/spec/support/simple_report.rb +16 -9
- metadata +3 -3
data/Readme.markdown
CHANGED
@@ -13,6 +13,7 @@ Ruby library that helps you to build and represent table-like data with:
|
|
13
13
|
* ActiveRecord
|
14
14
|
* Mongoid
|
15
15
|
* MongoMapper
|
16
|
+
* Array (slow but possible)
|
16
17
|
|
17
18
|
[Create an issue](https://github.com/bogdan/datagrid/issues/new) if you want more.
|
18
19
|
|
@@ -40,8 +41,8 @@ class SimpleReport
|
|
40
41
|
filter(:disabled, :eboolean)
|
41
42
|
filter(:confirmed, :boolean)
|
42
43
|
filter(:group_id, :integer, :multiple => true)
|
43
|
-
filter(:logins_count, :integer, :range => true)
|
44
|
-
filter(:group_name, :string, :header => "Group") do |value|
|
44
|
+
filter(:logins_count, :integer, :range => true, :before => :group_id)
|
45
|
+
filter(:group_name, :string, :header => "Group", :after => :category_id) do |value|
|
45
46
|
self.joins(:group).where(:groups => {:name => value})
|
46
47
|
end
|
47
48
|
|
@@ -129,7 +130,7 @@ Datagrid supports different type of filters including:
|
|
129
130
|
Each column is represented by name and code block to calculate the value.
|
130
131
|
|
131
132
|
``` ruby
|
132
|
-
column(:activated, :header => "Active", :order => "activated") do
|
133
|
+
column(:activated, :header => "Active", :order => "activated", :after => :name) do
|
133
134
|
self.activated?
|
134
135
|
end
|
135
136
|
```
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.9.
|
1
|
+
0.9.2
|
@@ -1,5 +1,5 @@
|
|
1
1
|
<tr>
|
2
|
-
<% grid.
|
2
|
+
<% grid.html_columns(*options[:columns]).each do |column| %>
|
3
3
|
<th class="<%= datagrid_column_classes(grid, column) %>">
|
4
4
|
<%= column.header %>
|
5
5
|
<%= datagrid_order_for(grid, column) if column.order && options[:order]%>
|
@@ -1,5 +1,5 @@
|
|
1
1
|
<tr class="<%= options[:cycle] && cycle(*options[:cycle]) %>">
|
2
|
-
<% grid.
|
2
|
+
<% grid.html_columns(*options[:columns]).each do |column| %>
|
3
3
|
<td class="<%= datagrid_column_classes(grid, column) %>"><%= datagrid_format_value(grid, column, asset) %></td>
|
4
4
|
<% end %>
|
5
5
|
</tr>
|
data/datagrid.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "datagrid"
|
8
|
-
s.version = "0.9.
|
8
|
+
s.version = "0.9.2"
|
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-
|
12
|
+
s.date = "2013-08-23"
|
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 = [
|
@@ -17,6 +17,7 @@ module Datagrid
|
|
17
17
|
end
|
18
18
|
|
19
19
|
module ClassMethods
|
20
|
+
# Adds a filter that acts like a column selection
|
20
21
|
def column_names_filter
|
21
22
|
filter(:column_names, :enum, :select => proc { |grid| grid.class.columns.map {|c| [c.header, c.name] }}, :multiple => true ) do |value|
|
22
23
|
scoped
|
@@ -24,7 +25,7 @@ module Datagrid
|
|
24
25
|
end
|
25
26
|
end
|
26
27
|
|
27
|
-
def columns(*args)
|
28
|
+
def columns(*args) #:nodoc:
|
28
29
|
options = args.extract_options!
|
29
30
|
column_names = selected_column_names(*args)
|
30
31
|
column_names << options
|
data/lib/datagrid/columns.rb
CHANGED
@@ -32,17 +32,36 @@ module Datagrid
|
|
32
32
|
args.compact!
|
33
33
|
args.map!(&:to_sym)
|
34
34
|
columns_array.select do |column|
|
35
|
-
(!options[:data] || column.data?) && (args.empty? || args.include?(column.name))
|
35
|
+
(!options[:data] || column.data?) && (!options[:html] || column.html?)&& (args.empty? || args.include?(column.name))
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
39
39
|
# Defines new datagrid column
|
40
|
+
#
|
41
|
+
# Arguments:
|
42
|
+
#
|
43
|
+
# * <tt>name</tt> - column name
|
44
|
+
# * <tt>options</tt> - hash of options
|
45
|
+
# * <tt>block</tt> - proc to calculate a column value
|
46
|
+
#
|
47
|
+
# Available options:
|
48
|
+
#
|
49
|
+
# * <tt>:html</tt> - determines if current column should be present in html table and how is it formatted
|
50
|
+
# * <tt>:order</tt> - determines if this column could be sortable and how
|
51
|
+
# * <tt>:order_desc</tt> - determines a descending order for given column (only in case when <tt>:order</tt> can not be easily inverted
|
52
|
+
# * <tt>:url</tt> - a proc with one argument, pass this option to easily convert the value into an URL
|
53
|
+
# * <tt>:before</tt> - determines the position of this column, by adding it before the column passed here
|
54
|
+
# * <tt>:after</tt> - determines the position of this column, by adding it after the column passed here
|
55
|
+
#
|
56
|
+
# See: https://github.com/bogdan/datagrid/wiki/Columns for examples
|
40
57
|
def column(name, options = {}, &block)
|
41
58
|
check_scope_defined!("Scope should be defined before columns")
|
42
59
|
block ||= lambda do |model|
|
43
60
|
model.send(name)
|
44
61
|
end
|
45
|
-
|
62
|
+
position = Datagrid::Utils.extract_position_from_options(columns_array, options)
|
63
|
+
column = Datagrid::Columns::Column.new(self, name, options, &block)
|
64
|
+
columns_array.insert(position, column)
|
46
65
|
end
|
47
66
|
|
48
67
|
# Returns column definition with given name
|
@@ -52,6 +71,30 @@ module Datagrid
|
|
52
71
|
end
|
53
72
|
end
|
54
73
|
|
74
|
+
# Returns an array of all defined column names
|
75
|
+
def column_names
|
76
|
+
columns.map(&:name)
|
77
|
+
end
|
78
|
+
|
79
|
+
def respond_to(&block) #:nodoc:
|
80
|
+
Datagrid::Columns::Column::ResponseFormat.new(&block)
|
81
|
+
end
|
82
|
+
|
83
|
+
def format(value, &block)
|
84
|
+
if block_given?
|
85
|
+
respond_to do |f|
|
86
|
+
f.data { value }
|
87
|
+
f.html do
|
88
|
+
instance_exec(value, &block)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
else
|
92
|
+
# Ruby Object#format exists.
|
93
|
+
# We don't want to change the behaviour and overwrite it.
|
94
|
+
super
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
55
98
|
def inherited(child_class) #:nodoc:
|
56
99
|
super(child_class)
|
57
100
|
child_class.columns_array = self.columns_array.clone
|
@@ -62,14 +105,22 @@ module Datagrid
|
|
62
105
|
module InstanceMethods
|
63
106
|
|
64
107
|
# Returns <tt>Array</tt> of human readable column names. See also "Localization" section
|
108
|
+
#
|
109
|
+
# Arguments:
|
110
|
+
#
|
111
|
+
# * <tt>column_names</tt> - list of column names if you want to limit data only to specified columns
|
65
112
|
def header(*column_names)
|
66
113
|
data_columns(*column_names).map(&:header)
|
67
114
|
end
|
68
115
|
|
69
116
|
# Returns <tt>Array</tt> column values for given asset
|
117
|
+
#
|
118
|
+
# Arguments:
|
119
|
+
#
|
120
|
+
# * <tt>column_names</tt> - list of column names if you want to limit data only to specified columns
|
70
121
|
def row_for(asset, *column_names)
|
71
122
|
data_columns(*column_names).map do |column|
|
72
|
-
column.
|
123
|
+
column.data_value(asset, self)
|
73
124
|
end
|
74
125
|
end
|
75
126
|
|
@@ -77,12 +128,16 @@ module Datagrid
|
|
77
128
|
def hash_for(asset)
|
78
129
|
result = {}
|
79
130
|
self.data_columns.each do |column|
|
80
|
-
result[column.name] = column.
|
131
|
+
result[column.name] = column.data_value(asset, self)
|
81
132
|
end
|
82
133
|
result
|
83
134
|
end
|
84
135
|
|
85
136
|
# Returns Array of Arrays with data for each row in datagrid assets without header.
|
137
|
+
#
|
138
|
+
# Arguments:
|
139
|
+
#
|
140
|
+
# * <tt>column_names</tt> - list of column names if you want to limit data only to specified columns
|
86
141
|
def rows(*column_names)
|
87
142
|
#TODO: find in batches
|
88
143
|
self.assets.map do |asset|
|
@@ -91,12 +146,30 @@ module Datagrid
|
|
91
146
|
end
|
92
147
|
|
93
148
|
# Returns Array of Arrays with data for each row in datagrid assets with header.
|
94
|
-
|
95
|
-
|
149
|
+
#
|
150
|
+
# Arguments:
|
151
|
+
#
|
152
|
+
# * <tt>column_names</tt> - list of column names if you want to limit data only to specified columns
|
153
|
+
def data(*column_names)
|
154
|
+
self.rows(*column_names).unshift(self.header(*column_names))
|
96
155
|
end
|
97
156
|
|
98
157
|
# Return Array of Hashes where keys are column names and values are column values
|
99
158
|
# for each row in datagrid <tt>#assets</tt>
|
159
|
+
#
|
160
|
+
# Example:
|
161
|
+
#
|
162
|
+
# class MyGrid
|
163
|
+
# scope { Model }
|
164
|
+
# column(:id)
|
165
|
+
# column(:name)
|
166
|
+
# end
|
167
|
+
#
|
168
|
+
# Model.create!(:name => "One")
|
169
|
+
# Model.create!(:name => "Two")
|
170
|
+
#
|
171
|
+
# MyGrid.new.data_hash # => [{:name => "One"}, {:name => "Two"}]
|
172
|
+
#
|
100
173
|
def data_hash
|
101
174
|
self.assets.map do |asset|
|
102
175
|
hash_for(asset)
|
@@ -139,12 +212,13 @@ module Datagrid
|
|
139
212
|
#
|
140
213
|
# MyGrid.new.columns # => all defined columns
|
141
214
|
# grid = MyGrid.new(:column_names => [:id, :name])
|
142
|
-
# grid.columns # => id and name
|
215
|
+
# grid.columns # => id and name columns
|
143
216
|
# grid.columns(:id, :category) # => id and category column
|
144
217
|
def columns(*args)
|
145
218
|
self.class.columns(*args)
|
146
219
|
end
|
147
220
|
|
221
|
+
# Returns all columns that can be represented in plain data(non-html) way
|
148
222
|
def data_columns(*names)
|
149
223
|
options = names.extract_options!
|
150
224
|
options[:data] = true
|
@@ -152,9 +226,28 @@ module Datagrid
|
|
152
226
|
self.columns(*names)
|
153
227
|
end
|
154
228
|
|
229
|
+
# Returns all columns that can be represented in HTML table
|
230
|
+
def html_columns(*names)
|
231
|
+
options = names.extract_options!
|
232
|
+
options[:html] = true
|
233
|
+
names << options
|
234
|
+
self.columns(*names)
|
235
|
+
end
|
236
|
+
|
237
|
+
# Finds a column by name
|
155
238
|
def column_by_name(name)
|
156
239
|
self.class.column_by_name(name)
|
157
240
|
end
|
241
|
+
|
242
|
+
|
243
|
+
def format(value, &block)
|
244
|
+
if block_given?
|
245
|
+
self.class.format(value, &block)
|
246
|
+
else
|
247
|
+
super
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
158
251
|
end # InstanceMethods
|
159
252
|
|
160
253
|
end
|
@@ -1,41 +1,52 @@
|
|
1
1
|
class Datagrid::Columns::Column
|
2
2
|
|
3
|
-
|
3
|
+
class ResponseFormat # :nodoc:
|
4
4
|
|
5
|
-
|
6
|
-
|
5
|
+
attr_accessor :data_block, :html_block
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
yield(self)
|
9
|
+
end
|
10
|
+
|
11
|
+
def data(&block)
|
12
|
+
self.data_block = block
|
13
|
+
end
|
14
|
+
|
15
|
+
def html(&block)
|
16
|
+
self.html_block = block
|
17
|
+
end
|
18
|
+
|
19
|
+
def data_value
|
20
|
+
data_block.call
|
21
|
+
end
|
22
|
+
|
23
|
+
def html_value(context)
|
24
|
+
context.instance_eval(&html_block)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
attr_accessor :grid_class, :options, :data_block, :name, :html_block
|
29
|
+
|
30
|
+
def initialize(grid_class, name, options = {}, &block)
|
31
|
+
self.grid_class = grid_class
|
7
32
|
self.name = name.to_sym
|
8
33
|
self.options = options
|
9
34
|
if options[:html] == true
|
10
35
|
self.html_block = block
|
11
36
|
else
|
37
|
+
self.data_block = block
|
38
|
+
|
12
39
|
if options[:html].is_a? Proc
|
13
40
|
self.html_block = options[:html]
|
14
41
|
end
|
15
|
-
self.block = block
|
16
|
-
end
|
17
|
-
if format
|
18
|
-
::Datagrid::Utils.warn_once(":format column option is deprecated. Use :url or :html option instead.")
|
19
42
|
end
|
20
43
|
end
|
21
44
|
|
22
|
-
def
|
23
|
-
|
45
|
+
def data_value(model, grid)
|
46
|
+
result = generic_value(model,grid)
|
47
|
+
result.is_a?(ResponseFormat) ? result.data_value : result
|
24
48
|
end
|
25
49
|
|
26
|
-
def value_for(model, grid)
|
27
|
-
if self.block.arity == 1
|
28
|
-
self.block.call(model)
|
29
|
-
elsif self.block.arity == 2
|
30
|
-
self.block.call(model, grid)
|
31
|
-
else
|
32
|
-
model.instance_eval(&self.block)
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
def format
|
37
|
-
self.options[:format]
|
38
|
-
end
|
39
50
|
|
40
51
|
def label
|
41
52
|
self.options[:label]
|
@@ -43,14 +54,14 @@ class Datagrid::Columns::Column
|
|
43
54
|
|
44
55
|
def header
|
45
56
|
self.options[:header] ||
|
46
|
-
I18n.translate(self.name, :scope => "datagrid.#{self.
|
57
|
+
I18n.translate(self.name, :scope => "datagrid.#{self.grid_class.param_name}.columns", :default => self.name.to_s.humanize )
|
47
58
|
end
|
48
59
|
|
49
60
|
def order
|
50
61
|
if options.has_key?(:order)
|
51
62
|
self.options[:order]
|
52
63
|
else
|
53
|
-
|
64
|
+
grid_class.driver.default_order(grid_class.scope, name)
|
54
65
|
end
|
55
66
|
end
|
56
67
|
|
@@ -60,11 +71,50 @@ class Datagrid::Columns::Column
|
|
60
71
|
end
|
61
72
|
|
62
73
|
def html?
|
63
|
-
|
74
|
+
options[:html] != false
|
64
75
|
end
|
65
76
|
|
66
77
|
def data?
|
67
|
-
self.
|
78
|
+
self.data_block != nil
|
79
|
+
end
|
80
|
+
|
81
|
+
def html_value(context, asset, grid)
|
82
|
+
if html? && html_block
|
83
|
+
value_from_html_block(context, asset, grid)
|
84
|
+
else
|
85
|
+
result = generic_value(asset,grid)
|
86
|
+
result.is_a?(ResponseFormat) ? result.html_value(context) : result
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def value_from_html_block(context, asset, grid)
|
91
|
+
args = []
|
92
|
+
remaining_arity = html_block.arity
|
93
|
+
|
94
|
+
if data?
|
95
|
+
args << data_value(asset,grid)
|
96
|
+
remaining_arity -= 1
|
97
|
+
end
|
98
|
+
|
99
|
+
args << asset if remaining_arity > 0
|
100
|
+
args << grid if remaining_arity > 1
|
101
|
+
|
102
|
+
return context.instance_exec(*args, &html_block)
|
103
|
+
end
|
104
|
+
|
105
|
+
def block
|
106
|
+
Datagrid::Utils.warn_once("Datagrid::Columns::Column#block is deprecated. Use #html_block or #data_block instead")
|
107
|
+
data_block
|
108
|
+
end
|
109
|
+
|
110
|
+
def generic_value(model, grid)
|
111
|
+
if self.data_block.arity == 1
|
112
|
+
self.data_block.call(model)
|
113
|
+
elsif self.data_block.arity == 2
|
114
|
+
self.data_block.call(model, grid)
|
115
|
+
else
|
116
|
+
model.instance_eval(&self.data_block)
|
117
|
+
end
|
68
118
|
end
|
69
119
|
|
70
120
|
end
|
data/lib/datagrid/core.rb
CHANGED
@@ -16,7 +16,7 @@ module Datagrid
|
|
16
16
|
|
17
17
|
module ClassMethods
|
18
18
|
|
19
|
-
def datagrid_attribute(name, &block)
|
19
|
+
def datagrid_attribute(name, &block) #:nodoc:
|
20
20
|
unless datagrid_attributes.include?(name)
|
21
21
|
block ||= lambda do |value|
|
22
22
|
value
|
@@ -32,6 +32,7 @@ module Datagrid
|
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
|
+
# Defines a scope at class level
|
35
36
|
def scope(&block)
|
36
37
|
if block
|
37
38
|
self.scope_value = block
|
@@ -41,7 +42,7 @@ module Datagrid
|
|
41
42
|
end
|
42
43
|
end
|
43
44
|
|
44
|
-
def driver
|
45
|
+
def driver #:nodoc:
|
45
46
|
@driver ||= Drivers::AbstractDriver.guess_driver(scope).new
|
46
47
|
end
|
47
48
|
|
@@ -60,12 +61,16 @@ module Datagrid
|
|
60
61
|
|
61
62
|
module InstanceMethods
|
62
63
|
|
63
|
-
def initialize(attributes = nil)
|
64
|
+
def initialize(attributes = nil, &block)
|
64
65
|
super()
|
65
66
|
|
66
67
|
if attributes
|
67
68
|
self.attributes = attributes
|
68
69
|
end
|
70
|
+
|
71
|
+
if block_given?
|
72
|
+
self.scope_value = block
|
73
|
+
end
|
69
74
|
end
|
70
75
|
|
71
76
|
def attributes
|
@@ -88,11 +93,14 @@ module Datagrid
|
|
88
93
|
driver.to_scope(scope)
|
89
94
|
end
|
90
95
|
|
91
|
-
|
96
|
+
|
97
|
+
def assign_attributes(attributes)
|
92
98
|
attributes.each do |name, value|
|
93
99
|
self[name] = value
|
94
100
|
end
|
101
|
+
self
|
95
102
|
end
|
103
|
+
alias attributes= assign_attributes
|
96
104
|
|
97
105
|
def as_query
|
98
106
|
attributes = self.attributes.clone
|
@@ -111,17 +119,19 @@ module Datagrid
|
|
111
119
|
if block_given?
|
112
120
|
self.scope_value = block
|
113
121
|
self
|
122
|
+
elsif scope_value
|
123
|
+
scope_value.call
|
114
124
|
else
|
115
125
|
check_scope_defined!
|
116
126
|
scope_value.call
|
117
127
|
end
|
118
128
|
end
|
119
129
|
|
120
|
-
def driver
|
130
|
+
def driver #:nodoc:
|
121
131
|
self.class.driver
|
122
132
|
end
|
123
133
|
|
124
|
-
def check_scope_defined!(message = nil)
|
134
|
+
def check_scope_defined!(message = nil) #:nodoc:
|
125
135
|
self.class.send :check_scope_defined!, message
|
126
136
|
end
|
127
137
|
|
data/lib/datagrid/filters.rb
CHANGED
@@ -46,6 +46,25 @@ module Datagrid
|
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
49
|
+
# Defines new datagrid filter
|
50
|
+
#
|
51
|
+
# Arguments:
|
52
|
+
#
|
53
|
+
# * <tt>name</tt> - filter name
|
54
|
+
# * <tt>options</tt> - hash of options
|
55
|
+
# * <tt>block</tt> - proc to apply the filter
|
56
|
+
#
|
57
|
+
# Available options:
|
58
|
+
#
|
59
|
+
# * <tt>:header</tt> - determines the header of the filter
|
60
|
+
# * <tt>:default</tt> - the default filter value
|
61
|
+
# * <tt>:multiple</tt> - determines if more than one option can be selected
|
62
|
+
# * <tt>:allow_nil</tt> - determines if the value can be nil
|
63
|
+
# * <tt>:allow_blank</tt> - determines if the value can be blank
|
64
|
+
# * <tt>:before</tt> - determines the position of this filter, by adding it before the filter passed here (when using datagrid_form_for helper)
|
65
|
+
# * <tt>:after</tt> - determines the position of this filter, by adding it after the filter passed here (when using datagrid_form_for helper)
|
66
|
+
#
|
67
|
+
# See: https://github.com/bogdan/datagrid/wiki/Columns for examples
|
49
68
|
def filter(attribute, *args, &block)
|
50
69
|
options = args.extract_options!
|
51
70
|
type = args.shift || :default
|
@@ -53,9 +72,9 @@ module Datagrid
|
|
53
72
|
klass = type.is_a?(Class) ? type : FILTER_TYPES[type]
|
54
73
|
raise ConfigurationError, "filter class #{type.inspect} not found" unless klass
|
55
74
|
|
56
|
-
|
75
|
+
position = Datagrid::Utils.extract_position_from_options(self.filters, options)
|
57
76
|
filter = klass.new(self, attribute, options, &block)
|
58
|
-
self.filters
|
77
|
+
self.filters.insert(position, filter)
|
59
78
|
|
60
79
|
datagrid_attribute(attribute) do |value|
|
61
80
|
filter.parse_values(value)
|
@@ -97,6 +116,11 @@ module Datagrid
|
|
97
116
|
self[filter.name]
|
98
117
|
end
|
99
118
|
|
119
|
+
# Returns filter object with the given name
|
120
|
+
def filter_by_name(name)
|
121
|
+
self.class.filter_by_name(name)
|
122
|
+
end
|
123
|
+
|
100
124
|
end # InstanceMethods
|
101
125
|
|
102
126
|
end
|
@@ -3,10 +3,10 @@ end
|
|
3
3
|
|
4
4
|
class Datagrid::Filters::BaseFilter
|
5
5
|
|
6
|
-
attr_accessor :
|
6
|
+
attr_accessor :grid_class, :options, :block, :name
|
7
7
|
|
8
8
|
def initialize(grid_class, name, options = {}, &block)
|
9
|
-
self.
|
9
|
+
self.grid_class = grid_class
|
10
10
|
self.name = name
|
11
11
|
self.options = options
|
12
12
|
self.block = block || default_filter_block
|
@@ -33,7 +33,7 @@ class Datagrid::Filters::BaseFilter
|
|
33
33
|
|
34
34
|
def parse_values(value)
|
35
35
|
if !self.multiple && value.is_a?(Array)
|
36
|
-
raise Datagrid::ArgumentError, "#{
|
36
|
+
raise Datagrid::ArgumentError, "#{grid_class}##{name} filter can not accept Array argument. Use :multiple option."
|
37
37
|
end
|
38
38
|
values = Array.wrap(value)
|
39
39
|
values.map! do |v|
|
@@ -44,7 +44,7 @@ class Datagrid::Filters::BaseFilter
|
|
44
44
|
|
45
45
|
def header
|
46
46
|
options[:header] ||
|
47
|
-
I18n.translate(self.name, :scope => "datagrid.#{
|
47
|
+
I18n.translate(self.name, :scope => "datagrid.#{grid_class.param_name}.filters", :default => self.name.to_s.humanize)
|
48
48
|
end
|
49
49
|
|
50
50
|
def default
|
@@ -11,11 +11,13 @@ class Datagrid::Filters::EnumFilter < Datagrid::Filters::BaseFilter
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def select(object = nil)
|
14
|
-
|
15
|
-
if
|
16
|
-
|
14
|
+
select = self.options[:select]
|
15
|
+
if select.is_a?(Symbol)
|
16
|
+
object.send(select)
|
17
|
+
elsif select.respond_to?(:call)
|
18
|
+
select.arity == 1 ? select.call(object) : select.call
|
17
19
|
else
|
18
|
-
|
20
|
+
select
|
19
21
|
end
|
20
22
|
end
|
21
23
|
|
@@ -94,13 +94,13 @@ module Datagrid
|
|
94
94
|
end
|
95
95
|
|
96
96
|
def datagrid_get_attribute(attribute_or_filter)
|
97
|
-
|
97
|
+
Utils.string_like?(attribute_or_filter) ? attribute_or_filter : attribute_or_filter.name
|
98
98
|
end
|
99
99
|
|
100
100
|
def datagrid_get_filter(attribute_or_filter)
|
101
|
-
if
|
101
|
+
if Utils.string_like?(attribute_or_filter)
|
102
102
|
object.class.filter_by_name(attribute_or_filter) ||
|
103
|
-
raise(Error, "filter #{attribute_or_filter} not found")
|
103
|
+
raise(Error, "Datagrid filter #{attribute_or_filter} not found")
|
104
104
|
else
|
105
105
|
attribute_or_filter
|
106
106
|
end
|
data/lib/datagrid/helper.rb
CHANGED
@@ -21,8 +21,6 @@ module Datagrid
|
|
21
21
|
# * <tt>:html</tt> - hash of attributes for <table> tag
|
22
22
|
# * <tt>:order</tt> - If false do not generate ordering controlls.
|
23
23
|
# Default: true.
|
24
|
-
# * <tt>:cycle</tt> - Used as arguments for cycle for each row.
|
25
|
-
# Default: false. Example: <tt>["odd", "even"]</tt>.
|
26
24
|
# * <tt>:columns</tt> - Array of column names to display.
|
27
25
|
# Used in case when same grid class is used in different places
|
28
26
|
# and needs different columns. Default: all defined columns.
|
@@ -57,7 +55,7 @@ module Datagrid
|
|
57
55
|
datagrid_renderer.form_for(grid, options)
|
58
56
|
end
|
59
57
|
|
60
|
-
# Provides access to datagrid
|
58
|
+
# Provides access to datagrid columns data.
|
61
59
|
#
|
62
60
|
# <%= datagrid_row(grid, user) do |row| %>
|
63
61
|
# <tr>
|
@@ -66,7 +64,7 @@ module Datagrid
|
|
66
64
|
# </tr>
|
67
65
|
# <% end %>
|
68
66
|
#
|
69
|
-
# Used in case you want to build
|
67
|
+
# Used in case you want to build html table completelly manually
|
70
68
|
def datagrid_row(grid, asset, &block)
|
71
69
|
HtmlRow.new(self, grid, asset).tap do |row|
|
72
70
|
if block_given?
|
data/lib/datagrid/renderer.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require "action_view"
|
2
2
|
|
3
3
|
module Datagrid
|
4
|
-
class Renderer
|
4
|
+
class Renderer #:nodoc:
|
5
5
|
|
6
6
|
def self.for(template)
|
7
7
|
new(template)
|
@@ -16,33 +16,13 @@ module Datagrid
|
|
16
16
|
column = grid.column_by_name(column)
|
17
17
|
end
|
18
18
|
|
19
|
-
value =
|
20
|
-
args = []
|
21
|
-
remaining_arity = column.html_block.arity
|
22
|
-
|
23
|
-
if column.data?
|
24
|
-
args << column.value(asset,grid)
|
25
|
-
remaining_arity -= 1
|
26
|
-
end
|
27
|
-
|
28
|
-
args << asset if remaining_arity > 0
|
29
|
-
args << grid if remaining_arity > 1
|
30
|
-
|
31
|
-
@template.instance_exec(*args, &column.html_block)
|
32
|
-
else
|
33
|
-
column.value(asset,grid)
|
34
|
-
end
|
19
|
+
value = column.html_value(@template, asset, grid)
|
35
20
|
|
36
21
|
url = column.options[:url] && column.options[:url].call(asset)
|
37
22
|
if url
|
38
23
|
@template.link_to(value, url)
|
39
24
|
else
|
40
|
-
|
41
|
-
when :url
|
42
|
-
@template.link_to(column.label ? asset.send(column.label) : I18n.t("datagrid.table.url_label", :default => "URL"), value)
|
43
|
-
else
|
44
|
-
_safe(value)
|
45
|
-
end
|
25
|
+
_safe(value)
|
46
26
|
end
|
47
27
|
end
|
48
28
|
|
@@ -57,10 +37,13 @@ module Datagrid
|
|
57
37
|
options = args.extract_options!
|
58
38
|
options[:html] ||= {}
|
59
39
|
options[:html][:class] ||= "datagrid #{html_class(grid)}"
|
40
|
+
if options[:cycle]
|
41
|
+
::Datagrid::Utils.warn_once("datagrid_table cycle option is deprecated. Use css to stylee odd/even rows instead.")
|
42
|
+
end
|
60
43
|
assets = args.any? ? args.shift : grid.assets
|
61
44
|
paginate = options[:paginate]
|
62
45
|
if paginate
|
63
|
-
::Datagrid::Utils.warn_once(":paginate option is deprecated.
|
46
|
+
::Datagrid::Utils.warn_once(":paginate option is deprecated. Look to https://github.com/bogdan/datagrid/wiki/Frontend.")
|
64
47
|
assets = assets.paginate(paginate)
|
65
48
|
end
|
66
49
|
|
data/lib/datagrid/utils.rb
CHANGED
@@ -32,7 +32,20 @@ module Datagrid
|
|
32
32
|
options
|
33
33
|
end
|
34
34
|
|
35
|
+
def string_like?(value)
|
36
|
+
value.is_a?(Symbol) || value.is_a?(String)
|
37
|
+
end
|
35
38
|
|
39
|
+
def extract_position_from_options(array, options)
|
40
|
+
position = options.extract!(:before, :after)
|
41
|
+
if position[:before]
|
42
|
+
array.index {|c| c.name.to_sym == position[:before].to_sym }
|
43
|
+
elsif position[:after]
|
44
|
+
array.index {|c| c.name.to_sym == position[:after].to_sym } + 1
|
45
|
+
else
|
46
|
+
-1
|
47
|
+
end
|
48
|
+
end
|
36
49
|
end
|
37
50
|
end
|
38
51
|
end
|
@@ -17,17 +17,40 @@ describe Datagrid::Columns do
|
|
17
17
|
:confirmed => false,
|
18
18
|
:category => "first",
|
19
19
|
:access_level => 'admin',
|
20
|
-
:pet => 'rottweiler'
|
20
|
+
:pet => 'rottweiler',
|
21
|
+
:shipping_date => Date.new(2013, 8, 1)
|
21
22
|
) }
|
23
|
+
let(:date) { Date.new(2013, 8, 1) }
|
22
24
|
|
23
25
|
it "should have data columns without html columns" do
|
24
26
|
subject.data_columns.size.should == subject.columns.size - 1
|
25
27
|
end
|
26
28
|
it "should build rows of data" do
|
27
|
-
subject.rows.should == [["Pop", "Star", "admin", "ROTTWEILER"]]
|
29
|
+
subject.rows.should == [[date, "Pop", "Star", "admin", "ROTTWEILER"]]
|
28
30
|
end
|
29
31
|
it "should generate header" do
|
30
|
-
subject.header.should == ["Group", "Name", "Access level", "Pet"]
|
32
|
+
subject.header.should == ["Shipping date", "Group", "Name", "Access level", "Pet"]
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should return html_columns" do
|
36
|
+
report = test_report do
|
37
|
+
scope {Entry}
|
38
|
+
column(:id)
|
39
|
+
column(:name, :html => false)
|
40
|
+
end
|
41
|
+
report.html_columns.map(&:name).should == [:id]
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should return html_columns when column definition has 2 arguments" do
|
45
|
+
report = test_report(:name => "Hello") do
|
46
|
+
scope {Entry}
|
47
|
+
filter(:name)
|
48
|
+
column(:id)
|
49
|
+
column(:name, :html => false) do |model, grid|
|
50
|
+
"'#{model.name}' filtered by '#{grid.name}'"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
report.row_for(Entry.create!(:name => "Hello World")).should == [8, "'Hello World' filtered by 'Hello'"]
|
31
54
|
end
|
32
55
|
|
33
56
|
it "should generate table data" do
|
@@ -42,12 +65,13 @@ describe Datagrid::Columns do
|
|
42
65
|
:group => "Pop",
|
43
66
|
:name => "Star",
|
44
67
|
:access_level => 'admin',
|
45
|
-
:pet => 'ROTTWEILER'
|
68
|
+
:pet => 'ROTTWEILER',
|
69
|
+
:shipping_date => date
|
46
70
|
}
|
47
71
|
end
|
48
72
|
|
49
73
|
it "should support csv export" do
|
50
|
-
subject.to_csv.should == "Group,Name,Access level,Pet\
|
74
|
+
subject.to_csv.should == "Shipping date,Group,Name,Access level,Pet\n#{date},Pop,Star,admin,ROTTWEILER\n"
|
51
75
|
end
|
52
76
|
|
53
77
|
it "should support csv export of particular columns" do
|
@@ -55,7 +79,7 @@ describe Datagrid::Columns do
|
|
55
79
|
end
|
56
80
|
|
57
81
|
it "should support csv export options" do
|
58
|
-
subject.to_csv(:col_sep => ";").should == "Group;Name;Access level;Pet\
|
82
|
+
subject.to_csv(:col_sep => ";").should == "Shipping date;Group;Name;Access level;Pet\n#{date};Pop;Star;admin;ROTTWEILER\n"
|
59
83
|
end
|
60
84
|
end
|
61
85
|
|
@@ -121,4 +145,19 @@ describe Datagrid::Columns do
|
|
121
145
|
|
122
146
|
end
|
123
147
|
|
148
|
+
|
149
|
+
context "when grid has formatted column" do
|
150
|
+
it "should output correct data" do
|
151
|
+
report = test_report do
|
152
|
+
scope {Entry}
|
153
|
+
column(:name) do |entry|
|
154
|
+
format(entry.name) do |value|
|
155
|
+
"<strong>#{value}</strong"
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
Entry.create!(:name => "Hello World")
|
160
|
+
report.rows.should == [["Hello World"]]
|
161
|
+
end
|
162
|
+
end
|
124
163
|
end
|
data/spec/datagrid/core_spec.rb
CHANGED
@@ -1,15 +1,39 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Datagrid::Core do
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
4
|
+
|
5
|
+
context 'with 2 persisted entries' do
|
6
|
+
before { 2.times { Entry.create } }
|
7
|
+
|
8
|
+
let(:limit) { Entry.limit(1) }
|
9
|
+
let(:report_class) do
|
10
|
+
test_report_class do
|
11
|
+
scope { Entry }
|
12
|
+
end
|
8
13
|
end
|
9
|
-
|
10
|
-
|
14
|
+
|
15
|
+
describe '#scope' do
|
16
|
+
context 'in the class' do
|
17
|
+
let(:report) { report_class.new }
|
18
|
+
|
19
|
+
it { expect(report.scope).to have(2).item }
|
20
|
+
end
|
21
|
+
|
22
|
+
context 'changes scope on the fly' do
|
23
|
+
let(:report) do
|
24
|
+
report_class.new.tap do |r|
|
25
|
+
r.scope { limit }
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
it { expect(report.scope).to have(1).item }
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'changes scope by initializer' do
|
33
|
+
let(:report) { report_class.new { limit } }
|
34
|
+
|
35
|
+
it { expect(report.scope).to have(1).item }
|
36
|
+
end
|
11
37
|
end
|
12
|
-
2.times { Entry.create }
|
13
|
-
report.assets.to_a.size.should == 1
|
14
38
|
end
|
15
39
|
end
|
@@ -33,4 +33,17 @@ describe Datagrid::Filters::EnumFilter do
|
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
36
|
+
|
37
|
+
it "should support select given as symbol" do
|
38
|
+
report = test_report do
|
39
|
+
scope {Entry}
|
40
|
+
filter(:group_id, :enum, :select => :selectable_group_ids)
|
41
|
+
def selectable_group_ids
|
42
|
+
[1,3,5]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
report.filter_by_name(:group_id).select(report).should == [1,3,5]
|
47
|
+
end
|
48
|
+
|
36
49
|
end
|
@@ -127,6 +127,29 @@ describe Datagrid::Filters do
|
|
127
127
|
end
|
128
128
|
grid.assets.should_not be_empty
|
129
129
|
end
|
130
|
-
|
130
|
+
|
131
|
+
end
|
132
|
+
|
133
|
+
describe "positioning filter before another" do
|
134
|
+
it "should insert the filter before the specified element" do
|
135
|
+
grid = test_report do
|
136
|
+
scope {Entry}
|
137
|
+
filter(:limit)
|
138
|
+
filter(:name, :before => :limit)
|
139
|
+
end
|
140
|
+
grid.filters.index {|f| f.name == :name}.should == 0
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
describe "positioning filter after another" do
|
145
|
+
it "should insert the filter before the specified element" do
|
146
|
+
grid = test_report do
|
147
|
+
scope {Entry}
|
148
|
+
filter(:limit)
|
149
|
+
filter(:name)
|
150
|
+
filter(:group_id, :after => :limit)
|
151
|
+
end
|
152
|
+
grid.filters.index {|f| f.name == :group_id}.should == 1
|
153
|
+
end
|
131
154
|
end
|
132
155
|
end
|
@@ -163,6 +163,19 @@ describe Datagrid::FormBuilder do
|
|
163
163
|
'<input class="created_at date_filter to" multiple name="report[created_at][]" size="30" type="text" value="2012-01-01"/>'
|
164
164
|
)}
|
165
165
|
end
|
166
|
+
context "with blank range value" do
|
167
|
+
around(:each) do |example|
|
168
|
+
with_date_format do
|
169
|
+
example.run
|
170
|
+
end
|
171
|
+
end
|
172
|
+
let(:_range) { [nil, nil] }
|
173
|
+
it { should equal_to_dom(
|
174
|
+
'<input class="created_at date_filter from" multiple name="report[created_at][]" size="30" type="text"/>' +
|
175
|
+
'<span class="separator date"> - </span>' +
|
176
|
+
'<input class="created_at date_filter to" multiple name="report[created_at][]" size="30" type="text"/>'
|
177
|
+
)}
|
178
|
+
end
|
166
179
|
end
|
167
180
|
context "with enum filter type" do
|
168
181
|
let(:_filter) { :category }
|
@@ -271,11 +284,21 @@ describe Datagrid::FormBuilder do
|
|
271
284
|
end
|
272
285
|
end
|
273
286
|
let(:_filter) { :group_id }
|
274
|
-
|
287
|
+
let(:expected_html) do
|
288
|
+
if ActionPack::VERSION::MAJOR == 3 && ActionPack::VERSION::MINOR < 2
|
289
|
+
<<-HTML
|
290
|
+
<select class="group_id enum_filter" id="report_group_id" multiple name="report[group_id][]">
|
291
|
+
<option value="hello">hello</option></select>
|
292
|
+
HTML
|
293
|
+
else
|
294
|
+
<<-HTML
|
275
295
|
<input name="report[group_id][]" type="hidden" value=""><select class="group_id enum_filter" id="report_group_id" multiple name="report[group_id][]">
|
276
296
|
<option value="hello">hello</option></select>
|
277
|
-
HTML
|
297
|
+
HTML
|
298
|
+
end
|
299
|
+
end
|
278
300
|
|
301
|
+
it { should equal_to_dom(expected_html) }
|
279
302
|
end
|
280
303
|
|
281
304
|
context "with column names filter" do
|
@@ -291,11 +314,23 @@ HTML
|
|
291
314
|
end
|
292
315
|
end
|
293
316
|
let(:_filter) { :column_names }
|
294
|
-
|
317
|
+
let(:expected_html) do
|
318
|
+
if ActionPack::VERSION::MAJOR == 3 && ActionPack::VERSION::MINOR < 2
|
319
|
+
<<-HTML
|
320
|
+
<select class="column_names enum_filter" id="report_column_names" multiple name="report[column_names][]"><option value="id" selected>Id</option>
|
321
|
+
<option value="name" selected>Name</option>
|
322
|
+
<option value="category">Category</option></select>
|
323
|
+
HTML
|
324
|
+
else
|
325
|
+
<<-HTML
|
295
326
|
<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
327
|
<option value="name" selected>Name</option>
|
297
328
|
<option value="category">Category</option></select>
|
298
|
-
HTML
|
329
|
+
HTML
|
330
|
+
end
|
331
|
+
end
|
332
|
+
|
333
|
+
it { should equal_to_dom(expected_html) }
|
299
334
|
end
|
300
335
|
end
|
301
336
|
|
@@ -318,7 +353,3 @@ HTML
|
|
318
353
|
end
|
319
354
|
end
|
320
355
|
end
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
@@ -7,13 +7,14 @@ require 'datagrid/renderer'
|
|
7
7
|
describe Datagrid::Helper do
|
8
8
|
subject do
|
9
9
|
template = ActionView::Base.new
|
10
|
+
template.stub(:protect_against_forgery?).and_return(false)
|
10
11
|
template.view_paths << File.expand_path("../../../app/views", __FILE__)
|
11
12
|
template.view_paths << File.expand_path("../../support/test_partials", __FILE__)
|
12
13
|
template
|
13
14
|
end
|
14
15
|
|
15
16
|
before(:each) do
|
16
|
-
subject.stub
|
17
|
+
subject.stub(:params).and_return({})
|
17
18
|
subject.stub(:url_for) do |options|
|
18
19
|
options.to_param
|
19
20
|
end
|
@@ -95,6 +96,7 @@ describe Datagrid::Helper do
|
|
95
96
|
"table.datagrid td.group" => 0
|
96
97
|
)
|
97
98
|
end
|
99
|
+
|
98
100
|
context "with column_names attribute" do
|
99
101
|
let(:grid) do
|
100
102
|
test_report(:column_names => "name") do
|
@@ -279,6 +281,22 @@ describe Datagrid::Helper do
|
|
279
281
|
)
|
280
282
|
end
|
281
283
|
|
284
|
+
context "when grid has complicated columns" do
|
285
|
+
let(:grid) do
|
286
|
+
test_report(:name => 'Hello') do
|
287
|
+
scope {Entry}
|
288
|
+
filter(:name)
|
289
|
+
column(:name) do |model, grid|
|
290
|
+
"'#{model.name}' filtered by '#{grid.name}'"
|
291
|
+
end
|
292
|
+
end
|
293
|
+
end
|
294
|
+
it "should ignore them" do
|
295
|
+
subject.datagrid_rows(grid, [entry]).should match_css_pattern(
|
296
|
+
"td.name" => 1
|
297
|
+
)
|
298
|
+
end
|
299
|
+
end
|
282
300
|
end
|
283
301
|
|
284
302
|
describe ".datagrid_order_for" do
|
@@ -361,5 +379,16 @@ describe Datagrid::Helper do
|
|
361
379
|
end
|
362
380
|
subject.datagrid_format_value(report, :name, entry).should == "<b>Star</b>"
|
363
381
|
end
|
382
|
+
it "should support format in column" do
|
383
|
+
report = test_report do
|
384
|
+
scope {Entry}
|
385
|
+
column(:name) do |e|
|
386
|
+
format(e.name) do |value|
|
387
|
+
link_to value, "/profile"
|
388
|
+
end
|
389
|
+
end
|
390
|
+
end
|
391
|
+
subject.datagrid_format_value(report, :name, entry).should == "<a href=\"/profile\">Star</a>"
|
392
|
+
end
|
364
393
|
end
|
365
394
|
end
|
@@ -1,16 +1,21 @@
|
|
1
1
|
|
2
2
|
|
3
3
|
def test_report(attributes = {}, &block)
|
4
|
-
klass =
|
5
|
-
klass.class_eval do
|
6
|
-
include Datagrid
|
7
|
-
end
|
8
|
-
if block
|
9
|
-
klass.class_eval(&block)
|
10
|
-
end
|
4
|
+
klass = test_report_class(&block)
|
11
5
|
klass.new(attributes)
|
12
6
|
end
|
13
7
|
|
8
|
+
def test_report_class(&block)
|
9
|
+
Class.new.tap do |klass|
|
10
|
+
klass.class_eval do
|
11
|
+
include Datagrid
|
12
|
+
end
|
13
|
+
if block
|
14
|
+
klass.class_eval(&block)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
14
19
|
class SimpleReport
|
15
20
|
|
16
21
|
include Datagrid
|
@@ -40,12 +45,14 @@ class SimpleReport
|
|
40
45
|
render :partial => "actions", :locals => {:model => model}
|
41
46
|
end
|
42
47
|
|
43
|
-
column(:access_level, :html => lambda {|data| content_tag :h1, data})
|
44
|
-
|
45
48
|
column(:pet, :html => lambda {|data| content_tag :em, data}) do
|
46
49
|
self.pet.try(:upcase)
|
47
50
|
end
|
48
51
|
|
52
|
+
column(:shipping_date, :before => :group)
|
53
|
+
|
54
|
+
column(:access_level, :html => lambda {|data| content_tag :h1, data}, :after => :actions)
|
55
|
+
|
49
56
|
def param_name
|
50
57
|
:report
|
51
58
|
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.9.
|
4
|
+
version: 0.9.2
|
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-
|
12
|
+
date: 2013-08-23 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|
@@ -337,7 +337,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
337
337
|
version: '0'
|
338
338
|
segments:
|
339
339
|
- 0
|
340
|
-
hash:
|
340
|
+
hash: 3747985271557157131
|
341
341
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
342
342
|
none: false
|
343
343
|
requirements:
|