Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Add support for datetime filter #85

Merged
merged 3 commits into from

2 participants

@iwiznia

Here's the pull request for the datetime filter functionality. I couldn't attach it to the previous issue #84

spec/datagrid/filters/date_time_filter_spec.rb
((5 lines not shown))
+ it "should support date range argument" do
+ e1 = Entry.create!(:created_at => DateTime.new(2013, 1, 1, 1, 0))
+ e2 = Entry.create!(:created_at => DateTime.new(2013, 1, 1, 2, 0))
+ e3 = Entry.create!(:created_at => DateTime.new(2013, 1, 1, 3, 0))
+ report = test_report(:created_at => DateTime.new(2013, 1, 1, 1, 30)..DateTime.new(2013, 1, 1, 2, 30)) do
+ scope { Entry }
+ filter(:created_at, :datetime)
+ end
+ report.assets.should_not include(e1)
+ report.assets.should include(e2)
+ report.assets.should_not include(e3)
+ end
+
+ {:active_record => Entry, :mongoid => MongoidEntry}.each do |orm, klass|
+ describe "with orm #{orm}" do
+ describe "date to timestamp conversion" do
@bogdan Owner
bogdan added a note

It looks wrong in the context of timestamp filter.
Should be: timestamp to timestamp conversion, but doesn't make that much sense.

Probably these tests cross with others in this file or we just need a different description.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
spec/datagrid/filters/date_time_filter_spec.rb
((117 lines not shown))
+ end
+
+
+ it "should support block" do
+ report = test_report(:created_at => DateTime.now) do
+ scope { Entry }
+ filter(:created_at, :datetime, :range => true) do |value|
+ where("created_at >= ?", value)
+ end
+ end
+ report.assets.should_not include(Entry.create!(:created_at => 1.day.ago))
+ report.assets.should include(Entry.create!(:created_at => DateTime.tomorrow))
+ end
+
+
+ context "when date format is configured" do
@bogdan Owner
bogdan added a note

*datetime format

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
spec/datagrid/filters/date_time_filter_spec.rb
((124 lines not shown))
+ where("created_at >= ?", value)
+ end
+ end
+ report.assets.should_not include(Entry.create!(:created_at => 1.day.ago))
+ report.assets.should include(Entry.create!(:created_at => DateTime.tomorrow))
+ end
+
+
+ context "when date format is configured" do
+ around(:each) do |example|
+ with_datetime_format(format = "%m/%d/%Y %H:%M") do
+ example.run
+ end
+ end
+
+ it "should have configurable date format" do
@bogdan Owner
bogdan added a note

date => datetime

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
spec/datagrid/filters/date_time_filter_spec.rb
((132 lines not shown))
+ context "when date format is configured" do
+ around(:each) do |example|
+ with_datetime_format(format = "%m/%d/%Y %H:%M") do
+ example.run
+ end
+ end
+
+ it "should have configurable date format" do
+ report = test_report(:created_at => "10/01/2013 01:00") do
+ scope {Entry}
+ filter(:created_at, :datetime)
+ end
+ report.created_at.should == DateTime.new(2013,10,01,1,0)
+ end
+
+ it "should support default explicit date" do
@bogdan Owner
bogdan added a note

date => datetime

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@bogdan bogdan commented on the diff
spec/datagrid/filters/date_time_filter_spec.rb
((143 lines not shown))
+ end
+ report.created_at.should == DateTime.new(2013,10,01,1,0)
+ end
+
+ it "should support default explicit date" do
+ report = test_report(:created_at => DateTime.parse("2013-10-01 01:00")) do
+ scope {Entry}
+ filter(:created_at, :datetime)
+ end
+ report.created_at.should == DateTime.new(2013,10,01,1,0)
+ end
+ end
+
+
+ it "should automatically reverse Array if first more than last" do
+ report = test_report(:created_at => ["2013-01-01 01:00", "2012-01-01 01:00"]) do
@bogdan Owner
bogdan added a note

Body doesn't match the description of the test.
We need to test that datagrid automatically reverses:

["2013-01-01 02:00", "2012-01-01 01:00"] to ["2013-01-01 01:00", "2012-01-01 02:00"]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@iwiznia

I changed the date's to datetime in the specs descriptions... not sure if that's what you meant. Also, what's wrong with the last test? It's checking that if you pass a range with the first value grater than the second, it reverses it...

spec/datagrid/filters/date_time_filter_spec.rb
((5 lines not shown))
+ it "should support datetime range argument" do
+ e1 = Entry.create!(:created_at => DateTime.new(2013, 1, 1, 1, 0))
+ e2 = Entry.create!(:created_at => DateTime.new(2013, 1, 1, 2, 0))
+ e3 = Entry.create!(:created_at => DateTime.new(2013, 1, 1, 3, 0))
+ report = test_report(:created_at => DateTime.new(2013, 1, 1, 1, 30)..DateTime.new(2013, 1, 1, 2, 30)) do
+ scope { Entry }
+ filter(:created_at, :datetime)
+ end
+ report.assets.should_not include(e1)
+ report.assets.should include(e2)
+ report.assets.should_not include(e3)
+ end
+
+ {:active_record => Entry, :mongoid => MongoidEntry}.each do |orm, klass|
+ describe "with orm #{orm}" do
+ describe "timestamp to timestamp conversion" do
@bogdan Owner
bogdan added a note

Lets just remove this description block - it makes no sense.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@iwiznia

Done.

@bogdan bogdan merged commit c34fd49 into bogdan:master
@iwiznia

Damn! I forgot to increase the version number... Is it ok if I change the version to 1.0.4?

@bogdan
Owner
@iwiznia

Ok, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jan 13, 2014
  1. Add support for datetime filter

    Ionatan Wiznia authored
  2. Wrong spec descriptions

    Ionatan Wiznia authored
Commits on Jan 14, 2014
  1. remove unnecessary test

    Ionatan Wiznia authored
This page is out of date. Refresh to see the latest.
View
13 Readme.markdown
@@ -61,13 +61,13 @@ Basic grid api:
``` ruby
report = SimpleReport.new(
- :group_id => [1,2], :from_logins_count => 1,
+ :group_id => [1,2], :from_logins_count => 1,
:category => "first",
:order => :group,
:descending => true
)
-report.assets # => Array of User instances:
+report.assets # => Array of User instances:
# SELECT * FROM users WHERE users.group_id in (1,2) AND users.logins_count >= 1 AND users.category = 'first' ORDER BY groups.name DESC
report.header # => ["Name", "Group", "Activated"]
@@ -118,6 +118,7 @@ Datagrid supports different type of filters including:
* integer
* float
* date
+* datetime
* boolean
* eboolean - the select of "yes", "no" and any
* enum
@@ -137,10 +138,10 @@ column(:activated, :header => "Active", :order => "activated", :after => :name)
end
```
-Some formatting options are also available.
+Some formatting options are also available.
Each column is sortable.
-[More about columns](https://github.com/bogdan/datagrid/wiki/Columns)
+[More about columns](https://github.com/bogdan/datagrid/wiki/Columns)
### Front end
@@ -178,8 +179,8 @@ All advanced frontend things are described in:
## Self-Promotion
-Like datagrid?
+Like datagrid?
-Follow the repository on [GitHub](https://github.com/bogdan/datagrid).
+Follow the repository on [GitHub](https://github.com/bogdan/datagrid).
Read [author blog](http://gusiev.com).
View
2  lib/datagrid/configuration.rb
@@ -8,6 +8,6 @@ def self.configure
yield(configuration)
end
- class Configuration < Struct.new(:date_formats)
+ class Configuration < Struct.new(:date_formats, :datetime_formats)
end
end
View
16 lib/datagrid/filters.rb
@@ -8,6 +8,7 @@ module Filters
require "datagrid/filters/boolean_enum_filter"
require "datagrid/filters/boolean_filter"
require "datagrid/filters/date_filter"
+ require "datagrid/filters/date_time_filter"
require "datagrid/filters/default_filter"
require "datagrid/filters/integer_filter"
require "datagrid/filters/composite_filters"
@@ -17,6 +18,7 @@ module Filters
FILTER_TYPES = {
:date => Filters::DateFilter,
+ :datetime => Filters::DateTimeFilter,
:string => Filters::StringFilter,
:default => Filters::DefaultFilter,
:eboolean => Filters::BooleanEnumFilter ,
@@ -52,7 +54,7 @@ def filter_by_name(attribute)
# Defines new datagrid filter.
# This method automatically generates <tt>attr_accessor</tt> for filter name
# and adds it to the list of datagrid attributes.
- #
+ #
# Arguments:
#
# * <tt>name</tt> - filter name
@@ -61,19 +63,19 @@ def filter_by_name(attribute)
# * <tt>block</tt> - proc to apply the filter
#
# Available options:
- #
+ #
# * <tt>:header</tt> - determines the header of the filter
# * <tt>:default</tt> - the default filter value. Able to accept a <tt>Proc</tt> in case default should be recalculated
- # * <tt>:multiple</tt> - if true multiple values can be assigned to this filter.
- # By default multiple values are parsed from string using `,` separator.
+ # * <tt>:multiple</tt> - if true multiple values can be assigned to this filter.
+ # By default multiple values are parsed from string using `,` separator.
# But you can specify a different separator as option value. Default: false.
# * <tt>:allow_nil</tt> - determines if the value can be nil
# * <tt>:allow_blank</tt> - determines if the value can be blank
- # * <tt>:before</tt> - determines the position of this filter,
+ # * <tt>:before</tt> - determines the position of this filter,
# by adding it before the filter passed here (when using datagrid_form_for helper)
- # * <tt>:after</tt> - determines the position of this filter,
+ # * <tt>:after</tt> - determines the position of this filter,
# by adding it after the filter passed here (when using datagrid_form_for helper)
- # * <tt>:dummy</tt> - if true, this filter will not be applied automatically
+ # * <tt>:dummy</tt> - if true, this filter will not be applied automatically
# and will be just displayed in form. In case you may want to apply it manually.
#
# See: https://github.com/bogdan/datagrid/wiki/Filters for examples
View
25 lib/datagrid/filters/date_time_filter.rb
@@ -0,0 +1,25 @@
+require "datagrid/filters/ranged_filter"
+
+class Datagrid::Filters::DateTimeFilter < Datagrid::Filters::BaseFilter
+
+ include RangedFilter
+
+ def parse(value)
+ Datagrid::Utils.parse_datetime(value)
+ end
+
+ def format(value)
+ if formats.any? && value
+ value.strftime(formats.first)
+ else
+ super
+ end
+ end
+
+ protected
+
+ def formats
+ Array(Datagrid.configuration.datetime_formats)
+ end
+end
+
View
4 lib/datagrid/form_builder.rb
@@ -29,6 +29,10 @@ def datagrid_date_filter(attribute_or_filter, options = {})
datagrid_range_filter(:date, attribute_or_filter, options)
end
+ def datagrid_date_time_filter(attribute_or_filter, options = {})
+ datagrid_range_filter(:datetime, attribute_or_filter, options)
+ end
+
def datagrid_default_filter(attribute_or_filter, options = {})
filter = datagrid_get_filter(attribute_or_filter)
text_field filter.name, options.reverse_merge(:value => object.filter_value_as_string(filter))
View
3  lib/datagrid/locale/en.yml
@@ -16,6 +16,9 @@ en:
date:
range_separator:
"<span class=\"separator date\"> - </span>"
+ datetime:
+ range_separator:
+ "<span class=\"separator datetime\"> - </span>"
eboolean:
"yes": "Yes"
View
20 lib/datagrid/utils.rb
@@ -1,4 +1,4 @@
-module Datagrid
+module Datagrid
module Utils # :nodoc:
class << self
@@ -73,6 +73,24 @@ def parse_date(value)
nil
end
+ def parse_datetime(value)
+ return nil if value.blank?
+ return value if value.is_a?(Range)
+ if value.is_a?(String)
+ Array(Datagrid.configuration.datetime_formats).each do |format|
+ begin
+ return DateTime.strptime(value, format)
+ rescue ::ArgumentError
+ end
+ end
+ end
+ return DateTime.parse(value) if value.is_a?(String)
+ return value.to_datetime if value.respond_to?(:to_datetime)
+ value
+ rescue ::ArgumentError
+ nil
+ end
+
def format_date_as_timestamp(value)
if !value
value
View
150 spec/datagrid/filters/date_time_filter_spec.rb
@@ -0,0 +1,150 @@
+require 'spec_helper'
+
+describe Datagrid::Filters::DateTimeFilter do
+ {:active_record => Entry, :mongoid => MongoidEntry}.each do |orm, klass|
+ describe "with orm #{orm}" do
+ describe "timestamp to timestamp conversion" do
+ let(:klass) { klass }
+ subject do
+ test_report(:created_at => _created_at) do
+ scope { klass }
+ filter(:created_at, :datetime, :range => true)
+ end.assets.to_a
+ end
+
+ def entry_dated(date)
+ klass.create(:created_at => date)
+ end
+
+ context "when single datetime paramter given" do
+ let(:_created_at) { DateTime.now }
+ it { should include(entry_dated(_created_at))}
+ it { should_not include(entry_dated(_created_at - 1.second))}
+ it { should_not include(entry_dated(_created_at + 1.second))}
+ end
+
+ context "when range datetime range given" do
+ let(:_created_at) { [DateTime.now.beginning_of_day, DateTime.now.end_of_day] }
+ it { should include(entry_dated(1.second.ago))}
+ it { should include(entry_dated(Date.today.to_datetime))}
+ it { should include(entry_dated(Date.today.end_of_day.to_datetime))}
+ it { should_not include(entry_dated(Date.yesterday.end_of_day))}
+ it { should_not include(entry_dated(Date.tomorrow.beginning_of_day))}
+ end
+ end
+
+ end
+ end
+
+ it "should support datetime range given as array argument" do
+ e1 = Entry.create!(:created_at => DateTime.new(2013, 1, 1, 1, 0))
+ e2 = Entry.create!(:created_at => DateTime.new(2013, 1, 1, 2, 0))
+ e3 = Entry.create!(:created_at => DateTime.new(2013, 1, 1, 3, 0))
+ report = test_report(:created_at => [DateTime.new(2013, 1, 1, 1, 30).to_s, DateTime.new(2013, 1, 1, 2, 30).to_s]) do
+ scope { Entry }
+ filter(:created_at, :datetime, :range => true)
+ end
+ report.assets.should_not include(e1)
+ report.assets.should include(e2)
+ report.assets.should_not include(e3)
+ end
+
+ it "should support minimum datetime argument" do
+ e1 = Entry.create!(:created_at => DateTime.new(2013, 1, 1, 1, 0))
+ e2 = Entry.create!(:created_at => DateTime.new(2013, 1, 1, 2, 0))
+ e3 = Entry.create!(:created_at => DateTime.new(2013, 1, 1, 3, 0))
+ report = test_report(:created_at => [DateTime.new(2013, 1, 1, 1, 30).to_s, nil]) do
+ scope { Entry }
+ filter(:created_at, :datetime, :range => true)
+ end
+ report.assets.should_not include(e1)
+ report.assets.should include(e2)
+ report.assets.should include(e3)
+ end
+
+ it "should support maximum datetime argument" do
+ e1 = Entry.create!(:created_at => DateTime.new(2013, 1, 1, 1, 0))
+ e2 = Entry.create!(:created_at => DateTime.new(2013, 1, 1, 2, 0))
+ e3 = Entry.create!(:created_at => DateTime.new(2013, 1, 1, 3, 0))
+ report = test_report(:created_at => [nil, DateTime.new(2013, 1, 1, 2, 30).to_s]) do
+ scope { Entry }
+ filter(:created_at, :datetime, :range => true)
+ end
+ report.assets.should include(e1)
+ report.assets.should include(e2)
+ report.assets.should_not include(e3)
+ end
+
+ it "should find something in one second interval" do
+
+ e1 = Entry.create!(:created_at => DateTime.new(2013, 1, 1, 1, 0))
+ e2 = Entry.create!(:created_at => DateTime.new(2013, 1, 1, 2, 0))
+ e3 = Entry.create!(:created_at => DateTime.new(2013, 1, 1, 3, 0))
+ report = test_report(:created_at => (DateTime.new(2013, 1, 1, 2, 0)..DateTime.new(2013, 1, 1, 2, 0))) do
+ scope { Entry }
+ filter(:created_at, :datetime, :range => true)
+ end
+ report.assets.should_not include(e1)
+ report.assets.should include(e2)
+ report.assets.should_not include(e3)
+ end
+ it "should support invalid range" do
+
+ e1 = Entry.create!(:created_at => DateTime.new(2013, 1, 1, 1, 0))
+ e2 = Entry.create!(:created_at => DateTime.new(2013, 1, 1, 2, 0))
+ e3 = Entry.create!(:created_at => DateTime.new(2013, 1, 1, 3, 0))
+ report = test_report(:created_at => (DateTime.new(2013, 1, 1, 3, 0)..DateTime.new(2013, 1, 1, 1, 0))) do
+ scope { Entry }
+ filter(:created_at, :datetime, :range => true)
+ end
+ report.assets.should_not include(e1)
+ report.assets.should_not include(e2)
+ report.assets.should_not include(e3)
+ end
+
+
+ it "should support block" do
+ report = test_report(:created_at => DateTime.now) do
+ scope { Entry }
+ filter(:created_at, :datetime, :range => true) do |value|
+ where("created_at >= ?", value)
+ end
+ end
+ report.assets.should_not include(Entry.create!(:created_at => 1.day.ago))
+ report.assets.should include(Entry.create!(:created_at => DateTime.tomorrow))
+ end
+
+
+ context "when datetime format is configured" do
+ around(:each) do |example|
+ with_datetime_format(format = "%m/%d/%Y %H:%M") do
+ example.run
+ end
+ end
+
+ it "should have configurable datetime format" do
+ report = test_report(:created_at => "10/01/2013 01:00") do
+ scope {Entry}
+ filter(:created_at, :datetime)
+ end
+ report.created_at.should == DateTime.new(2013,10,01,1,0)
+ end
+
+ it "should support default explicit datetime" do
+ report = test_report(:created_at => DateTime.parse("2013-10-01 01:00")) do
+ scope {Entry}
+ filter(:created_at, :datetime)
+ end
+ report.created_at.should == DateTime.new(2013,10,01,1,0)
+ end
+ end
+
+
+ it "should automatically reverse Array if first more than last" do
+ report = test_report(:created_at => ["2013-01-01 01:00", "2012-01-01 01:00"]) do
@bogdan Owner
bogdan added a note

Body doesn't match the description of the test.
We need to test that datagrid automatically reverses:

["2013-01-01 02:00", "2012-01-01 01:00"] to ["2013-01-01 01:00", "2012-01-01 02:00"]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ scope {Entry}
+ filter(:created_at, :datetime, :range => true)
+ end
+ report.created_at.should == [DateTime.new(2012, 01, 01, 1, 0), DateTime.new(2013, 01, 01, 1, 0)]
+ end
+end
View
14 spec/support/configuration.rb
@@ -11,3 +11,17 @@ def with_date_format(format = "%m/%d/%Y")
end
end
end
+
+def with_datetime_format(format = "%m/%d/%Y")
+ begin
+ old_format = Datagrid.configuration.datetime_formats
+ Datagrid.configure do |config|
+ config.datetime_formats = format
+ end
+ yield
+ ensure
+ Datagrid.configure do |config|
+ config.datetime_formats = old_format
+ end
+ end
+end
Something went wrong with that request. Please try again.