datagrid 1.0.0 → 1.0.1

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
- 1.0.0
1
+ 1.0.1
@@ -65,10 +65,6 @@ table.datagrid
65
65
  a
66
66
  float: left
67
67
 
68
- &.dp-choose-date
69
- margin-left: -22px
70
- margin-top: 7px
71
-
72
68
  input[class*='filter']
73
69
  border: 2px solid #ccc
74
70
  border-radius: 4px
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "datagrid"
8
- s.version = "1.0.0"
8
+ s.version = "1.0.1"
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-09-19"
12
+ s.date = "2013-10-14"
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 = [
@@ -18,6 +18,17 @@ module Datagrid
18
18
 
19
19
  module ClassMethods
20
20
  # Adds a filter that acts like a column selection
21
+ # All defined columns will be available to select/deselect
22
+ # as a multi-select enum filter.
23
+ # Columns with <tt>:mandatory => true</tt> option
24
+ # will always present in the grid table and won't be listed
25
+ # in column names selection
26
+ # Accepts same options as <tt>:enum</tt> filter
27
+ #
28
+ # Examples:
29
+ #
30
+ # column_names_filter(:header => "Choose columns")
31
+ #
21
32
  def column_names_filter(options = {})
22
33
  filter(:column_names, :enum, {
23
34
  :select => :optional_columns_select,
@@ -174,7 +174,7 @@ module Datagrid
174
174
  # * <tt>column_names</tt> - list of column names if you want to limit data only to specified columns
175
175
  def rows(*column_names)
176
176
  #TODO: find in batches
177
- self.assets.map do |asset|
177
+ driver.batch_map(assets) do |asset|
178
178
  self.row_for(asset, *column_names)
179
179
  end
180
180
  end
@@ -189,7 +189,7 @@ module Datagrid
189
189
  end
190
190
 
191
191
  # Return Array of Hashes where keys are column names and values are column values
192
- # for each row in datagrid <tt>#assets</tt>
192
+ # for each row in filtered datagrid relation.
193
193
  #
194
194
  # Example:
195
195
  #
@@ -205,7 +205,7 @@ module Datagrid
205
205
  # MyGrid.new.data_hash # => [{:name => "One"}, {:name => "Two"}]
206
206
  #
207
207
  def data_hash
208
- self.assets.map do |asset|
208
+ driver.batch_map(assets) do |asset|
209
209
  hash_for(asset)
210
210
  end
211
211
  end
@@ -268,12 +268,27 @@ module Datagrid
268
268
  self.columns(*names)
269
269
  end
270
270
 
271
- # Finds a column by name
271
+ # Finds a column definition by name
272
272
  def column_by_name(name)
273
273
  self.class.column_by_name(name)
274
274
  end
275
275
 
276
276
 
277
+ # Gives ability to have a different formatting for CSV and HTML column value.
278
+ #
279
+ # Example:
280
+ #
281
+ # column(:name) do |model|
282
+ # format(model.name) do |value|
283
+ # content_tag(:strong, value)
284
+ # end
285
+ # end
286
+ #
287
+ # column(:company) do |model|
288
+ # format(model.company.name) do
289
+ # render :partial => "company_with_logo", :locals => {:company => model.company }
290
+ # end
291
+ # end
277
292
  def format(value, &block)
278
293
  if block_given?
279
294
  self.class.format(value, &block)
@@ -74,6 +74,14 @@ module Datagrid
74
74
  raise NotImplementedError
75
75
  end
76
76
 
77
+ def normalized_column_type(scope, field)
78
+ raise NotImplementedError
79
+ end
80
+
81
+ def batch_map(scope)
82
+ raise NotImplementedError
83
+ end
84
+
77
85
  protected
78
86
  def timestamp_class?(klass)
79
87
  TIMESTAMP_CLASSES.include?(klass)
@@ -71,13 +71,31 @@ module Datagrid
71
71
  end
72
72
 
73
73
  def contains(scope, field, value)
74
- if column_type(scope, field) == :string
75
- field = prefix_table_name(scope, field)
76
- scope.where("#{field} #{contains_predicate} ?", "%#{value}%")
77
- else
78
- # dont support contains operation by non-varchar column now
79
- scope.where("1=0")
74
+ field = prefix_table_name(scope, field)
75
+ scope.where("#{field} #{contains_predicate} ?", "%#{value}%")
76
+ end
77
+
78
+ def normalized_column_type(scope, field)
79
+ type = column_type(scope, field)
80
+ return nil unless type
81
+ {
82
+ [:string, :text, :time, :binary] => :string,
83
+ [:integer, :primary_key] => :integer,
84
+ [:float, :decimal] => :float,
85
+ [:date] => :date,
86
+ [:datetime, :timestamp] => :timestamp,
87
+ [:boolean] => :boolean
88
+ }.each do |keys, value|
89
+ return value if keys.include?(type)
90
+ end
91
+ end
92
+
93
+ def batch_map(scope, &block)
94
+ result = []
95
+ scope.find_each do |record|
96
+ result << yield(record)
80
97
  end
98
+ result
81
99
  end
82
100
 
83
101
  protected
@@ -64,6 +64,10 @@ module Datagrid
64
64
  def column_names(scope)
65
65
  []
66
66
  end
67
+
68
+ def batch_map(scope, &block)
69
+ scope.map(&block)
70
+ end
67
71
  end
68
72
  end
69
73
  end
@@ -55,6 +55,10 @@ module Datagrid
55
55
  def column_names(scope)
56
56
  [] # TODO: implement support
57
57
  end
58
+
59
+ def batch_map(scope, &block)
60
+ scope.map(&block)
61
+ end
58
62
  end
59
63
  end
60
64
  end
@@ -52,12 +52,36 @@ module Datagrid
52
52
  end
53
53
 
54
54
  def contains(scope, field, value)
55
- scope(field => Regexp.compile(Regexp.escape(value)))
55
+ scope.where(field => Regexp.compile(Regexp.escape(value)))
56
56
  end
57
57
 
58
58
  def column_names(scope)
59
59
  to_scope(scope).klass.fields.keys
60
60
  end
61
+
62
+ def normalized_column_type(scope, field)
63
+ type = to_scope(scope).klass.fields[field.to_s].try(:type)
64
+ return nil unless type
65
+ {
66
+ [BigDecimal , String, Symbol, Range, Array, Hash, ] => :string,
67
+ [Boolean] => :boolean,
68
+
69
+ [Date] => :date,
70
+
71
+ TIMESTAMP_CLASSES => :timestamp,
72
+
73
+ [Float] => :fload,
74
+
75
+ [Integer] => :integer,
76
+ }.each do |keys, value|
77
+ return value if keys.include?(type)
78
+ end
79
+ return :string
80
+ end
81
+
82
+ def batch_map(scope, &block)
83
+ scope.map(&block)
84
+ end
61
85
  end
62
86
  end
63
87
  end
@@ -55,24 +55,26 @@ module Datagrid
55
55
  #
56
56
  # Arguments:
57
57
  #
58
- # * <tt>name</tt> - filter name
59
- # * <tt>type</tt> - filter type that defines type case and GUI representation of a filter
60
- # * <tt>options</tt> - hash of options
61
- # * <tt>block</tt> - proc to apply the filter
58
+ # * <tt>name</tt> - filter name
59
+ # * <tt>type</tt> - filter type that defines type case and GUI representation of a filter
60
+ # * <tt>options</tt> - hash of options
61
+ # * <tt>block</tt> - proc to apply the filter
62
62
  #
63
63
  # Available options:
64
64
  #
65
- # * <tt>:header</tt> - determines the header of the filter
66
- # * <tt>:default</tt> - the default filter value. Able to accept a <tt>Proc</tt> in case default should be recalculated
67
- # * <tt>:multiple</tt> - determines if more than one option can be selected
68
- # * <tt>:allow_nil</tt> - determines if the value can be nil
69
- # * <tt>:allow_blank</tt> - determines if the value can be blank
70
- # * <tt>:before</tt> - determines the position of this filter,
71
- # by adding it before the filter passed here (when using datagrid_form_for helper)
72
- # * <tt>:after</tt> - determines the position of this filter,
73
- # by adding it after the filter passed here (when using datagrid_form_for helper)
74
- # * <tt>:dummy</tt> - if true, this filter will not be applied automatically
75
- # and will just be displayed in form. In case you may want to apply it manually.
65
+ # * <tt>:header</tt> - determines the header of the filter
66
+ # * <tt>:default</tt> - the default filter value. Able to accept a <tt>Proc</tt> in case default should be recalculated
67
+ # * <tt>:multiple</tt> - if true multiple values can be assigned to this filter.
68
+ # By default multiple values are parsed from string using `,` separator.
69
+ # But you can specify a different separator as option value. Default: false.
70
+ # * <tt>:allow_nil</tt> - determines if the value can be nil
71
+ # * <tt>:allow_blank</tt> - determines if the value can be blank
72
+ # * <tt>:before</tt> - determines the position of this filter,
73
+ # by adding it before the filter passed here (when using datagrid_form_for helper)
74
+ # * <tt>:after</tt> - determines the position of this filter,
75
+ # by adding it after the filter passed here (when using datagrid_form_for helper)
76
+ # * <tt>:dummy</tt> - if true, this filter will not be applied automatically
77
+ # and will be just displayed in form. In case you may want to apply it manually.
76
78
  #
77
79
  # See: https://github.com/bogdan/datagrid/wiki/Filters for examples
78
80
  def filter(name, type = :default, options = {}, &block)
@@ -121,7 +123,7 @@ module Datagrid
121
123
  self.class.filters
122
124
  end
123
125
 
124
- # Returns filter valur for given filter definition
126
+ # Returns filter value for given filter definition
125
127
  def filter_value(filter)
126
128
  self[filter.name]
127
129
  end
@@ -1,7 +1,7 @@
1
1
  class Datagrid::FilteringError < StandardError
2
2
  end
3
3
 
4
- class Datagrid::Filters::BaseFilter
4
+ class Datagrid::Filters::BaseFilter #:nodoc:
5
5
 
6
6
  attr_accessor :grid_class, :options, :block, :name
7
7
 
@@ -1,4 +1,4 @@
1
- class Datagrid::Filters::BooleanEnumFilter < Datagrid::Filters::EnumFilter
1
+ class Datagrid::Filters::BooleanEnumFilter < Datagrid::Filters::EnumFilter #:nodoc:
2
2
 
3
3
  YES = "YES"
4
4
  NO = "NO"
@@ -1,5 +1,5 @@
1
1
  require "datagrid/utils"
2
- class Datagrid::Filters::BooleanFilter < Datagrid::Filters::BaseFilter
2
+ class Datagrid::Filters::BooleanFilter < Datagrid::Filters::BaseFilter #:nodoc:
3
3
 
4
4
  def parse(value)
5
5
  Datagrid::Utils.booleanize(value)
@@ -1,6 +1,6 @@
1
1
  module Datagrid
2
2
  module Filters
3
- module CompositeFilters
3
+ module CompositeFilters #:nodoc:
4
4
 
5
5
  def self.included(base)
6
6
  base.extend ClassMethods
@@ -12,26 +12,9 @@ class Datagrid::Filters::DateFilter < Datagrid::Filters::BaseFilter
12
12
  end
13
13
 
14
14
  def parse(value)
15
- return nil if value.blank?
16
- return value if value.is_a?(Range)
17
- if value.is_a?(String)
18
- formats.each do |format|
19
- begin
20
- return Date.strptime(value, format)
21
- rescue ArgumentError
22
- end
23
- end
24
- end
25
- return value.to_date if value.respond_to?(:to_date)
26
- return value unless value.is_a?(String)
27
- Date.parse(value)
28
- rescue ArgumentError
29
- nil
15
+ Datagrid::Utils.parse_date(value)
30
16
  end
31
17
 
32
- def formats
33
- Array(Datagrid.configuration.date_formats)
34
- end
35
18
 
36
19
  def format(value)
37
20
  if formats.any? && value
@@ -43,23 +26,15 @@ class Datagrid::Filters::DateFilter < Datagrid::Filters::BaseFilter
43
26
 
44
27
  def default_filter_where(driver, scope, value)
45
28
  if driver.is_timestamp?(scope, name)
46
- value = format_value_timestamp(value)
29
+ value = Datagrid::Utils.format_date_as_timestamp(value)
47
30
  end
48
31
  super(driver, scope, value)
49
32
  end
50
33
 
51
34
  protected
52
- def format_value_timestamp(value)
53
- if !value
54
- value
55
- elsif (range? && value.is_a?(Array))
56
- [value.first.try(:beginning_of_day), value.last.try(:end_of_day)]
57
- elsif value.is_a?(Range)
58
- (value.first.beginning_of_day..value.last.end_of_day)
59
- else
60
- value.beginning_of_day..value.end_of_day
61
- end
62
- end
63
35
 
36
+ def formats
37
+ Array(Datagrid.configuration.date_formats)
38
+ end
64
39
  end
65
40
 
@@ -6,12 +6,16 @@ class Datagrid::Filters::DynamicFilter < Datagrid::Filters::BaseFilter
6
6
 
7
7
  def initialize(*)
8
8
  super
9
- options[:multiple] = true
10
9
  options[:select] ||= default_select
10
+ unless options.has_key?(:include_blank)
11
+ options[:include_blank] = false
12
+ end
11
13
  end
12
14
 
13
- def parse(value)
14
- value
15
+ def parse_values(filter)
16
+ field, operation, value = filter
17
+
18
+ [field, operation, type_cast(field, value)]
15
19
  end
16
20
 
17
21
  def unapplicable_value?(filter)
@@ -21,15 +25,31 @@ class Datagrid::Filters::DynamicFilter < Datagrid::Filters::BaseFilter
21
25
 
22
26
  def default_filter_where(driver, scope, filter)
23
27
  field, operation, value = filter
24
- driver.to_scope(scope)
28
+ date_conversion = value.is_a?(Date) && driver.is_timestamp?(scope, field)
25
29
  case operation
26
30
  when '='
31
+ if date_conversion
32
+ value = Datagrid::Utils.format_date_as_timestamp(value)
33
+ end
27
34
  driver.where(scope, field, value)
28
35
  when '=~'
29
- driver.contains(scope, field, value)
36
+ if column_type(field) == :string
37
+ driver.contains(scope, field, value)
38
+ else
39
+ if date_conversion
40
+ value = Datagrid::Utils.format_date_as_timestamp(value)
41
+ end
42
+ driver.where(scope, field, value)
43
+ end
30
44
  when '>='
45
+ if date_conversion
46
+ value = value.beginning_of_day
47
+ end
31
48
  driver.greater_equal(scope, field, value)
32
49
  when '<='
50
+ if date_conversion
51
+ value = value.end_of_day
52
+ end
33
53
  driver.less_equal(scope, field, value)
34
54
  else
35
55
  raise "unknown operation: #{operation.inspect}"
@@ -38,7 +58,7 @@ class Datagrid::Filters::DynamicFilter < Datagrid::Filters::BaseFilter
38
58
 
39
59
  def operations_select
40
60
  %w(= =~ >= <=).map do |operation|
41
- I18n.t(operation, :scope => "datagrid.filters.dynamic.operations")
61
+ [I18n.t(operation, :scope => "datagrid.filters.dynamic.operations").html_safe, operation]
42
62
  end
43
63
  end
44
64
 
@@ -54,4 +74,30 @@ class Datagrid::Filters::DynamicFilter < Datagrid::Filters::BaseFilter
54
74
  }
55
75
  end
56
76
 
77
+ def type_cast(field, value)
78
+ type = column_type(field)
79
+ return nil if value.blank?
80
+ case type
81
+ when :string
82
+ value.to_s
83
+ when :integer
84
+ value.is_a?(Numeric) || value =~ /^\d/ ? value.to_i : nil
85
+ when :float
86
+ value.is_a?(Numeric) || value =~ /^\d/ ? value.to_f : nil
87
+ when :date
88
+ Datagrid::Utils.parse_date(value)
89
+ when :timestamp
90
+ Datagrid::Utils.parse_date(value)
91
+ when :boolean
92
+ Datagrid::Utils.booleanize(value)
93
+ when nil
94
+ value
95
+ else
96
+ raise NotImplementedError, "unknown column type: #{type.inspect}"
97
+ end
98
+ end
99
+
100
+ def column_type(field)
101
+ grid_class.driver.normalized_column_type(grid_class.scope, field)
102
+ end
57
103
  end
@@ -6,6 +6,9 @@ class Datagrid::Filters::EnumFilter < Datagrid::Filters::BaseFilter
6
6
 
7
7
  def initialize(*args)
8
8
  super(*args)
9
+ if checkboxes?
10
+ options[:multiple] = true
11
+ end
9
12
  raise Datagrid::ConfigurationError, ":select option not specified" unless options[:select]
10
13
  end
11
14
 
@@ -15,7 +18,11 @@ class Datagrid::Filters::EnumFilter < Datagrid::Filters::BaseFilter
15
18
  end
16
19
 
17
20
  def strict
18
- self.options[:strict]
21
+ options[:strict]
22
+ end
23
+
24
+ def checkboxes?
25
+ options[:checkboxes]
19
26
  end
20
27
 
21
28
  end
@@ -22,7 +22,7 @@ module Datagrid
22
22
  end
23
23
 
24
24
  def datagrid_boolean_filter(attribute_or_filter, options = {})
25
- check_box(datagrid_get_attribute(attribute_or_filter), options)
25
+ check_box(datagrid_get_attribute(attribute_or_filter), options.reverse_merge(datagrid_extra_checkbox_options))
26
26
  end
27
27
 
28
28
  def datagrid_date_filter(attribute_or_filter, options = {})
@@ -31,8 +31,7 @@ module Datagrid
31
31
 
32
32
  def datagrid_default_filter(attribute_or_filter, options = {})
33
33
  filter = datagrid_get_filter(attribute_or_filter)
34
- value = object.filter_value_as_string(filter)
35
- text_field filter.name, options.merge(:value => object.filter_value_as_string(filter))
34
+ text_field filter.name, options.reverse_merge(:value => object.filter_value_as_string(filter))
36
35
  end
37
36
 
38
37
  def datagrid_enum_filter(attribute_or_filter, options = {})
@@ -40,7 +39,16 @@ module Datagrid
40
39
  if !options.has_key?(:multiple) && filter.multiple?
41
40
  options[:multiple] = true
42
41
  end
43
- select filter.name, filter.select(object) || [], {:include_blank => filter.include_blank, :prompt => filter.prompt, :include_hidden => false}, options
42
+ if filter.checkboxes?
43
+ filter.select(options).map do |element|
44
+ text, value = @template.send(:option_text_and_value, element)
45
+ id = [object_name, filter.name, value.underscore].join('_')
46
+ input = check_box(filter.name, options.merge(datagrid_extra_checkbox_options).reverse_merge(:id => id, :multiple => true), value, nil)
47
+ label(filter.name, input + text, :for => id)
48
+ end.join("\n").html_safe
49
+ else
50
+ select filter.name, filter.select(object) || [], {:include_blank => filter.include_blank, :prompt => filter.prompt, :include_hidden => false}, options
51
+ end
44
52
  end
45
53
 
46
54
  def datagrid_integer_filter(attribute_or_filter, options = {})
@@ -57,18 +65,18 @@ module Datagrid
57
65
  field, operation, value = object.filter_value(filter)
58
66
  options = options.merge(:name => input_name)
59
67
  field_input = select(
60
- filter.name,
61
- filter.select(object) || [],
68
+ filter.name,
69
+ filter.select(object) || [],
62
70
  {
63
71
  :include_blank => filter.include_blank,
64
72
  :prompt => filter.prompt,
65
73
  :include_hidden => false,
66
74
  :selected => field
67
- },
75
+ },
68
76
  add_html_classes(options, "field")
69
77
  )
70
78
  operation_input = select(
71
- filter.name, filter.operations_select,
79
+ filter.name, filter.operations_select,
72
80
  {:include_blank => false, :include_hidden => false, :prompt => false, :selected => operation },
73
81
  add_html_classes(options, "operation")
74
82
  )
@@ -83,7 +91,7 @@ module Datagrid
83
91
 
84
92
 
85
93
  from_options = datagrid_range_filter_options(object, filter, :from, options)
86
- to_options = datagrid_range_filter_options(object, filter, :to, options)
94
+ to_options = datagrid_range_filter_options(object, filter, :to, options)
87
95
  # 2 inputs: "from date" and "to date" to specify a range
88
96
  [
89
97
  text_field(filter.name, from_options),
@@ -100,17 +108,17 @@ module Datagrid
100
108
  type_method_map = {:from => :first, :to => :last}
101
109
  options = add_html_classes(options, type)
102
110
  options[:value] = filter.format(object[filter.name].try(type_method_map[type]))
103
- # In case of datagrid ranged filter
111
+ # In case of datagrid ranged filter
104
112
  # from and to input will have same id
105
- options[:id] = if !options.key?(:id)
106
- # Rails provides it's own default id for all inputs
107
- # In order to prevent that we assign no id by default
108
- options[:id] = nil
109
- elsif options[:id].present?
110
- # If the id was given we prefix it
111
- # with from_ and to_ accordingly
112
- options[:id] = [type, options[:id]].join("_")
113
- end
113
+ options[:id] = if !options.key?(:id)
114
+ # Rails provides it's own default id for all inputs
115
+ # In order to prevent that we assign no id by default
116
+ options[:id] = nil
117
+ elsif options[:id].present?
118
+ # If the id was given we prefix it
119
+ # with from_ and to_ accordingly
120
+ options[:id] = [type, options[:id]].join("_")
121
+ end
114
122
  options
115
123
  end
116
124
 
@@ -140,11 +148,16 @@ module Datagrid
140
148
  end
141
149
 
142
150
  def add_html_classes(options, *classes)
143
- Datagrid::Utils.add_html_classes(options, *classes)
151
+ Datagrid::Utils.add_html_classes(options, *classes)
152
+ end
153
+
154
+ def datagrid_extra_checkbox_options
155
+ ::ActionPack::VERSION::MAJOR >= 4 ? {:include_hidden => false} : {}
144
156
  end
145
157
 
146
158
  class Error < StandardError
147
159
  end
160
+
148
161
  end
149
162
  end
150
163
 
@@ -22,7 +22,7 @@ en:
22
22
  "no": "No"
23
23
  dynamic:
24
24
  operations:
25
- ">=": ">="
26
- "<=": "<="
25
+ ">=": "&ge;"
26
+ "<=": "&le;"
27
27
  "=": "="
28
- "=~": "=~"
28
+ "=~": "&asymp;"
@@ -38,7 +38,7 @@ module Datagrid
38
38
  options[:html] ||= {}
39
39
  options[:html][:class] ||= "datagrid #{html_class(grid)}"
40
40
  if options[:cycle]
41
- ::Datagrid::Utils.warn_once("datagrid_table cycle option is deprecated. Use css to stylee odd/even rows instead.")
41
+ ::Datagrid::Utils.warn_once("datagrid_table cycle option is deprecated. Use css to style odd/even rows instead.")
42
42
  end
43
43
  assets = args.any? ? args.shift : grid.assets
44
44
  paginate = options[:paginate]
@@ -54,6 +54,37 @@ module Datagrid
54
54
  end
55
55
  block.call(*args)
56
56
  end
57
+
58
+ def parse_date(value)
59
+ return nil if value.blank?
60
+ return value if value.is_a?(Range)
61
+ if value.is_a?(String)
62
+ Array(Datagrid.configuration.date_formats).each do |format|
63
+ begin
64
+ return Date.strptime(value, format)
65
+ rescue ::ArgumentError
66
+ end
67
+ end
68
+ end
69
+ return Date.parse(value) if value.is_a?(String)
70
+ return value.to_date if value.respond_to?(:to_date)
71
+ value
72
+ rescue ::ArgumentError
73
+ nil
74
+ end
75
+
76
+ def format_date_as_timestamp(value)
77
+ if !value
78
+ value
79
+ elsif value.is_a?(Array)
80
+ [value.first.try(:beginning_of_day), value.last.try(:end_of_day)]
81
+ elsif value.is_a?(Range)
82
+ (value.first.beginning_of_day..value.last.end_of_day)
83
+ else
84
+ value.beginning_of_day..value.end_of_day
85
+ end
86
+ end
87
+
57
88
  end
58
89
  end
59
90
  end
@@ -14,24 +14,109 @@ describe Datagrid::Filters::DynamicFilter do
14
14
  report.assets.should include(Entry.create!(:name => 'hello'))
15
15
  report.assets.should_not include(Entry.create!(:name => 'bye'))
16
16
  end
17
+
18
+ it "should support >= operation" do
19
+ report.condition = [:name, ">=", "d"]
20
+ report.assets.should include(Entry.create!(:name => 'x'))
21
+ report.assets.should include(Entry.create!(:name => 'd'))
22
+ report.assets.should_not include(Entry.create!(:name => 'a'))
23
+ end
24
+
17
25
  it "should blank value" do
18
26
  report.condition = [:name, "=", ""]
19
27
  report.assets.should include(Entry.create!(:name => 'hello'))
20
28
  end
21
- it "should support =~ operation" do
29
+
30
+ it "should support =~ operation on strings" do
22
31
  report.condition = [:name, "=~", "ell"]
23
32
  report.assets.should include(Entry.create!(:name => 'hello'))
24
33
  report.assets.should_not include(Entry.create!(:name => 'bye'))
25
34
  end
26
- it "should support >= operation" do
35
+
36
+ it "should support =~ operation integers" do
37
+ report.condition = [:group_id, "=~", 2]
38
+ report.assets.should include(Entry.create!(:group_id => 2))
39
+ report.assets.should_not include(Entry.create!(:group_id => 1))
40
+ report.assets.should_not include(Entry.create!(:group_id => 3))
41
+ end
42
+
43
+ it "should support >= operation on integer" do
27
44
  report.condition = [:group_id, ">=", 2]
28
45
  report.assets.should include(Entry.create!(:group_id => 3))
29
46
  report.assets.should_not include(Entry.create!(:group_id => 1))
30
47
  end
31
- it "should support <= operation" do
48
+
49
+ it "should support <= operation on integer" do
32
50
  report.condition = [:group_id, "<=", 2]
33
51
  report.assets.should include(Entry.create!(:group_id => 1))
34
52
  report.assets.should_not include(Entry.create!(:group_id => 3))
35
53
  end
36
54
 
55
+ it "should support <= operation on integer with string value" do
56
+ report.condition = [:group_id, "<=", '2']
57
+ report.assets.should include(Entry.create!(:group_id => 1))
58
+ report.assets.should include(Entry.create!(:group_id => 2))
59
+ report.assets.should_not include(Entry.create!(:group_id => 3))
60
+ end
61
+
62
+ it "should nullify incorrect value for integer" do
63
+ report.condition = [:group_id, "<=", 'aa']
64
+ report.condition.should == [:group_id, "<=", nil]
65
+ end
66
+
67
+ it "should nullify incorrect value for date" do
68
+ report.condition = [:shipping_date, "<=", 'aa']
69
+ report.condition.should == [:shipping_date, "<=", nil]
70
+ end
71
+
72
+ it "should nullify incorrect value for datetime" do
73
+ report.condition = [:created_at, "<=", 'aa']
74
+ report.condition.should == [:created_at, "<=", nil]
75
+ end
76
+
77
+ it "should support date comparation operation by timestamp column" do
78
+ report.condition = [:created_at, "<=", '1986-08-05']
79
+ report.condition.should == [:created_at, "<=", Date.parse('1986-08-05')]
80
+ report.assets.should include(Entry.create!(:created_at => DateTime.parse('1986-08-04 01:01:01')))
81
+ report.assets.should include(Entry.create!(:created_at => DateTime.parse('1986-08-05 23:59:59')))
82
+ report.assets.should include(Entry.create!(:created_at => DateTime.parse('1986-08-05 00:00:00')))
83
+ report.assets.should_not include(Entry.create!(:created_at => DateTime.parse('1986-08-06 00:00:00')))
84
+ report.assets.should_not include(Entry.create!(:created_at => DateTime.parse('1986-08-06 23:59:59')))
85
+ end
86
+
87
+ it "should support date = operation by timestamp column" do
88
+ report.condition = [:created_at, "=", '1986-08-05']
89
+ report.condition.should == [:created_at, "=", Date.parse('1986-08-05')]
90
+ report.assets.should_not include(Entry.create!(:created_at => DateTime.parse('1986-08-04 23:59:59')))
91
+ report.assets.should include(Entry.create!(:created_at => DateTime.parse('1986-08-05 23:59:59')))
92
+ report.assets.should include(Entry.create!(:created_at => DateTime.parse('1986-08-05 00:00:01')))
93
+ #TODO: investigate SQLite issue and uncomment this line
94
+ #report.assets.should include(Entry.create!(:created_at => DateTime.parse('1986-08-05 00:00:00')))
95
+ report.assets.should_not include(Entry.create!(:created_at => DateTime.parse('1986-08-06 23:59:59')))
96
+ end
97
+
98
+ it "should support date =~ operation by timestamp column" do
99
+ report.condition = [:created_at, "=~", '1986-08-05']
100
+ report.condition.should == [:created_at, "=~", Date.parse('1986-08-05')]
101
+ report.assets.should_not include(Entry.create!(:created_at => DateTime.parse('1986-08-04 23:59:59')))
102
+ report.assets.should include(Entry.create!(:created_at => DateTime.parse('1986-08-05 23:59:59')))
103
+ report.assets.should include(Entry.create!(:created_at => DateTime.parse('1986-08-05 00:00:01')))
104
+ #TODO: investigate SQLite issue and uncomment this line
105
+ #report.assets.should include(Entry.create!(:created_at => DateTime.parse('1986-08-05 00:00:00')))
106
+ report.assets.should_not include(Entry.create!(:created_at => DateTime.parse('1986-08-06 23:59:59')))
107
+ end
108
+
109
+ it "should support operations for invalid date" do
110
+ report.condition = [:shipping_date, "<=", '1986-08-05']
111
+ report.assets.should include(Entry.create!(:shipping_date => '1986-08-04'))
112
+ report.assets.should include(Entry.create!(:shipping_date => '1986-08-05'))
113
+ report.assets.should_not include(Entry.create!(:shipping_date => '1986-08-06'))
114
+ end
115
+ it "should support operations for invalid date" do
116
+ report.condition = [:shipping_date, "<=", Date.parse('1986-08-05')]
117
+ report.assets.should include(Entry.create!(:shipping_date => '1986-08-04'))
118
+ report.assets.should include(Entry.create!(:shipping_date => '1986-08-05'))
119
+ report.assets.should_not include(Entry.create!(:shipping_date => '1986-08-06'))
120
+ end
121
+
37
122
  end
@@ -122,4 +122,23 @@ describe Datagrid::Filters::IntegerFilter do
122
122
  report.assets.should_not include(Entry.create!( :group_id => 3))
123
123
  end
124
124
 
125
+ it "should support multiple values" do
126
+ report = test_report(:group_id => "1,2") do
127
+ scope {Entry}
128
+ filter(:group_id, :string, :multiple => true)
129
+ end
130
+ report.assets.should include(Entry.create!( :group_id => 1))
131
+ report.assets.should include(Entry.create!( :group_id => 2))
132
+ report.assets.should_not include(Entry.create!( :group_id => 3))
133
+ end
134
+
135
+ it "should support custom separator multiple values" do
136
+ report = test_report(:group_id => "1|2") do
137
+ scope {Entry}
138
+ filter(:group_id, :string, :multiple => '|')
139
+ end
140
+ report.assets.should include(Entry.create!( :group_id => 1))
141
+ report.assets.should include(Entry.create!( :group_id => 2))
142
+ report.assets.should_not include(Entry.create!( :group_id => 3))
143
+ end
125
144
  end
@@ -20,6 +20,7 @@ describe Datagrid::Filters::StringFilter do
20
20
  report.assets.should include(Entry.create!( :name => "one,1"))
21
21
  report.assets.should include(Entry.create!( :name => "two,2"))
22
22
  report.assets.should_not include(Entry.create!( :name => "one"))
23
+ report.assets.should_not include(Entry.create!( :name => "two"))
23
24
  end
24
25
 
25
26
  end
@@ -218,6 +218,29 @@ describe Datagrid::FormBuilder do
218
218
  <option value="second">second</option></select>'
219
219
  )}
