delocalize 0.3.1 → 0.3.2
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/README.markdown +147 -126
- data/lib/delocalize/localized_date_time_parser.rb +8 -2
- data/lib/delocalize/rails_ext/action_view.rb +22 -24
- data/lib/delocalize/rails_ext/active_record.rb +2 -2
- data/test/delocalize_test.rb +52 -17
- data/test/test_helper.rb +18 -0
- metadata +23 -20
- data/Rakefile +0 -14
- data/VERSION +0 -1
data/README.markdown
CHANGED
@@ -14,7 +14,9 @@ You can use delocalize as a gem (preferred). Using delocalize as a Rails plugin
|
|
14
14
|
|
15
15
|
To use delocalize, put the following gem requirement in your `Gemfile`:
|
16
16
|
|
17
|
-
|
17
|
+
```ruby
|
18
|
+
gem "delocalize"
|
19
|
+
```
|
18
20
|
|
19
21
|
### Rails 2
|
20
22
|
|
@@ -22,7 +24,9 @@ Note: Support for Rails 2 has been discontinued. This version is only considered
|
|
22
24
|
|
23
25
|
To use delocalize, put the following gem requirement in your `environment.rb`:
|
24
26
|
|
25
|
-
|
27
|
+
```ruby
|
28
|
+
config.gem "delocalize", :source => 'http://gemcutter.org'
|
29
|
+
```
|
26
30
|
|
27
31
|
In Rails 2.3, alternatively, you can use it with Bundler. See http://gembundler.com/rails23.html for instructions.
|
28
32
|
|
@@ -33,44 +37,48 @@ Delocalize, just as the name suggest, does pretty much the opposite of localize.
|
|
33
37
|
|
34
38
|
In the grey past, if you want your users to be able to input localized data, such as dates and numbers, you had to manually override attribute accessors:
|
35
39
|
|
36
|
-
|
37
|
-
|
38
|
-
|
40
|
+
```ruby
|
41
|
+
def price=(price)
|
42
|
+
write_attribute(:price, price.gsub(',', '.'))
|
43
|
+
end
|
44
|
+
```
|
39
45
|
|
40
46
|
delocalize does this under the covers -- all you need is your regular translation data (as YAML or Ruby file) where you need Rails' standard translations:
|
41
47
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
48
|
+
```yml
|
49
|
+
de:
|
50
|
+
number:
|
51
|
+
format:
|
52
|
+
separator: ','
|
53
|
+
delimiter: '.'
|
54
|
+
date:
|
55
|
+
input:
|
56
|
+
formats: [:default, :long, :short] # <- this and ...
|
57
|
+
|
58
|
+
formats:
|
59
|
+
default: "%d.%m.%Y"
|
60
|
+
short: "%e. %b"
|
61
|
+
long: "%e. %B %Y"
|
62
|
+
only_day: "%e"
|
63
|
+
|
64
|
+
day_names: [Sonntag, Montag, Dienstag, Mittwoch, Donnerstag, Freitag, Samstag]
|
65
|
+
abbr_day_names: [So, Mo, Di, Mi, Do, Fr, Sa]
|
66
|
+
month_names: [~, Januar, Februar, März, April, Mai, Juni, Juli, August, September, Oktober, November, Dezember]
|
67
|
+
abbr_month_names: [~, Jan, Feb, Mär, Apr, Mai, Jun, Jul, Aug, Sep, Okt, Nov, Dez]
|
68
|
+
order: [ :day, :month, :year ]
|
69
|
+
|
70
|
+
time:
|
71
|
+
input:
|
72
|
+
formats: [:long, :medium, :short, :default, :time] # <- ... this are the only non-standard keys
|
73
|
+
formats:
|
74
|
+
default: "%A, %e. %B %Y, %H:%M Uhr"
|
75
|
+
short: "%e. %B, %H:%M Uhr"
|
76
|
+
long: "%A, %e. %B %Y, %H:%M Uhr"
|
77
|
+
time: "%H:%M"
|
78
|
+
|
79
|
+
am: "vormittags"
|
80
|
+
pm: "nachmittags"
|
81
|
+
```
|
74
82
|
|
75
83
|
For dates and times, you have to define input formats which are taken from the actual formats. The important thing here is to define input formats sorted by descending complexity; in other words: the format which contains the most (preferably non-numeric) information should be first in the list because it can produce the most reliable match. Exception: If you think there most complex format is not the one that most users will input, you can put the most-used in front so you save unnecessary iterations.
|
76
84
|
|
@@ -78,12 +86,14 @@ Careful with formats containing only numbers: It's very hard to produce reliable
|
|
78
86
|
|
79
87
|
delocalize then overrides `to_input_field_tag` in ActionView's `InstanceTag` so you can use localized text fields:
|
80
88
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
89
|
+
```erb
|
90
|
+
<% form_for @product do |f| %>
|
91
|
+
<%= f.text_field :name %>
|
92
|
+
<%= f.text_field :released_on %>
|
93
|
+
<%= f.text_field :price %>
|
94
|
+
<% end %>
|
95
|
+
```
|
96
|
+
|
87
97
|
In this example, a user can enter the release date and the price just like he's used to in his language, for example:
|
88
98
|
|
89
99
|
> Name: "Couch"
|
@@ -97,13 +107,22 @@ Edit forms then also show localized dates/numbers. By default, dates and times a
|
|
97
107
|
You can also customize the output using some options:
|
98
108
|
|
99
109
|
The price should always show two decimal digits and we don't need the delimiter:
|
100
|
-
<%= f.text_field :price, :precision => 2, :delimiter => '' %>
|
101
110
|
|
102
|
-
|
103
|
-
|
111
|
+
```erb
|
112
|
+
<%= f.text_field :price, :precision => 2, :delimiter => '' %>
|
113
|
+
```
|
104
114
|
|
115
|
+
The `released_on` date should be shown in the `:full` format:
|
116
|
+
|
117
|
+
```erb
|
118
|
+
<%= f.text_field :released_on, :format => :full %>
|
119
|
+
```
|
120
|
+
|
105
121
|
Since `I18n.localize` supports localizing `strftime` strings, we can also do this:
|
106
|
-
|
122
|
+
|
123
|
+
```erb
|
124
|
+
<%= f.text_field :released_on, :format => "%B %Y" %>
|
125
|
+
```
|
107
126
|
|
108
127
|
### Ruby 1.9 + Psych YAML Parser
|
109
128
|
|
@@ -121,85 +140,87 @@ http://pivotallabs.com/users/mkocher/blog/articles/1692-yaml-psych-and-ruby-1-9-
|
|
121
140
|
|
122
141
|
__Psych Preferred Formatting:__
|
123
142
|
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
143
|
+
```yml
|
144
|
+
en:
|
145
|
+
number:
|
146
|
+
format:
|
147
|
+
separator: '.'
|
148
|
+
delimiter: ','
|
149
|
+
precision: 2
|
150
|
+
date:
|
151
|
+
input:
|
152
|
+
formats:
|
153
|
+
- :default
|
154
|
+
- :long
|
155
|
+
- :short
|
156
|
+
formats:
|
157
|
+
default: "%m/%d/%Y"
|
158
|
+
short: "%b %e"
|
159
|
+
long: "%B %e, %Y"
|
160
|
+
only_day: "%e"
|
161
|
+
day_names:
|
162
|
+
- Sunday
|
163
|
+
- Monday
|
164
|
+
- Tuesday
|
165
|
+
- Wednesday
|
166
|
+
- Thursday
|
167
|
+
- Friday
|
168
|
+
- Saturday
|
169
|
+
abbr_day_names:
|
170
|
+
- Sun
|
171
|
+
- Mon
|
172
|
+
- Tue
|
173
|
+
- Wed
|
174
|
+
- Thur
|
175
|
+
- Fri
|
176
|
+
- Sat
|
177
|
+
month_names:
|
178
|
+
- ~
|
179
|
+
- January
|
180
|
+
- February
|
181
|
+
- March
|
182
|
+
- April
|
183
|
+
- May
|
184
|
+
- June
|
185
|
+
- July
|
186
|
+
- August
|
187
|
+
- September
|
188
|
+
- October
|
189
|
+
- November
|
190
|
+
- December
|
191
|
+
abbr_month_names:
|
192
|
+
- ~
|
193
|
+
- Jan
|
194
|
+
- Feb
|
195
|
+
- Mar
|
196
|
+
- Apr
|
197
|
+
- May
|
198
|
+
- Jun
|
199
|
+
- Jul
|
200
|
+
- Aug
|
201
|
+
- Sep
|
202
|
+
- Oct
|
203
|
+
- Nov
|
204
|
+
- Dec
|
205
|
+
order:
|
206
|
+
- :month
|
207
|
+
- :day
|
208
|
+
- :year
|
209
|
+
time:
|
210
|
+
input:
|
211
|
+
formats:
|
212
|
+
- :default
|
213
|
+
- :long
|
214
|
+
- :short
|
215
|
+
- :time
|
216
|
+
formats:
|
217
|
+
default: "%m/%d/%Y %I:%M%p"
|
218
|
+
short: "%B %e %I:%M %p"
|
219
|
+
long: "%A, %B %e, %Y %I:%M%p"
|
220
|
+
time: "%l:%M%p"
|
221
|
+
am: "am"
|
222
|
+
pm: "pm"
|
223
|
+
```
|
203
224
|
|
204
225
|
### Compatibility
|
205
226
|
|
@@ -53,9 +53,15 @@ module Delocalize
|
|
53
53
|
end
|
54
54
|
|
55
55
|
def translate_month_and_day_names(datetime)
|
56
|
-
|
56
|
+
# Note: This should be a bulk lookup but due to a bug in i18n it doesn't work properly with fallbacks.
|
57
|
+
# See https://github.com/svenfuchs/i18n/issues/104.
|
58
|
+
# TODO Make it a bulk lookup again at some point in the future when the bug is fixed in i18n.
|
59
|
+
translated = [:month_names, :abbr_month_names, :day_names, :abbr_day_names].map do |key|
|
60
|
+
I18n.t(key, :scope => :date)
|
61
|
+
end.flatten.compact
|
62
|
+
|
57
63
|
original = (Date::MONTHNAMES + Date::ABBR_MONTHNAMES + Date::DAYNAMES + Date::ABBR_DAYNAMES).compact
|
58
|
-
translated.each_with_index { |name, i| datetime.gsub!(name
|
64
|
+
translated.each_with_index { |name, i| datetime.gsub!(/\b#{name}\b/, original[i]) }
|
59
65
|
end
|
60
66
|
|
61
67
|
def input_formats(type)
|
@@ -10,30 +10,27 @@ ActionView::Helpers::InstanceTag.class_eval do
|
|
10
10
|
def to_input_field_tag(field_type, options = {})
|
11
11
|
options.symbolize_keys!
|
12
12
|
# numbers and dates/times should be localized unless value is already defined
|
13
|
-
if object && options[:value].blank? && object.respond_to?(:column_for_attribute) && column = object.column_for_attribute(method_name)
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
#
|
30
|
-
|
31
|
-
# we don't format integer hidden fields because this breaks nested_attributes
|
32
|
-
options[:value] = number_with_precision(value, opts) unless hidden_for_integer
|
33
|
-
end
|
34
|
-
elsif column.date? || column.time?
|
35
|
-
options[:value] = value ? I18n.l(value, :format => options.delete(:format)) : nil
|
13
|
+
if object && (options[:value].blank? || !options[:value].is_a?(String)) && object.respond_to?(:column_for_attribute) && column = object.column_for_attribute(method_name)
|
14
|
+
value = options[:value] || object.send(method_name)
|
15
|
+
|
16
|
+
if column.number?
|
17
|
+
number_options = I18n.t(:'number.format')
|
18
|
+
separator = options.delete(:separator) || number_options[:separator]
|
19
|
+
delimiter = options.delete(:delimiter) || number_options[:delimiter]
|
20
|
+
precision = options.delete(:precision) || number_options[:precision]
|
21
|
+
opts = { :separator => separator, :delimiter => delimiter, :precision => precision }
|
22
|
+
# integers don't need a precision
|
23
|
+
opts.merge!(:precision => 0) if column.type == :integer
|
24
|
+
|
25
|
+
hidden_for_integer = field_type == 'hidden' && column.type == :integer
|
26
|
+
|
27
|
+
# the number will be formatted only if it has no numericality errors
|
28
|
+
if object.respond_to?(:errors) && !Array(object.errors[method_name]).try(:include?, 'is not a number')
|
29
|
+
# we don't format integer hidden fields because this breaks nested_attributes
|
30
|
+
options[:value] = number_with_precision(value, opts) unless hidden_for_integer
|
36
31
|
end
|
32
|
+
elsif column.date? || column.time?
|
33
|
+
options[:value] = value ? I18n.l(value, :format => options.delete(:format)) : nil
|
37
34
|
end
|
38
35
|
end
|
39
36
|
|
@@ -44,7 +41,7 @@ end
|
|
44
41
|
# TODO: does it make sense to also override FormTagHelper methods?
|
45
42
|
# ActionView::Helpers::FormTagHelper.class_eval do
|
46
43
|
# include ActionView::Helpers::NumberHelper
|
47
|
-
#
|
44
|
+
#
|
48
45
|
# alias original_text_field_tag text_field_tag
|
49
46
|
# def text_field_tag(name, value = nil, options = {})
|
50
47
|
# value = options.delete(:value) if options.key?(:value)
|
@@ -54,3 +51,4 @@ end
|
|
54
51
|
# original_text_field_tag(name, value, options)
|
55
52
|
# end
|
56
53
|
# end
|
54
|
+
|
@@ -39,7 +39,8 @@ ActiveRecord::Base.class_eval do
|
|
39
39
|
end
|
40
40
|
alias_method_chain :convert_number_column_value, :localization
|
41
41
|
|
42
|
-
|
42
|
+
|
43
|
+
define_method( (Gem::Version.new(ActiveRecord::VERSION::STRING) < Gem::Version.new('3.2.9')) ? :field_changed? : :_field_changed? ) do |attr, old, value|
|
43
44
|
if column = column_for_attribute(attr)
|
44
45
|
if column.number? && column.null && (old.nil? || old == 0) && value.blank?
|
45
46
|
# For nullable numeric columns, NULL gets stored in database for blank (i.e. '') values.
|
@@ -53,7 +54,6 @@ ActiveRecord::Base.class_eval do
|
|
53
54
|
value = column.type_cast(value)
|
54
55
|
end
|
55
56
|
end
|
56
|
-
|
57
57
|
old != value
|
58
58
|
end
|
59
59
|
end
|
data/test/delocalize_test.rb
CHANGED
@@ -11,6 +11,10 @@ class DelocalizeActiveRecordTest < ActiveRecord::TestCase
|
|
11
11
|
@product = Product.new
|
12
12
|
end
|
13
13
|
|
14
|
+
def teardown
|
15
|
+
Timecop.return
|
16
|
+
end
|
17
|
+
|
14
18
|
test "delocalizes localized number" do
|
15
19
|
@product.price = '1.299,99'
|
16
20
|
assert_equal 1299.99, @product.price
|
@@ -43,6 +47,7 @@ class DelocalizeActiveRecordTest < ActiveRecord::TestCase
|
|
43
47
|
end
|
44
48
|
|
45
49
|
test "delocalizes localized date without year" do
|
50
|
+
Timecop.return
|
46
51
|
date = Date.civil(Date.today.year, 10, 19)
|
47
52
|
|
48
53
|
@product.released_on = '19. Okt'
|
@@ -59,6 +64,17 @@ class DelocalizeActiveRecordTest < ActiveRecord::TestCase
|
|
59
64
|
assert_equal time, @product.published_at
|
60
65
|
end
|
61
66
|
|
67
|
+
test "delocalizes with fallback locale" do
|
68
|
+
I18n::Backend::Simple.include(I18n::Backend::Fallbacks)
|
69
|
+
I18n.fallbacks[:xx] = [:xx, :tt]
|
70
|
+
|
71
|
+
I18n.with_locale :xx do
|
72
|
+
@product.released_on = '10|11|2009'
|
73
|
+
date = Date.civil(2009, 11, 10)
|
74
|
+
assert_equal date, @product.released_on
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
62
78
|
test "delocalizes localized datetime without year" do
|
63
79
|
time = Time.zone.local(Date.today.year, 3, 1, 12, 0, 0)
|
64
80
|
|
@@ -66,21 +82,9 @@ class DelocalizeActiveRecordTest < ActiveRecord::TestCase
|
|
66
82
|
assert_equal time, @product.published_at
|
67
83
|
end
|
68
84
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
now = Date.today
|
73
|
-
time = Time.zone.local(now.year, now.month, now.day, 9, 0, 0)
|
74
|
-
@product.cant_think_of_a_sensible_time_field = '09:00 Uhr'
|
75
|
-
assert_equal time, @product.cant_think_of_a_sensible_time_field
|
76
|
-
end
|
77
|
-
else
|
78
|
-
test "delocalizes localized time (non-DST)" do
|
79
|
-
now = Date.today
|
80
|
-
time = Time.zone.local(now.year, now.month, now.day, 8, 0, 0)
|
81
|
-
@product.cant_think_of_a_sensible_time_field = '08:00 Uhr'
|
82
|
-
assert_equal time, @product.cant_think_of_a_sensible_time_field
|
83
|
-
end
|
85
|
+
test "delocalizes localized time (DST)" do
|
86
|
+
@product.cant_think_of_a_sensible_time_field = '09:00 Uhr'
|
87
|
+
assert_equal '09:00', @product.cant_think_of_a_sensible_time_field.strftime('%H:%M')
|
84
88
|
end
|
85
89
|
|
86
90
|
test "invalid dates should be delocalized to nil" do
|
@@ -179,6 +183,23 @@ class DelocalizeActiveRecordTest < ActiveRecord::TestCase
|
|
179
183
|
assert_equal @product.price, 0
|
180
184
|
assert_equal @product.price_before_type_cast, "asd"
|
181
185
|
end
|
186
|
+
|
187
|
+
test 'it should gsub only whole translated words and not mess up the original string' do
|
188
|
+
orig_march = I18n.t('date.month_names')[3]
|
189
|
+
orig_monday = I18n.t('date.abbr_day_names')[1]
|
190
|
+
|
191
|
+
#Simulate Dutch
|
192
|
+
I18n.t('date.month_names')[3] = 'Maart'
|
193
|
+
I18n.t('date.abbr_day_names')[1] = 'Ma'
|
194
|
+
|
195
|
+
subject = '30 Maart 2011'
|
196
|
+
Delocalize::LocalizedDateTimeParser.send(:translate_month_and_day_names, subject)
|
197
|
+
|
198
|
+
assert_equal subject, '30 March 2011'
|
199
|
+
|
200
|
+
I18n.t('date.month_names')[3] = orig_march
|
201
|
+
I18n.t('date.abbr_day_names')[1] = orig_monday
|
202
|
+
end
|
182
203
|
end
|
183
204
|
|
184
205
|
class DelocalizeActionViewTest < ActionView::TestCase
|
@@ -264,19 +285,32 @@ class DelocalizeActionViewTest < ActionView::TestCase
|
|
264
285
|
}
|
265
286
|
end
|
266
287
|
|
267
|
-
test "
|
288
|
+
test "delocalizes a given non-string :value" do
|
289
|
+
@product.price = 1299.9
|
290
|
+
assert_dom_equal '<input id="product_price" name="product[price]" size="30" type="text" value="1.499,90" />',
|
291
|
+
text_field(:product, :price, :value => 1499.90)
|
292
|
+
end
|
293
|
+
|
294
|
+
test "doesn't override given string :value" do
|
268
295
|
@product.price = 1299.9
|
269
296
|
assert_dom_equal '<input id="product_price" name="product[price]" size="30" type="text" value="1.499,90" />',
|
270
297
|
text_field(:product, :price, :value => "1.499,90")
|
271
298
|
end
|
272
299
|
|
273
|
-
test "doesn't convert the value if field has errors" do
|
300
|
+
test "doesn't convert the value if field has numericality errors" do
|
274
301
|
@product = ProductWithValidation.new(:price => 'this is not a number')
|
275
302
|
@product.valid?
|
276
303
|
assert_dom_equal %(<div class="field_with_errors"><input id="product_price" name="product[price]" size="30" type="text" value="this is not a number" /></div>),
|
277
304
|
text_field(:product, :price)
|
278
305
|
end
|
279
306
|
|
307
|
+
test "should convert the value if field have non-numericality errors, but have other errors, e.g. business rules" do
|
308
|
+
@product = ProductWithBusinessValidation.new(:price => '1.337,66')
|
309
|
+
@product.valid?
|
310
|
+
assert_dom_equal %(<div class="field_with_errors"><input id="product_price" name="product[price]" size="30" type="text" value="1.337,66" /></div>),
|
311
|
+
text_field(:product, :price)
|
312
|
+
end
|
313
|
+
|
280
314
|
test "doesn't raise an exception when object isn't an ActiveReccord" do
|
281
315
|
@product = NonArProduct.new
|
282
316
|
assert_nothing_raised {
|
@@ -294,3 +328,4 @@ class DelocalizeActionViewTest < ActionView::TestCase
|
|
294
328
|
text_field(:product, :some_value_with_default)
|
295
329
|
end
|
296
330
|
end
|
331
|
+
|
data/test/test_helper.rb
CHANGED
@@ -5,6 +5,8 @@ require 'bundler'
|
|
5
5
|
|
6
6
|
Bundler.require(:default, :development)
|
7
7
|
|
8
|
+
require 'rails/all'
|
9
|
+
|
8
10
|
require 'test/unit'
|
9
11
|
|
10
12
|
require 'delocalize/rails_ext/action_view'
|
@@ -47,6 +49,13 @@ de = {
|
|
47
49
|
:separator => ',',
|
48
50
|
:delimiter => '.'
|
49
51
|
}
|
52
|
+
},
|
53
|
+
:activerecord => {
|
54
|
+
:errors => {
|
55
|
+
:messages => {
|
56
|
+
:not_a_number => 'is not a number'
|
57
|
+
}
|
58
|
+
}
|
50
59
|
}
|
51
60
|
}
|
52
61
|
|
@@ -73,6 +82,14 @@ class ProductWithValidation < Product
|
|
73
82
|
validates_presence_of :price
|
74
83
|
end
|
75
84
|
|
85
|
+
class ProductWithBusinessValidation < Product
|
86
|
+
validate do |record|
|
87
|
+
if record.price > 10
|
88
|
+
record.errors.add(:price, :invalid)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
76
93
|
config = YAML.load_file(File.dirname(__FILE__) + '/database.yml')
|
77
94
|
ActiveRecord::Base.establish_connection(config['test'])
|
78
95
|
|
@@ -86,3 +103,4 @@ ActiveRecord::Base.connection.create_table :products do |t|
|
|
86
103
|
t.integer :times_sold
|
87
104
|
t.decimal :some_value_with_default, :default => 0, :precision => 20, :scale => 2
|
88
105
|
end
|
106
|
+
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: delocalize
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,33 +9,33 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2013-09-10 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|
16
|
-
requirement:
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
20
20
|
- !ruby/object:Gem::Version
|
21
21
|
version: '3.0'
|
22
|
+
- - <
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: '4'
|
22
25
|
type: :runtime
|
23
26
|
prerelease: false
|
24
|
-
version_requirements:
|
25
|
-
- !ruby/object:Gem::Dependency
|
26
|
-
name: sqlite3
|
27
|
-
requirement: &2160175980 !ruby/object:Gem::Requirement
|
27
|
+
version_requirements: !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
|
-
- -
|
30
|
+
- - ! '>='
|
31
31
|
- !ruby/object:Gem::Version
|
32
|
-
version:
|
33
|
-
|
34
|
-
|
35
|
-
|
32
|
+
version: '3.0'
|
33
|
+
- - <
|
34
|
+
- !ruby/object:Gem::Version
|
35
|
+
version: '4'
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: timecop
|
38
|
-
requirement:
|
38
|
+
requirement: !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ~>
|
@@ -43,7 +43,12 @@ dependencies:
|
|
43
43
|
version: 0.3.5
|
44
44
|
type: :development
|
45
45
|
prerelease: false
|
46
|
-
version_requirements:
|
46
|
+
version_requirements: !ruby/object:Gem::Requirement
|
47
|
+
none: false
|
48
|
+
requirements:
|
49
|
+
- - ~>
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
version: 0.3.5
|
47
52
|
description: Delocalize is a tool for parsing localized dates/times and numbers.
|
48
53
|
email: clemens@railway.at
|
49
54
|
executables: []
|
@@ -51,10 +56,6 @@ extensions: []
|
|
51
56
|
extra_rdoc_files:
|
52
57
|
- README.markdown
|
53
58
|
files:
|
54
|
-
- MIT-LICENSE
|
55
|
-
- Rakefile
|
56
|
-
- VERSION
|
57
|
-
- lib/delocalize.rb
|
58
59
|
- lib/delocalize/i18n_ext.rb
|
59
60
|
- lib/delocalize/localized_date_time_parser.rb
|
60
61
|
- lib/delocalize/localized_numeric_parser.rb
|
@@ -62,12 +63,14 @@ files:
|
|
62
63
|
- lib/delocalize/rails_ext/active_record.rb
|
63
64
|
- lib/delocalize/rails_ext/time_zone.rb
|
64
65
|
- lib/delocalize/railtie.rb
|
65
|
-
- lib/delocalize/ruby_ext.rb
|
66
66
|
- lib/delocalize/ruby_ext/date.rb
|
67
67
|
- lib/delocalize/ruby_ext/datetime.rb
|
68
68
|
- lib/delocalize/ruby_ext/numeric.rb
|
69
69
|
- lib/delocalize/ruby_ext/time.rb
|
70
|
+
- lib/delocalize/ruby_ext.rb
|
71
|
+
- lib/delocalize.rb
|
70
72
|
- README.markdown
|
73
|
+
- MIT-LICENSE
|
71
74
|
- test/database.yml
|
72
75
|
- test/delocalize_test.rb
|
73
76
|
- test/test_helper.rb
|
@@ -92,7 +95,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
92
95
|
version: '0'
|
93
96
|
requirements: []
|
94
97
|
rubyforge_project:
|
95
|
-
rubygems_version: 1.8.
|
98
|
+
rubygems_version: 1.8.23
|
96
99
|
signing_key:
|
97
100
|
specification_version: 3
|
98
101
|
summary: Localized date/time and number parsing
|
data/Rakefile
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
require 'rake'
|
2
|
-
require 'rake/testtask'
|
3
|
-
require 'rdoc/task'
|
4
|
-
|
5
|
-
desc 'Test the delocalize gem.'
|
6
|
-
Rake::TestTask.new(:test) do |t|
|
7
|
-
t.libs << 'lib'
|
8
|
-
t.libs << 'test'
|
9
|
-
t.pattern = 'test/delocalize_test.rb'
|
10
|
-
t.verbose = true
|
11
|
-
end
|
12
|
-
|
13
|
-
desc 'Default: run unit tests.'
|
14
|
-
task :default => :test
|
data/VERSION
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
0.3.1
|