datagrid 1.0.0 → 1.0.1

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