220
220
  end
221
+ context "with checkboxes option" do
222
+ let(:_filter) { :category_with_prompt }
223
+ it { should equal_to_dom(
224
+ '<select class="category_with_prompt enum_filter" id="report_category_with_prompt" name="report[category_with_prompt]"><option value="">My Prompt</option>
225
+ <option value="first">first</option>
226
+ <option value="second">second</option></select>'
227
+ )}
228
+ end
229
+ context "with checkboxes option" do
230
+ let(:_grid) do
231
+ test_report do
232
+ scope {Entry}
233
+ filter(:category, :enum, :select => ["first", "second"], :checkboxes => true)
234
+ end
235
+ end
236
+ let(:_filter) { :category }
237
+ it { should equal_to_dom(
238
+ '
239
+ <label for="report_category_first"><input class="category enum_filter" id="report_category_first" name="report[category][]" type="checkbox" value="first" />first</label>
240
+ <label for="report_category_second"><input class="category enum_filter" id="report_category_second" name="report[category][]" type="checkbox" value="second" />second</label>
241
+ '
242
+ )}
243
+ end
221
244
  end
222
245
 
223
246
  context "with eboolean filter type" do
@@ -373,9 +396,9 @@ describe Datagrid::FormBuilder do
373
396
  <option value="shipping_date">Shipping date</option>
