amount_field 1.4.0

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.
@@ -0,0 +1,38 @@
1
+ == 1.4.0 2009-10-06
2
+
3
+ * fix: negative values like '-1,00', '-1,0', '-1,' or '-1' are considered valid
4
+ * add test for '-value' and '+value'
5
+ * more test values and easier usage in tests
6
+
7
+ == 1.3.0 2009-09-06
8
+
9
+ * fix: helper amount_field_tag no works as expected (accepting name and value instead of object and method)
10
+ * add helper amount_field for ActionView::Base and amount_field for ActionView::Helpers::FormBuilder
11
+ * use an instance variable internally for the original assigned value and remove class AssignedValue
12
+
13
+ == 1.2.0 2009-09-04
14
+
15
+ * fix: an invalid value is still invalid after multiple calls to valid?
16
+
17
+ == 1.1.0 2009-08-31
18
+
19
+ * Fix "undefined method `to_f' for [...]:Array" by supported attribute of type float
20
+ (even if it is not a good idea to use float for amount because of rounding errors)
21
+ * Default configuration uses I18n.t('number.amount_field.format') from the plugin file
22
+ amount_field/locale/(en|de).yml. This means the default configuration depends on I18n.locale
23
+ and is not necessarily the german format by default anymore.
24
+ * The delimiter, separator and precision are now optional, so "1.234,00", "1234,00" and "1234" are
25
+ all valid at the same time.
26
+
27
+ == 1.0.2 2009-08-07
28
+
29
+ * fix typo and update readme concerning installation
30
+
31
+ == 1.0.1 2009-08-07
32
+
33
+ * Bugfix: a given format option for one amount field does not manipulate the default configuration
34
+
35
+ == 1.0.0 2009-07-28
36
+
37
+ * Initial release
38
+
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 [Thomas Baustert]
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.
@@ -0,0 +1,20 @@
1
+ History.txt
2
+ MIT-LICENSE
3
+ Manifest
4
+ README.rdoc
5
+ Rakefile
6
+ init.rb
7
+ install.rb
8
+ lib/amount_field.rb
9
+ lib/amount_field/configuration.rb
10
+ lib/amount_field/form_helper.rb
11
+ lib/amount_field/form_tag_helper.rb
12
+ lib/amount_field/validations.rb
13
+ locale/de.yml
14
+ locale/en.yml
15
+ test/form_helper_test.rb
16
+ test/form_tag_helper_test.rb
17
+ test/models/test_product.rb
18
+ test/test_helper.rb
19
+ test/validations_test.rb
20
+ uninstall.rb
@@ -0,0 +1,181 @@
1
+ = AmountField
2
+
3
+ Rails gem/plugin that accepts (amount) values in german or us format like 1.234,56 or 1,234.56".
4
+
5
+ Only tested for Rails 2.3. It may works with older versions but I haven't tested it.
6
+ Drop me a line if you encounter problems.
7
+
8
+ == Installation
9
+
10
+ As Gem:
11
+
12
+ $ gem sources -a http://gems.github.com (you only have to do this once)
13
+ $ sudo gem install thomasbaustert-amount_field
14
+
15
+ As plugin:
16
+
17
+ $ script/plugin install git://github.com/thomasbaustert/amount_field.git
18
+
19
+ == Example
20
+
21
+ First: Use the helper <tt>amount_field</tt> instead of the <tt>text_field</tt> helper:
22
+
23
+ <% form_for(@product) do |f| %>
24
+ <%= f.amount_field :price %>
25
+ ...
26
+ <% end %>
27
+
28
+ <% form_for(@product) do |f| %>
29
+ <%= amount_field :product, :price %>
30
+ ...
31
+ <% end %>
32
+
33
+ The helper <tt>amount_field_tag</tt> is provided too, but you have to handle the validation on
34
+ your own:
35
+
36
+ <% form_tag(:action => "create", {}) do -%>
37
+ <%= amount_field_tag :price, 1234.56 %>
38
+ ...
39
+
40
+ Second: Use the validation macro <tt>validates_amount_format_of</tt> in your model:
41
+
42
+ class Product < ActiveRecord::Base
43
+ validates_amount_format_of :price
44
+ validates_numericality_of :price
45
+ validates_presence_of :price
46
+ ...
47
+ end
48
+
49
+ Note! Make sure you always call <tt>validates_amount_format_of</tt> *before* every
50
+ other validation macro for the same attribute (e.g. before <tt>validates_numericality_of</tt>
51
+ and <tt>validates_presence_of</tt> for <tt>price</tt>).
52
+
53
+ == Configuration
54
+
55
+ The following configuration is supported:
56
+
57
+ === Format Configuration
58
+
59
+ Definition:
60
+
61
+ Delimiter = thousand separator (e.g. '.' in 1.234.567)
62
+ Separator = separator of value and decimal places (e.g. ',' in 12,56)
63
+ Precision = number of decimal places
64
+
65
+ The default format configuration is defined via Rails I18n and accessable through the key
66
+ <tt>number.amount_field.format</tt> from the file <tt>amount_field/locale/(en|de).yml</tt>.
67
+
68
+ Example:
69
+
70
+ I18n.locale = :de
71
+ I18n.t('number.amount_field.format') # => { :precision => 2, :delimiter => '.', :separator => ',' }
72
+
73
+ Currently only the locale <tt>de</tt> and<tt>en</tt> are supported.
74
+
75
+ If you want to define the default configuration independent from I18n, you can set it as follows:
76
+
77
+ AmountField::ActiveRecord::Validations.configuration =
78
+ { :precision => 1, :delimiter => ',', :separator => '.' }
79
+
80
+ An explicitly defined format will overwrite the default configuration for that attribute:
81
+
82
+ validates_amount_format_of :price, :separator => '.', :delimiter => ',', :precision => 1
83
+ # VALID: "1,234.5" (1234.5)
84
+
85
+ Standard Rails options like <tt>:allow_blank</tt>, or <tt>:allow_nil</tt> are supported:
86
+
87
+ validates_amount_format_of :price, :allow_blank => true
88
+
89
+ === CSS class and prefix
90
+
91
+ By default the input field contains the CSS class <tt>amount_field</tt> so you can define
92
+ a CSS layout for every amount field like:
93
+
94
+ input.amount_field {
95
+ text-align:right;
96
+ }
97
+
98
+ The method prefix and the CSS class can be changed as follows:
99
+
100
+ AmountField::Configuration.prefix = "my_prefix"
101
+ AmountField::Configuration.css_class = "my_class"
102
+
103
+ That will create the html:
104
+
105
+ <input name="product[my_prefix_price]" class=" my_class"...
106
+
107
+ and the appropriate method <tt>my_prefix_price=(value)</tt>.
108
+
109
+ == Input
110
+
111
+ By default delimiter, separator and precision are optional, so "1.234,00", "1234,00" and "1234"
112
+ are all valid for the german locale (de) at the same time.
113
+
114
+ In all other cases the validation will fail and add an error message to the original
115
+ attribute (e.g. <tt>price</tt>). (See Error Messages)
116
+
117
+ == Output
118
+
119
+ The helper <tt>amount_field</tt> uses the Rails helper <tt>number_with_precision</tt> internally
120
+ and passes the plugin format configuration as an argument. A value like 1234.56 is therefore
121
+ displayed as "1.234,56" for the locale <tt>de</tt> and "1,234.56" for the locale <tt>en</tt>.
122
+
123
+ You can explicitly set the format configuration with the option <tt>format</tt>:
124
+
125
+ amount_field(:price, :format => { :separator => '', ... })
126
+
127
+ And it is possible to pass the value explicitly:
128
+
129
+ amount_field(:price, :value => ...)
130
+
131
+ == Error Messages
132
+
133
+ By default the german and english messages are taken from the file
134
+ <tt>amount_field/locale/(en|de).yml</tt> through the key
135
+ <tt>activerecord.errors.messages.invalid_amount_format</tt>.
136
+
137
+ You can define your own by adding your Yaml file to the load path like:
138
+
139
+ # environment.rb
140
+ I18n.load_path << "#{RAILS_ROOT}/locale/en.yml"
141
+
142
+ # "#{RAILS_ROOT}/locale/en.yml"
143
+ de:
144
+ activerecord:
145
+ errors:
146
+ messages:
147
+ invalid_amount_format: "bla ... '{{value}}' blub ... ({{format_example}})"
148
+
149
+ The placeholder <tt>{{value}}</tt> is substituted with the given value (e.g. "1.x") and
150
+ <tt>{{format_example}}</tt> with a valid example of the currently accepted format (e.g. 'd.ddd,dd').
151
+
152
+ == How does it work?
153
+
154
+ Basically the helper <tt>amount_field</tt> defines a input field like so:
155
+
156
+ <input name="product[amount_field_price]" class=" amount_field"...
157
+
158
+ The validation macro <tt>validates_amount_format_of</tt> defines a special setter method
159
+ <tt>amount_field_price=(value)</tt> that accept the value. After successfully format
160
+ validation the original parameter is converted to a ruby value (e.g. "1.234,56" to 1234.56)
161
+ and assigned to the original attribute <tt>price</tt>. Following validation macros work on
162
+ the converted value. That's why it is currently important to call
163
+ <tt>validates_amount_format_of</tt> before every other macro.
164
+
165
+ == Running Tests
166
+
167
+ You need a database <tt>gem_amount_field_test</tt> to run all tests.
168
+ See test_helper.rb for details.
169
+
170
+ == Credits
171
+
172
+ * Michael Schiller (for feedback and ideas)
173
+
174
+ == Contact
175
+
176
+ For comments and question feel free to contact me: business@thomasbaustert.de
177
+
178
+ If you are using the plugin, consider recommending me at workingwithrails.com:
179
+ http://workingwithrails.com/person/6131-thomas-baustert
180
+
181
+ Copyright (c) 2009 [Thomas Baustert], released under the MIT license
@@ -0,0 +1,12 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'echoe'
4
+
5
+ Echoe.new('amount_field', '1.4.0') do |p|
6
+ p.description = "Rails gem/plugin that accepts (amount) values in german or us format like 1.234,56 or 1,234.56"
7
+ p.url = "http://github.com/thomasbaustert/amount_field"
8
+ p.author = "Thomas Baustert"
9
+ p.email =" business@thomasbaustert.de"
10
+ p.ignore_pattern = ["tmp/*", "script/*"]
11
+ p.development_dependencies = []
12
+ end
@@ -0,0 +1,31 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{amount_field}
5
+ s.version = "1.4.0"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Thomas Baustert"]
9
+ s.date = %q{2009-10-06}
10
+ s.description = %q{Rails gem/plugin that accepts (amount) values in german or us format like 1.234,56 or 1,234.56}
11
+ s.email = %q{ business@thomasbaustert.de}
12
+ s.extra_rdoc_files = ["README.rdoc", "lib/amount_field.rb", "lib/amount_field/configuration.rb", "lib/amount_field/form_helper.rb", "lib/amount_field/form_tag_helper.rb", "lib/amount_field/validations.rb"]
13
+ s.files = ["History.txt", "MIT-LICENSE", "Manifest", "README.rdoc", "Rakefile", "init.rb", "install.rb", "lib/amount_field.rb", "lib/amount_field/configuration.rb", "lib/amount_field/form_helper.rb", "lib/amount_field/form_tag_helper.rb", "lib/amount_field/validations.rb", "locale/de.yml", "locale/en.yml", "test/form_helper_test.rb", "test/form_tag_helper_test.rb", "test/models/test_product.rb", "test/test_helper.rb", "test/validations_test.rb", "uninstall.rb", "amount_field.gemspec"]
14
+ s.homepage = %q{http://github.com/thomasbaustert/amount_field}
15
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Amount_field", "--main", "README.rdoc"]
16
+ s.require_paths = ["lib"]
17
+ s.rubyforge_project = %q{amount_field}
18
+ s.rubygems_version = %q{1.3.5}
19
+ s.summary = %q{Rails gem/plugin that accepts (amount) values in german or us format like 1.234,56 or 1,234.56}
20
+ s.test_files = ["test/form_helper_test.rb", "test/form_tag_helper_test.rb", "test/models/test_product.rb", "test/test_helper.rb", "test/validations_test.rb"]
21
+
22
+ if s.respond_to? :specification_version then
23
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
24
+ s.specification_version = 3
25
+
26
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
27
+ else
28
+ end
29
+ else
30
+ end
31
+ end
data/init.rb ADDED
@@ -0,0 +1,4 @@
1
+ # Include hook code here
2
+
3
+ require 'amount_field'
4
+
@@ -0,0 +1 @@
1
+ # Install hook code here
@@ -0,0 +1,22 @@
1
+ # AmountField
2
+
3
+ require 'amount_field/validations'
4
+ require 'amount_field/form_helper'
5
+ require 'amount_field/form_tag_helper'
6
+
7
+ ActiveRecord::Base.class_eval do
8
+ include AmountField::ActiveRecord::Validations
9
+ end
10
+
11
+ ActionView::Helpers::FormBuilder.class_eval do
12
+ include AmountField::Helpers::FormBuilder
13
+ end
14
+
15
+ ActionView::Base.class_eval do
16
+ include AmountField::Helpers::FormHelper
17
+ include AmountField::Helpers::FormTagHelper
18
+ end
19
+
20
+ I18n.load_path << "#{File.dirname(__FILE__)}/../locale/en.yml"
21
+ I18n.load_path << "#{File.dirname(__FILE__)}/../locale/de.yml"
22
+
@@ -0,0 +1,20 @@
1
+ module AmountField
2
+ class Configuration
3
+
4
+ ##
5
+ # Defines the prefix for the special setter method name:
6
+ # def #{prefix}_xxx=(value) ...
7
+ # end
8
+ #
9
+ @@prefix = 'amount_field'
10
+ mattr_accessor :prefix
11
+
12
+ ##
13
+ # Defines the CSS class name for the <tt>amount_field</tt> helper.
14
+ # <input ...class="... #{css_class}" .../>
15
+ #
16
+ @@css_class = 'amount_field'
17
+ mattr_accessor :css_class
18
+
19
+ end
20
+ end
@@ -0,0 +1,62 @@
1
+ module AmountField #:nodoc:
2
+ module Helpers #:nodoc:
3
+
4
+ module FormHelper #:nodoc:
5
+
6
+ include ActionView::Helpers::NumberHelper
7
+
8
+ def amount_field(object_name, method, options = {})
9
+ format_options = I18n.t(:'number.amount_field.format', :raise => true) rescue {}
10
+ format_options = format_options.merge(AmountField::ActiveRecord::Validations.configuration)
11
+ format_options.merge!(options.delete(:format) || {})
12
+
13
+ object = options.delete(:object) || instance_variable_get("@#{object_name}")
14
+
15
+ # if no explicit value is given, we set a formatted one. In case of an error we take the
16
+ # original value inserted by the user.
17
+ unless object.errors.on(method)
18
+ options[:value] ||= number_with_precision(object.send(method), format_options)
19
+ else
20
+ options[:value] ||= object.send("#{method}_before_type_cast")
21
+ end
22
+ options[:name] = "#{object_name}[#{AmountField::Configuration.prefix}_#{method}]"
23
+ options[:class] = "#{options[:class]} #{AmountField::Configuration.css_class}"
24
+ options[:id] ||= "#{object_name}_#{method}"
25
+
26
+ text_field(object_name, method, options)
27
+ end
28
+
29
+ end
30
+
31
+ module FormBuilder #:nodoc:
32
+
33
+ include ActionView::Helpers::NumberHelper
34
+
35
+ def amount_field(method, options = {})
36
+ #todo try to remove redundant code by using: @template.amount_field(object, method, options)
37
+ format_options = I18n.t(:'number.amount_field.format', :raise => true) rescue {}
38
+ format_options = format_options.merge(AmountField::ActiveRecord::Validations.configuration)
39
+ format_options.merge!(options.delete(:format) || {})
40
+
41
+ if (explicit_object = options.delete(:object))
42
+ self.object = explicit_object
43
+ end
44
+
45
+ # if no explicit value is given, we set a formatted one. In case of an error we take the
46
+ # original value inserted by the user.
47
+ unless object.errors.on(method)
48
+ options[:value] ||= number_with_precision(object.send(method), format_options)
49
+ else
50
+ options[:value] ||= object.send("#{method}_before_type_cast")
51
+ end
52
+ options[:name] = "#{object_name}[#{AmountField::Configuration.prefix}_#{method}]"
53
+ options[:class] = "#{options[:class]} #{AmountField::Configuration.css_class}"
54
+
55
+ text_field(method, options)
56
+ end
57
+
58
+ end
59
+
60
+ end
61
+ end
62
+
@@ -0,0 +1,22 @@
1
+ module AmountField #:nodoc:
2
+ module Helpers #:nodoc:
3
+ module FormTagHelper
4
+ include ActionView::Helpers::NumberHelper
5
+
6
+ def amount_field_tag(name, value = nil, options = {})
7
+ format_options = I18n.t(:'number.amount_field.format', :raise => true) rescue {}
8
+ format_options = format_options.merge(AmountField::ActiveRecord::Validations.configuration)
9
+ format_options.merge!(options.delete(:format) || {})
10
+
11
+ # if no explicit value is given, we set a formatted one. In case of an error we take the
12
+ # original value inserted by the user.
13
+ options[:value] ||= number_with_precision(value.to_s, format_options)
14
+ options[:name] = "#{AmountField::Configuration.prefix}_#{name}"
15
+ options[:class] = "#{options[:class]} #{AmountField::Configuration.css_class}"
16
+
17
+ text_field_tag(name, value, options)
18
+ end
19
+
20
+ end
21
+ end
22
+ end