multiparameter_attributes_handler 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2013 Rob Nichols
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,85 @@
1
+ == Multiparameter Attributes Handler
2
+
3
+ === Background
4
+
5
+ Rails form helpers for time, datetime and date return multiparameter attributes
6
+ that ActiveRecord objects are able to convert into parent attributes.
7
+
8
+ For example
9
+
10
+ date_select(:thing, :last_read)
11
+
12
+ when set to 24th June 2004, will generate
13
+
14
+ 'thing' => {
15
+ "last_read(1i)" => "2004",
16
+ "last_read(2i)" => "6",
17
+ "last_read(3i)" => "24"
18
+ }
19
+
20
+ ActiveRecord understands this and converts these key/value pairs into a date
21
+ object that is passed to thing.last_record=
22
+
23
+ === A solution without ActiveRecord
24
+
25
+ Multiparameter Attributes Handler allows other objects to do the same. In
26
+ particular, ActiveResource models.
27
+
28
+ It does this by modifying the way attributes= works. So for the above example,
29
+ the values passed down the attributes= chain gets converted to:
30
+
31
+ 'thing' => {
32
+ "last_read(1i)" => "2004",
33
+ "last_read(2i)" => "6",
34
+ "last_read(3i)" => "24",
35
+ "last_read" => Time.local('2004', '6', '24')
36
+ }
37
+
38
+ So for a ActiveResource Thing, this functionality is added like this:
39
+
40
+ class Thing < ActiveResource::Base
41
+ include MultiparameterAttributesHandler
42
+ end
43
+
44
+ === Only setter affected
45
+
46
+ Note that this gem provides handling of the parameters received from the form
47
+ submission. For the form helpers to work, they need to passed a date or time
48
+ to the form.
49
+
50
+ One solution is to over-ride the getter in the model. So for the Thing example
51
+ above, the complete solution would look like this:
52
+
53
+ require 'date'
54
+ class Thing < ActiveResource::Base
55
+ include MultiparameterAttributesHandler
56
+
57
+ def last_read
58
+ Date.parse(super)
59
+ end
60
+ end
61
+
62
+ Rails form date helpers will then work for last_read:
63
+
64
+ date_select(:thing, :last_read)
65
+
66
+ And in the controller's create and update methods:
67
+
68
+ thing.attributes = params[:thing]
69
+
70
+ Or
71
+
72
+ Thing.new(params[:thing])
73
+
74
+ Or
75
+
76
+ thing.update_attributes(params[:thing])
77
+
78
+
79
+ === Installation
80
+
81
+ This functionality is made available via the multiparameter_attributes_handler
82
+ gem. So add this to your gemfile:
83
+
84
+ gem 'multiparameter_attributes_handler'
85
+
data/Rakefile ADDED
@@ -0,0 +1,18 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/clean'
4
+ require 'rdoc/task'
5
+ require 'rake/testtask'
6
+
7
+ Rake::RDocTask.new do |rdoc|
8
+ files =['README.rdoc', 'MIT-LICENSE', 'lib/**/*.rb']
9
+ rdoc.rdoc_files.add(files)
10
+ rdoc.main = "README.rdoc" # page to start on
11
+ rdoc.title = "MultiparameterAttributesHandler Docs"
12
+ rdoc.rdoc_dir = 'doc/rdoc' # rdoc output folder
13
+ rdoc.options << '--line-numbers'
14
+ end
15
+
16
+ Rake::TestTask.new do |t|
17
+ t.test_files = FileList['test/**/*.rb']
18
+ end
@@ -0,0 +1,9 @@
1
+ require_relative 'multiparameter_attributes_handler/manipulator'
2
+ require_relative 'multiparameter_attributes_handler/multiparameter_attributes_handler_error'
3
+ module MultiparameterAttributesHandler
4
+
5
+ def attributes=(new_attributes)
6
+ super Manipulator.new(new_attributes).output
7
+ end
8
+
9
+ end
@@ -0,0 +1,120 @@
1
+ module MultiparameterAttributesHandler
2
+ class Manipulator
3
+
4
+ attr_accessor :hash
5
+
6
+ def initialize(hash)
7
+ @hash = hash
8
+ end
9
+
10
+ def multiparameters
11
+ keys = multiparameter_keys.collect do |k|
12
+ k.gsub(ends_with_number_letter_in_brackets, "")
13
+ end
14
+ keys.uniq!
15
+ keys.delete_if{|k| empty_date_values_for? k}
16
+ return keys
17
+ end
18
+
19
+ def values_for(multiparameter)
20
+ return hash[multiparameter] unless multiparameters.include? multiparameter
21
+ keys_for(multiparameter).collect{|k| hash[k]}
22
+ end
23
+
24
+ def value_of(multiparameter)
25
+ values = values_for(multiparameter)
26
+ return values unless values.kind_of? Array
27
+ convert_to_time(multiparameter, values)
28
+ end
29
+
30
+ def output
31
+ begin
32
+ multiparameters.each do |multiparameter|
33
+ hash[multiparameter] = value_of(multiparameter)
34
+ end
35
+ rescue => e
36
+ errors << e
37
+ end
38
+ return hash if errors.empty?
39
+ raise_combined_error(errors)
40
+ end
41
+
42
+ private
43
+ def convert_to_time(multiparameter, values)
44
+ begin
45
+ Time.local(*values)
46
+ rescue => e
47
+ msg = "Error determining value_of #{multiparameter} from #{values} (#{e.message})"
48
+ raise_assignment_errors(multiparameter, values, msg, e)
49
+ end
50
+ end
51
+
52
+ def multiparameter_keys
53
+ hash.keys.select{|k| k =~ ends_with_number_letter_in_brackets}
54
+ end
55
+
56
+ def ends_with_number_letter_in_brackets
57
+ /\(\d+\w+\)$/
58
+ end
59
+
60
+ def keys_for(multiparameter)
61
+ keys = multiparameter_keys.select{|k| /^#{multiparameter}\(/ =~ k}
62
+ add_missing_keys_for(multiparameter, keys)
63
+ return keys.sort if sequence_starting_at_one?(keys)
64
+
65
+ raise_assignment_errors(
66
+ multiparameter,
67
+ keys,
68
+ "key number sequence incomplete or not starting at one"
69
+ )
70
+
71
+ end
72
+
73
+ def add_missing_keys_for(multiparameter, keys)
74
+ postscript = characters_after_sequence_number(keys.first)
75
+ numbers = sequence_numbers(keys)
76
+ (1..numbers.last).each do |number|
77
+ next if number < 3 # don't replace missing date keys
78
+ next if numbers.include? number
79
+ key = "#{multiparameter}(#{number}#{postscript})"
80
+ hash[key] = '00'
81
+ keys << key
82
+ end
83
+ end
84
+
85
+ def characters_after_sequence_number(sample_key)
86
+ match = sample_key.match(/\(\d+(\w*)\)/)
87
+ match ? match[1] : ""
88
+ end
89
+
90
+ def empty_date_values_for?(multiparameter)
91
+ keys = keys_for(multiparameter)[0..2].select{|p| hash[p].empty?}
92
+ !keys.empty?
93
+ end
94
+
95
+ def sequence_starting_at_one?(keys)
96
+ numbers = sequence_numbers(keys)
97
+ expected = (1..10).to_a
98
+ numbers == expected[0..(numbers.length - 1)]
99
+ end
100
+
101
+ def sequence_numbers(keys)
102
+ keys.collect{|k| m = k.match(/\((\d+)\w+\)/); m ? m[1].to_i : nil}.sort
103
+ end
104
+
105
+ def errors
106
+ @errors ||= []
107
+ end
108
+
109
+ def raise_assignment_errors(multiparameter, values, message, error = StandardError)
110
+ msg = "Error determining value_of #{multiparameter} from #{values} (#{message})"
111
+ raise AttributeAssignmentError.new(error, multiparameter), msg
112
+ end
113
+
114
+ def raise_combined_error(errors)
115
+ error_descriptions = errors.collect { |ex| ex.message }.join(",")
116
+ msg = "#{errors.size} error(s) on determining value of multiparameter attributes [#{error_descriptions}]"
117
+ raise MultiparameterAssignmentErrors.new(errors), msg
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,29 @@
1
+
2
+ module MultiparameterAttributesHandler
3
+
4
+ class MultiparameterAttributesHandlerError < StandardError
5
+
6
+ end
7
+
8
+ # Raised when an error occurred while doing a mass assignment to an attribute through the
9
+ # <tt>attributes=</tt> method. The exception has an +attribute_name+ property that is
10
+ # the name of the offending attribute.
11
+ class AttributeAssignmentError < MultiparameterAttributesHandlerError
12
+ attr_reader :exception_raised, :attribute_name
13
+ def initialize(exception_raised, attribute_name)
14
+ @exception_raised = exception_raised
15
+ @attribute_name = attribute_name
16
+ end
17
+ end
18
+
19
+ # Raised when there are multiple errors while doing a mass assignment through the +attributes+
20
+ # method. The exception has an +errors+ property that contains an array of AttributeAssignmentError
21
+ # objects, each corresponding to the error while assigning to an attribute.
22
+ class MultiparameterAssignmentErrors < MultiparameterAttributesHandlerError
23
+ attr_reader :errors
24
+ def initialize(errors)
25
+ @errors = errors
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,13 @@
1
+ module MultiparameterAttributesHandler
2
+ VERSION = "0.0.1"
3
+ end
4
+
5
+ # History
6
+ # =======
7
+ #
8
+ # 0.0.1: First gem
9
+ # ----------------
10
+ #
11
+ # Released for testing and review of functionality.
12
+ #
13
+
@@ -0,0 +1,85 @@
1
+ # To change this template, choose Tools | Templates
2
+ # and open the template in the editor.
3
+
4
+ $:.unshift File.join(File.dirname(__FILE__),'..','lib')
5
+
6
+ require 'test/unit'
7
+ require_relative '../../lib/multiparameter_attributes_handler'
8
+
9
+ module MultiparameterAttributesHandler
10
+ class ManipulatorTest < Test::Unit::TestCase
11
+
12
+ def setup
13
+ @hash = {
14
+ "last_read(1i)" => "2004",
15
+ "last_read(2i)" => "6",
16
+ "last_read(3i)" => "24",
17
+ "other(1i)" => "2012",
18
+ "other(2i)" => "2",
19
+ "other(3i)" => "2",
20
+ "other(4i)" => "11",
21
+ "other(5i)" => "35",
22
+ "foo" => 'bar',
23
+ "something" => 'ho',
24
+ "something_else" => 'hum'
25
+ }
26
+ @original = @hash.clone
27
+ @manipulator = Manipulator.new(@hash)
28
+ @output = @manipulator.output
29
+ end
30
+
31
+ def test_multiparameters
32
+ assert_equal(['last_read', 'other'], @manipulator.multiparameters)
33
+ end
34
+
35
+ def test_values_for
36
+ assert_equal(@hash['foo'], @manipulator.values_for('foo'))
37
+ end
38
+
39
+ def test_values_for_multiparameter
40
+ assert_equal(['2004', '6', '24'], @manipulator.values_for('last_read'))
41
+ end
42
+
43
+ def test_value_of
44
+ assert_equal(@hash['foo'], @manipulator.value_of('foo'))
45
+ end
46
+
47
+ def test_value_of_multiparameter
48
+ assert_equal(Time.local(*@manipulator.values_for('last_read')), @manipulator.value_of('last_read'))
49
+ assert_equal(Time.local(*@manipulator.values_for('other')), @manipulator.value_of('other'))
50
+ end
51
+
52
+ def test_output_returns_original_content
53
+ @hash.each do |key, value|
54
+ assert_equal(value, @output[key])
55
+ end
56
+ end
57
+
58
+ def test_output_returns_multiparameter_content_and_original_content
59
+ combined_length = @original.length + @manipulator.multiparameters.length
60
+ assert_equal(combined_length, @output.length)
61
+ end
62
+
63
+ def test_output_returns_multiparameter_content
64
+ @manipulator.multiparameters.each do |multiparameter|
65
+ assert_equal(@manipulator.value_of(multiparameter), @output[multiparameter])
66
+ end
67
+ end
68
+
69
+ def test_output_manipulates_hash
70
+ assert_not_equal(@original, @hash)
71
+ assert_equal(@output, @hash)
72
+ end
73
+
74
+ def test_partial_multiparameters_are_ignored
75
+ [
76
+ {"last_read(1i)" => "2004", "last_read(2i)" => "6", "last_read(3i)" => ""},
77
+ {"last_read(1i)" => "2004", "last_read(2i)" => "", "last_read(3i)" => "24"},
78
+ {"last_read(1i)" => "", "last_read(2i)" => "6", "last_read(3i)" => "24"}
79
+ ].each do |params|
80
+ assert_equal([], Manipulator.new(params).multiparameters, "#{params.inspect} should return []")
81
+ end
82
+ end
83
+
84
+ end
85
+ end
@@ -0,0 +1,28 @@
1
+ # To change this template, choose Tools | Templates
2
+ # and open the template in the editor.
3
+
4
+ $:.unshift File.join(File.dirname(__FILE__),'..','lib')
5
+
6
+ require 'test/unit'
7
+ require_relative '../../lib/multiparameter_attributes_handler'
8
+
9
+ module MultiparameterAttributesHandler
10
+ class MultiparameterAttributesHandlerErrorTest < Test::Unit::TestCase
11
+
12
+ def test_error
13
+ assert_raise RuntimeError do
14
+ raise "Oh yes"
15
+ end
16
+ end
17
+
18
+ def test_attribute_assignment_error
19
+ error = assert_raise AttributeAssignmentError do
20
+ raise AttributeAssignmentError.new('b', 'c'), 'd'
21
+ end
22
+ assert_equal('d', error.message)
23
+ assert_equal('b', error.exception_raised)
24
+ assert_equal('c', error.attribute_name)
25
+ end
26
+
27
+ end
28
+ end
data/test/thing.rb ADDED
@@ -0,0 +1,16 @@
1
+ require_relative '../lib/multiparameter_attributes_handler'
2
+
3
+ class Parent
4
+ attr_accessor :attributes
5
+ end
6
+
7
+
8
+ class Thing < Parent
9
+
10
+ include MultiparameterAttributesHandler
11
+
12
+ def initialize
13
+
14
+ end
15
+ end
16
+
@@ -0,0 +1,183 @@
1
+ $:.unshift File.join(File.dirname(__FILE__),'..','lib')
2
+
3
+ require 'test/unit'
4
+ require 'date'
5
+ require_relative 'thing'
6
+
7
+ class ThingTest < Test::Unit::TestCase
8
+
9
+ def setup
10
+ @thing = Thing.new
11
+ end
12
+
13
+ def test_multiparameter_attributes_on_date
14
+ attributes = { "last_read(1i)" => "2004", "last_read(2i)" => "6", "last_read(3i)" => "24" }
15
+ @thing.attributes = attributes
16
+ # note that extra #to_date call allows test to pass for Oracle, which
17
+ # treats dates/times the same
18
+ assert_equal Time.local(2004, 6, 24), @thing.attributes['last_read']
19
+ end
20
+
21
+ def test_multiparameter_attributes_on_date_with_empty_year
22
+ attributes = { "last_read(1i)" => "", "last_read(2i)" => "6", "last_read(3i)" => "24" }
23
+ @thing.attributes = attributes
24
+ # note that extra #to_date call allows test to pass for Oracle, which
25
+ # treats dates/times the same
26
+ assert_nil @thing.attributes['last_read']
27
+ end
28
+
29
+ def test_multiparameter_attributes_on_date_with_empty_month
30
+ attributes = { "last_read(1i)" => "2004", "last_read(2i)" => "", "last_read(3i)" => "24" }
31
+ @thing.attributes = attributes
32
+ # note that extra #to_date call allows test to pass for Oracle, which
33
+ # treats dates/times the same
34
+ assert_nil @thing.attributes['last_read']
35
+ end
36
+
37
+ def test_multiparameter_attributes_on_date_with_empty_day
38
+ attributes = { "last_read(1i)" => "2004", "last_read(2i)" => "6", "last_read(3i)" => "" }
39
+ @thing.attributes = attributes
40
+ # note that extra #to_date call allows test to pass for Oracle, which
41
+ # treats dates/times the same
42
+ assert_nil @thing.attributes['last_read']
43
+ end
44
+
45
+ def test_multiparameter_attributes_on_date_with_empty_day_and_year
46
+ attributes = { "last_read(1i)" => "", "last_read(2i)" => "6", "last_read(3i)" => "" }
47
+ @thing.attributes = attributes
48
+ # note that extra #to_date call allows test to pass for Oracle, which
49
+ # treats dates/times the same
50
+ assert_nil @thing.attributes['last_read']
51
+ end
52
+
53
+ def test_multiparameter_attributes_on_date_with_empty_day_and_month
54
+ attributes = { "last_read(1i)" => "2004", "last_read(2i)" => "", "last_read(3i)" => "" }
55
+ @thing.attributes = attributes
56
+ # note that extra #to_date call allows test to pass for Oracle, which
57
+ # treats dates/times the same
58
+ assert_nil @thing.attributes['last_read']
59
+ end
60
+
61
+ def test_multiparameter_attributes_on_date_with_empty_year_and_month
62
+ attributes = { "last_read(1i)" => "", "last_read(2i)" => "", "last_read(3i)" => "24" }
63
+ @thing.attributes = attributes
64
+ # note that extra #to_date call allows test to pass for Oracle, which
65
+ # treats dates/times the same
66
+ assert_nil @thing.attributes['last_read']
67
+ end
68
+
69
+ def test_multiparameter_attributes_on_date_with_all_empty
70
+ attributes = { "last_read(1i)" => "", "last_read(2i)" => "", "last_read(3i)" => "" }
71
+ @thing.attributes = attributes
72
+ assert_nil @thing.attributes['last_read']
73
+ end
74
+
75
+ def test_multiparameter_attributes_on_time
76
+ attributes = {
77
+ "written_on(1i)" => "2004", "written_on(2i)" => "6", "written_on(3i)" => "24",
78
+ "written_on(4i)" => "16", "written_on(5i)" => "24", "written_on(6i)" => "00"
79
+ }
80
+ @thing.attributes = attributes
81
+ assert_equal Time.local(2004, 6, 24, 16, 24, 0), @thing.attributes['written_on']
82
+ end
83
+
84
+ def test_multiparameter_attributes_on_time_with_no_date
85
+ ex = assert_raise(MultiparameterAttributesHandler::MultiparameterAssignmentErrors) do
86
+ attributes = {
87
+ "written_on(4i)" => "16", "written_on(5i)" => "24", "written_on(6i)" => "00"
88
+ }
89
+ @thing.attributes = attributes
90
+ end
91
+ assert_equal("written_on", ex.errors[0].attribute_name)
92
+ end
93
+
94
+ def test_multiparameter_attributes_on_time_with_invalid_time_params
95
+ ex = assert_raise(MultiparameterAttributesHandler::MultiparameterAssignmentErrors) do
96
+ attributes = {
97
+ "written_on(1i)" => "2004", "written_on(2i)" => "6", "written_on(3i)" => "24",
98
+ "written_on(4i)" => "2004", "written_on(5i)" => "36", "written_on(6i)" => "64",
99
+ }
100
+ @thing.attributes = attributes
101
+ end
102
+ assert_equal("written_on", ex.errors[0].attribute_name)
103
+ end
104
+
105
+ def test_multiparameter_attributes_on_time_with_old_date
106
+ attributes = {
107
+ "written_on(1i)" => "1850", "written_on(2i)" => "6", "written_on(3i)" => "24",
108
+ "written_on(4i)" => "16", "written_on(5i)" => "24", "written_on(6i)" => "00"
109
+ }
110
+ @thing.attributes = attributes
111
+ # testing against to_s(:db) representation because either a Time or a DateTime might be returned, depending on platform
112
+ assert_equal "1850-06-24 16:24:00", @thing.attributes['written_on'].strftime("%Y-%m-%d %H:%M:%S")
113
+ end
114
+
115
+ def test_multiparameter_attributes_on_time_will_raise_on_big_time_if_missing_date_parts
116
+ ex = assert_raise(MultiparameterAttributesHandler::MultiparameterAssignmentErrors) do
117
+ attributes = {
118
+ "written_on(4i)" => "16", "written_on(5i)" => "24"
119
+ }
120
+ @thing.attributes = attributes
121
+ end
122
+ assert_equal("written_on", ex.errors[0].attribute_name)
123
+ end
124
+
125
+ def test_multiparameter_attributes_on_time_with_raise_on_small_time_if_missing_date_parts
126
+ ex = assert_raise(MultiparameterAttributesHandler::MultiparameterAssignmentErrors) do
127
+ attributes = {
128
+ "written_on(4i)" => "16", "written_on(5i)" => "12", "written_on(6i)" => "02"
129
+ }
130
+ @thing.attributes = attributes
131
+ end
132
+ assert_equal("written_on", ex.errors[0].attribute_name)
133
+ end
134
+
135
+ def test_multiparameter_attributes_on_time_will_ignore_hour_if_missing
136
+ attributes = {
137
+ "written_on(1i)" => "2004", "written_on(2i)" => "12", "written_on(3i)" => "12",
138
+ "written_on(5i)" => "12", "written_on(6i)" => "02"
139
+ }
140
+ @thing.attributes = attributes
141
+ assert_equal Time.local(2004, 12, 12, 0, 12, 2), @thing.attributes['written_on']
142
+ end
143
+
144
+ def test_multiparameter_attributes_on_time_will_ignore_hour_if_blank
145
+ attributes = {
146
+ "written_on(1i)" => "", "written_on(2i)" => "", "written_on(3i)" => "",
147
+ "written_on(4i)" => "", "written_on(5i)" => "12", "written_on(6i)" => "02"
148
+ }
149
+ @thing.attributes = attributes
150
+ assert_nil @thing.attributes['written_on']
151
+ end
152
+
153
+ def test_multiparameter_attributes_on_time_will_ignore_date_if_empty
154
+ attributes = {
155
+ "written_on(1i)" => "", "written_on(2i)" => "", "written_on(3i)" => "",
156
+ "written_on(4i)" => "16", "written_on(5i)" => "24"
157
+ }
158
+
159
+ @thing.attributes = attributes
160
+ assert_nil @thing.attributes['written_on']
161
+ end
162
+
163
+ def test_multiparameter_attributes_on_time_with_seconds_will_ignore_date_if_empty
164
+ attributes = {
165
+ "written_on(1i)" => "", "written_on(2i)" => "", "written_on(3i)" => "",
166
+ "written_on(4i)" => "16", "written_on(5i)" => "12", "written_on(6i)" => "02"
167
+ }
168
+
169
+ @thing.attributes = attributes
170
+ assert_nil @thing.attributes['written_on']
171
+ end
172
+
173
+ def test_multiparameter_attributes_on_time_with_empty_seconds
174
+ attributes = {
175
+ "written_on(1i)" => "2004", "written_on(2i)" => "6", "written_on(3i)" => "24",
176
+ "written_on(4i)" => "16", "written_on(5i)" => "24", "written_on(6i)" => ""
177
+ }
178
+
179
+ @thing.attributes = attributes
180
+ assert_equal Time.local(2004, 6, 24, 16, 24, 0), @thing.attributes['written_on']
181
+ end
182
+
183
+ end
metadata ADDED
@@ -0,0 +1,62 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: multiparameter_attributes_handler
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Rob Nichols
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-03-05 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: Rails forms helpers for date and time fields generate multiparameter
15
+ params. multiparameter_attributes_handler allows objects to assign these to thier
16
+ attributes,
17
+ email:
18
+ - rob@undervale.co.uk
19
+ executables: []
20
+ extensions: []
21
+ extra_rdoc_files: []
22
+ files:
23
+ - lib/multiparameter_attributes_handler/version.rb
24
+ - lib/multiparameter_attributes_handler/manipulator.rb
25
+ - lib/multiparameter_attributes_handler/multiparameter_attributes_handler_error.rb
26
+ - lib/multiparameter_attributes_handler.rb
27
+ - MIT-LICENSE
28
+ - Rakefile
29
+ - README.rdoc
30
+ - test/thing.rb
31
+ - test/multiparameter_attributes_handler/multiparameter_attributes_handler_error_test.rb
32
+ - test/multiparameter_attributes_handler/manipulator_test.rb
33
+ - test/thing_test.rb
34
+ homepage: https://github.com/reggieb/multiparameter_attributes_handler
35
+ licenses: []
36
+ post_install_message:
37
+ rdoc_options: []
38
+ require_paths:
39
+ - lib
40
+ required_ruby_version: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ required_rubygems_version: !ruby/object:Gem::Requirement
47
+ none: false
48
+ requirements:
49
+ - - ! '>='
50
+ - !ruby/object:Gem::Version
51
+ version: '0'
52
+ requirements: []
53
+ rubyforge_project:
54
+ rubygems_version: 1.8.24
55
+ signing_key:
56
+ specification_version: 3
57
+ summary: Allows objects with attributes, to handle multiparameter params
58
+ test_files:
59
+ - test/thing.rb
60
+ - test/multiparameter_attributes_handler/multiparameter_attributes_handler_error_test.rb
61
+ - test/multiparameter_attributes_handler/manipulator_test.rb
62
+ - test/thing_test.rb