374
397
  <option value="created_at">Created at</option>
375
398
  <option value="updated_at">Updated at</option></select><select class="condition dynamic_filter operation" id="report_condition" name="report[condition][]"><option value="=">=</option>
376
- <option value="=~">=~</option>
377
- <option value="&gt;=">&gt;=</option>
378
- <option value="&lt;=">&lt;=</option></select><input class="condition dynamic_filter value" id="report_condition" name="report[condition][]" size="30" type="text">
399
+ <option value="=~">&asymp;</option>
400
+ <option value="&gt;=">&ge;</option>
401
+ <option value="&lt;=">&le;</option></select><input class="condition dynamic_filter value" id="report_condition" name="report[condition][]" size="30" type="text">
379
402
  HTML
380
403
  end
381
404
  it {should equal_to_dom(expected_html)}
@@ -389,9 +412,9 @@ describe Datagrid::FormBuilder do
389
412
  <<-HTML
390
413
  <select class="condition dynamic_filter field" id="report_condition" name="report[condition][]"><option value="id" selected>id</option>
391
414
  <option value="name">name</option></select><select class="condition dynamic_filter operation" id="report_condition" name="report[condition][]"><option value="=">=</option>
392
- <option value="=~">=~</option>
393
- <option value="&gt;=" selected>&gt;=</option>
394
- <option value="&lt;=">&lt;=</option></select><input class="condition dynamic_filter value" id="report_condition" name="report[condition][]" size="30" type="text" value="1">
415
+ <option value="=~">&asymp;</option>
416
+ <option value="&gt;=" selected>&ge;</option>
417
+ <option value="&lt;=">&le;</option></select><input class="condition dynamic_filter value" id="report_condition" name="report[condition][]" size="30" type="text" value="1">
395
418
  HTML
