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