date_params 1.0.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -3,6 +3,7 @@
3
3
  .bundle
4
4
  .config
5
5
  .yardoc
6
+ .idea/
6
7
  Gemfile.lock
7
8
  InstalledFiles
8
9
  _yardoc
data/.travis.yml ADDED
@@ -0,0 +1,3 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
data/HISTORY.md ADDED
@@ -0,0 +1,10 @@
1
+ # 2.0.0 / 2013-05-03
2
+
3
+ * Removed support for specifying the namespace as an array in preference of the the `:namespace` option.
4
+ * Added `datetime_parser` controller method for parsing date and time input fields to a DateTimeobject.
5
+ * Added travis support
6
+ * Removed the need to include DateParams::ControllerAdditions into the controller
7
+
8
+ # 1.0.0 / 2013-04-23
9
+
10
+ * Initial release
data/README.md CHANGED
@@ -1,12 +1,14 @@
1
1
  # DateParams
2
2
 
3
- Dates passed in by date-pickers or text-input fields need to be
4
- converted from their string format to a ruby Date to be able to be saved
5
- and manipulated. This gem provides a simple controller add-on to
3
+ Dates and times passed in as strings date-pickers or time-pickers need to be
4
+ converted from their string format to a ruby Date or DateTime to be able to be saved
5
+ and manipulated. This gem provides two simple controller add-ons to
6
6
  facilitate the conversion.
7
7
 
8
8
  ## Installation
9
9
 
10
+ Rails 3.x and Ruby 1.9.3 or 2.x required.
11
+
10
12
  Add this line to your application's Gemfile:
11
13
 
12
14
  gem 'date_params'
@@ -21,12 +23,12 @@ Or install it yourself as:
21
23
 
22
24
  ## Usage
23
25
 
24
- Include the controller additions in the controller that needs to parse
25
- date parameters and then specify dates to be formatted:
26
+ ### date_params
27
+
28
+ Specify the dates to be parsed:
26
29
  ```ruby
27
30
  class UsersController < ApplicationController
28
31
  # e.g. parameters come in as: { sign_up_on: '01/05/2013' }
29
- include DateParams::ControllerAdditions
30
32
  date_params :sign_up_on
31
33
  # and now params[:sign_up_on] is a Date object
32
34
  end
@@ -34,7 +36,6 @@ end
34
36
 
35
37
  Any options that a `before_filter` accepts can be passed in:
36
38
  ```ruby
37
- include DateParams::ControllerAdditions
38
39
  date_params :sign_up_on, only: [:index]
39
40
  ```
40
41
 
@@ -42,20 +43,34 @@ If date fields are namespaced in a model that can be specified with the
42
43
  `namespace` option:
43
44
  ```ruby
44
45
  # will parse parameters in the format of: { user: { searched_on: '01/04/2013', sign_up_on: '04/03/2013' } }
45
- include DateParams::ControllerAdditions
46
46
  date_params :searched_on, :sign_up_on, namespace: :user
47
47
  ```
48
48
 
49
- Or specify a namespace for each parameter individually:
49
+ Date format can be passed as an option (default is `%m/%d/%Y`):
50
50
  ```ruby
51
- include DateParams::ControllerAdditions
52
- date_params [:user, :searched_on], [:company, :sign_up_on]
51
+ date_params :search_on, :sign_up_on, date_format: '%d-%m-%Y'
53
52
  ```
54
53
 
55
- Date format can be passed as an option (default is `%m/%d/%Y`):
54
+ ### datetime_params
55
+
56
+ Specify the datetime fields that need to be parsed:
56
57
  ```ruby
57
- include DateParams::ControllerAdditions
58
- date_params :search_on, :sign_up_on, date_format: '%d-%m-%Y'
58
+ class UsersController < ApplicationController
59
+ # e.g. parameters come in as: { sign_up_at_date: '01/05/2013', sign_up_at_time: '7:30 pm' }
60
+ datetime_params :sign_up_at
61
+ # and now params[:sign_up_at] is a timezone-aware DateTime object
62
+ end
63
+ ```
64
+
65
+ In addition to the `:namespace` and `:date_format` options, the time format can be specified
66
+ (default is `%I:%M %p`):
67
+ ```ruby
68
+ date_params :sign_up_at, time_format: '%H:%M:%S'
69
+ ```
70
+
71
+ To specify exactly which fields should be parsed:
72
+ ```ruby
73
+ date_params { date: :sign_up_on, time: :sign_up_time, field: :sign_up_at }, only: :create
59
74
  ```
60
75
 
61
76
  ## Contributing
data/date_params.gemspec CHANGED
@@ -19,8 +19,10 @@ Gem::Specification.new do |spec|
19
19
  spec.require_paths = ['lib']
20
20
 
21
21
  spec.add_dependency 'activesupport'
22
+ spec.add_dependency 'tzinfo'
22
23
 
23
24
  spec.add_development_dependency 'bundler', '~> 1.3'
24
25
  spec.add_development_dependency 'rake'
25
26
  spec.add_development_dependency 'rspec'
27
+ spec.add_development_dependency 'pry-debugger'
26
28
  end
@@ -1,61 +1,32 @@
1
- require 'date'
2
1
  require 'active_support/concern'
3
- require 'active_support/core_ext/object/try'
4
- require 'active_support/core_ext/object/blank'
5
2
 
6
3
  module DateParams
7
4
  module ControllerAdditions
8
5
  extend ActiveSupport::Concern
9
6
 
10
7
  module ClassMethods
11
- # Usage:
12
- #
13
- # To convert only on specific actions use:
14
- # date_params :param_name, [:namespaced, :param_name], only: :action_name
15
- # If all variables are in a common namespace, use the namespace option:
16
- # date_params :param_name1, :param_name2, namespace: :namespaced
17
- # @see #parse_date_param!
8
+ # Converts a text field with a date, in a specified format, into a Date object
18
9
  def date_params(*args)
19
10
  options = args.extract_options!
20
11
  before_filter options do |controller|
21
- controller.parse_date_params(args, options)
12
+ args.each { |param| DateParams::Parser.new(param, options, controller.params).parse_date_param! }
22
13
  end
23
14
  end
24
- end
25
-
26
- # Usage:
27
- #
28
- # To convert params[:my_date]
29
- # date_params :my_date
30
- #
31
- # To convert params[:my_model][:my_date1] use one of the following:
32
- # parse_date_param!([:my_model, :my_date1])
33
- # parse_date_param!(:my_date1, namespace: :my_model)
34
- #
35
- # if the format of the data is not '%m/%d/%Y'
36
- # parse_date_param!(:my_date1, date_format: '%m/%Y')
37
- def parse_date_param!(param, options)
38
- param_path = Array(param).dup
39
- param_path.unshift options[:namespace] if options[:namespace] && param_path.length == 1
40
- date_format = options.fetch(:date_format, '%m/%d/%Y')
41
- traversed_params = params
42
15
 
43
- if param_path.length > 1
44
- param_key = param_path.pop
45
- param_path.each { |k| traversed_params = traversed_params.try :[], k }
46
- else
47
- param_key = param_path.first
16
+ # Similar to #date_params, but parses a date input field and a time input field
17
+ # and combines them into a new timezone-aware datetime field.
18
+ def datetime_params(*args)
19
+ options = args.extract_options!
20
+ before_filter options do |controller|
21
+ args.each { |param| DateParams::Parser.new(param, options, controller.params).parse_datetime_param! }
22
+ end
48
23
  end
49
-
50
- value = traversed_params.try(:[], param_key)
51
- return nil if value.blank?
52
- date_format = value =~ /\d{4}-\d{2}-\d{2}/ ? '%Y-%m-%d' : date_format
53
- date = Date.strptime(value, date_format)
54
- traversed_params[param_key] = date if date
55
24
  end
25
+ end
26
+ end
56
27
 
57
- def parse_date_params(the_params, options)
58
- the_params.each{ |param| parse_date_param! param, options }
59
- end
28
+ if defined? ActionController::Base
29
+ ActionController::Base.class_eval do
30
+ include DateParams::ControllerAdditions
60
31
  end
61
32
  end
@@ -0,0 +1,60 @@
1
+ require 'time'
2
+ require 'date'
3
+ require 'tzinfo'
4
+ require 'active_support/core_ext/time/zones'
5
+ require 'active_support/core_ext/time/calculations'
6
+ require 'active_support/time_with_zone'
7
+ require 'active_support/core_ext/object/try'
8
+ require 'active_support/core_ext/object/blank'
9
+ require 'active_support/core_ext/hash/keys'
10
+
11
+ class DateParams::Parser
12
+ attr_reader :param, :options, :params, :date_format, :time_format
13
+ def initialize(param, options, params)
14
+ @param = param
15
+ @options = options
16
+ @params = params
17
+ @date_format = options.fetch :date_format, '%m/%d/%Y'
18
+ @time_format = options.fetch :time_format, '%I:%M %p'
19
+ end
20
+
21
+ def parse_date_param!(field = param)
22
+ date_string = traversed_params.try(:[], field)
23
+ return if date_string.blank?
24
+ inferred_date_format = date_string =~ /\d{4}-\d{2}-\d{2}/ ? '%Y-%m-%d' : date_format
25
+ date = Date.strptime(date_string, inferred_date_format)
26
+ traversed_params[field] = date if date
27
+ end
28
+
29
+ def parse_datetime_param!
30
+ if param.is_a? Hash
31
+ fields = param
32
+ fields.assert_valid_keys :date, :time, :field
33
+ else
34
+ fields = {
35
+ date: "#{param}_date".to_sym,
36
+ time: "#{param}_time".to_sym,
37
+ field: param
38
+ }
39
+ end
40
+
41
+ date = parse_date_param! fields[:date]
42
+ return if date.blank?
43
+ time_string = traversed_params.try(:[], fields[:time])
44
+ return if time_string.blank?
45
+ datetime_format = "%Y-%m-%dT#{time_format}%z"
46
+ datetime_string = "#{date.iso8601}T#{time_string}#{Time.zone.name}"
47
+ datetime = Time.strptime(datetime_string, datetime_format).in_time_zone(Time.zone)
48
+ traversed_params[fields[:field]] = datetime if datetime
49
+ end
50
+
51
+ private
52
+
53
+ def traversed_params
54
+ traversed_params = params
55
+ if options[:namespace].present?
56
+ traversed_params = traversed_params.try :[], options[:namespace]
57
+ end
58
+ traversed_params
59
+ end
60
+ end
@@ -1,3 +1,3 @@
1
1
  module DateParams
2
- VERSION = "1.0.0"
2
+ VERSION = "2.0.0"
3
3
  end
data/lib/date_params.rb CHANGED
@@ -1,4 +1,6 @@
1
+ require 'date_params/controller_additions'
2
+
1
3
  module DateParams
2
4
  autoload :VERSION, 'date_params/version'
3
- autoload :ControllerAdditions, 'date_params/controller_additions.rb'
5
+ autoload :Parser, 'date_params/parser'
4
6
  end
@@ -0,0 +1,99 @@
1
+ require 'spec_helper'
2
+
3
+ describe DateParams::Parser do
4
+ let(:options) { {} }
5
+ let(:parser) { described_class.new param, options, params }
6
+
7
+ describe '#parse_date_param!' do
8
+ let(:params) do
9
+ {
10
+ date: '08/10/2012',
11
+ paginated_date: '2012-08-10',
12
+ invalid_date: '000000',
13
+ user: {
14
+ notified_on: '08/10/2012'
15
+ }
16
+ }
17
+ end
18
+ let(:date) { Date.parse '2012-08-10' }
19
+
20
+ context 'invalid format' do
21
+ let(:param) { :invalid_date }
22
+ it 'should raise when unknown format' do
23
+ expect { expect parser.parse_date_param! }.to raise_error ArgumentError
24
+ end
25
+ end
26
+
27
+ context 'valid format' do
28
+ before { parser.parse_date_param! }
29
+
30
+ describe 'param field is updated' do
31
+ let(:param) { :date }
32
+ subject { params[:date] }
33
+ it { should eq date }
34
+ end
35
+
36
+ context 'namespace option is present' do
37
+ let(:param) { :notified_on }
38
+ let(:options) { { namespace: :user } }
39
+ subject { params[:user][:notified_on] }
40
+ it { should eq date }
41
+ end
42
+
43
+ context 'date format is yyyy-mm-dd from pagination' do
44
+ let(:param) { :paginated_date }
45
+ subject { params[:paginated_date] }
46
+ it { should eq date }
47
+ end
48
+ end
49
+ end
50
+
51
+ describe '#parse_datetime_param!' do
52
+ before { Time.zone = 'EST' }
53
+ let(:params) do
54
+ {
55
+ created_at_date: '08/10/2012',
56
+ created_at_time: '12:30 am',
57
+ invalid_time: '1111',
58
+ empty_time: '',
59
+ user: {
60
+ notified_at_date: '08/10/2012',
61
+ notified_at_time: '12:30 am'
62
+ }
63
+ }
64
+ end
65
+ let(:datetime) { Time.zone.parse '2012-08-10 00:30' }
66
+
67
+ context 'invalid format' do
68
+ let(:param) { { date: :created_at_date, time: :invalid_time, field: :created_at } }
69
+ it 'should raise when unknown format' do
70
+ expect { expect parser.parse_datetime_param! }.to raise_error ArgumentError
71
+ end
72
+ end
73
+
74
+ context 'valid format' do
75
+ before { parser.parse_datetime_param! }
76
+
77
+ describe 'param field is updated' do
78
+ let(:param) { :created_at }
79
+ subject { params[:created_at] }
80
+ it { should eq datetime }
81
+ end
82
+
83
+ context 'namespace option is present' do
84
+ let(:param) { :notified_at }
85
+ let(:options) { { namespace: :user } }
86
+ subject { params[:user][:notified_at] }
87
+ it { should eq datetime }
88
+ end
89
+
90
+ context 'time is empty' do
91
+ let(:param) { { date: :created_at_date, time: :empty_time, field: :created_at } }
92
+ it 'parses the date but not the time' do
93
+ params[:created_at_date].should eq datetime.to_date
94
+ params[:created_at].should be_nil
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require 'rubygems'
2
2
  require 'bundler/setup'
3
+ require 'pry-debugger'
3
4
 
4
5
  require 'date_params'
5
6
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: date_params
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 2.0.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-04-23 00:00:00.000000000 Z
12
+ date: 2013-05-03 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -27,6 +27,22 @@ dependencies:
27
27
  - - ! '>='
28
28
  - !ruby/object:Gem::Version
29
29
  version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: tzinfo
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
30
46
  - !ruby/object:Gem::Dependency
31
47
  name: bundler
32
48
  requirement: !ruby/object:Gem::Requirement
@@ -75,6 +91,22 @@ dependencies:
75
91
  - - ! '>='
76
92
  - !ruby/object:Gem::Version
77
93
  version: '0'
94
+ - !ruby/object:Gem::Dependency
95
+ name: pry-debugger
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
78
110
  description: Dates passed in by date-pickers or text-input fields to a rails controller
79
111
  need to be converted to a ruby Date to be able to be saved and manipulated. This
80
112
  gem provides a simple controller add-on to facilitate the conversion.
@@ -85,15 +117,18 @@ extensions: []
85
117
  extra_rdoc_files: []
86
118
  files:
87
119
  - .gitignore
120
+ - .travis.yml
88
121
  - Gemfile
122
+ - HISTORY.md
89
123
  - LICENSE.txt
90
124
  - README.md
91
125
  - Rakefile
92
126
  - date_params.gemspec
93
127
  - lib/date_params.rb
94
128
  - lib/date_params/controller_additions.rb
129
+ - lib/date_params/parser.rb
95
130
  - lib/date_params/version.rb
96
- - spec/date_picker/controller_additions_spec.rb
131
+ - spec/date_params/parser_spec.rb
97
132
  - spec/spec_helper.rb
98
133
  homepage: https://github.com/LessonPlanet/date_params
99
134
  licenses:
@@ -121,5 +156,6 @@ signing_key:
121
156
  specification_version: 3
122
157
  summary: Convert date string parameters in a rails controller into Date objects.
123
158
  test_files:
124
- - spec/date_picker/controller_additions_spec.rb
159
+ - spec/date_params/parser_spec.rb
125
160
  - spec/spec_helper.rb
161
+ has_rdoc:
@@ -1,58 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe DateParams::ControllerAdditions do
4
- let(:mock_controller) do
5
- Class.new do
6
- attr_accessor :params
7
- include DateParams::ControllerAdditions
8
- end.new
9
- end
10
- let(:custom_params) do
11
- {
12
- date: '08/10/2012',
13
- paginated_date: '2012-08-10',
14
- invalid_date: '000000',
15
- model: {
16
- date: '08/10/2012'
17
- }
18
- }
19
- end
20
- let(:date) { Date.parse '2012-08-10' }
21
-
22
- context 'invalid format' do
23
- let(:param_spec) { :invalid_date }
24
- it 'should raise when unknown format' do
25
- mock_controller.params = custom_params
26
- expect { mock_controller.parse_date_param!(param_spec, {}) }.to raise_error ArgumentError, 'invalid date'
27
- end
28
- end
29
-
30
- context 'valid format' do
31
- before do
32
- mock_controller.params = custom_params
33
- mock_controller.parse_date_param!(param_spec, {})
34
- end
35
-
36
- context 'should update params' do
37
- let(:param_spec) { :date }
38
- subject { mock_controller.params[:date] }
39
- it { should eq date }
40
- end
41
-
42
- context 'should update nested params' do
43
- let(:param_spec) { [:model, :date] }
44
- subject { mock_controller.params[:model][:date] }
45
- it { should eq date }
46
-
47
- it 'should not change the original' do
48
- param_spec.should == [:model, :date]
49
- end
50
- end
51
-
52
- context 'when date format is yyyy-mm-dd from pagination' do
53
- let(:param_spec) { :paginated_date }
54
- subject { mock_controller.params[:paginated_date] }
55
- it { should eq date }
56
- end
57
- end
58
- end