396
419
  end
397
420
  it {should equal_to_dom(expected_html)}
@@ -405,9 +428,9 @@ describe Datagrid::FormBuilder do
405
428
  <<-HTML
406
429
  <select class="condition dynamic_filter field" id="report_condition" name="report[condition][]"><option value="id">id</option>
407
430
  <option value="name">name</option></select><select class="condition dynamic_filter operation" id="report_condition" name="report[condition][]"><option value="=">=</option>
408
- <option value="=~">=~</option>
409
- <option value="&gt;=">&gt;=</option>
410
- <option value="&lt;=">&lt;=</option></select><input class="condition dynamic_filter value" id="report_condition" name="report[condition][]" size="30" type="text">
431
+ <option value="=~">&asymp;</option>
432
+ <option value="&gt;=">&ge;</option>
433
+ <option value="&lt;=">&le;</option></select><input class="condition dynamic_filter value" id="report_condition" name="report[condition][]" size="30" type="text">
411
434
  HTML
412
435
  end
413
436
  it {should equal_to_dom(expected_html)}
@@ -14,6 +14,7 @@ $LOAD_PATH.unshift(File.dirname(__FILE__))
14
14
 
15
15
  require "active_record"
16
16
  require 'action_view'
17
+ require "rails"
17
18
  require "mongoid"
18
19
  require "mongo_mapper"
19
20
  require 'datagrid'
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: 1.0.0
4
+ version: 1.0.1
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-09-19 00:00:00.000000000 Z
12
+ date: 2013-10-14 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
@@ -344,7 +344,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
344
344
  version: '0'
345
345
  segments:
346
346
  - 0
347
- hash: -2432952415509999407
347
+ hash: 1961249610796694956
348
348
  required_rubygems_version: !ruby/object:Gem::Requirement
349
349
  none: false
350
350
  requirements: