delocalize 0.4.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,15 @@
1
+ # TODO Rethink: Shouldn't this return numbers instead of reformatted strings?
2
+ module Delocalize
3
+ module Parsers
4
+ class Number
5
+ # Parse numbers removing unneeded characters and replacing decimal separator
6
+ # through I18n. This will return a valid Ruby Numeric value (as String).
7
+ def parse(value)
8
+ return value unless value.is_a?(String)
9
+
10
+ separator, delimiter = I18n.t([:separator, :delimiter], :scope => :'number.format')
11
+ value.gsub(delimiter, '').gsub(separator, '.')
12
+ end
13
+ end
14
+ end
15
+ end
@@ -1,15 +1,15 @@
1
1
  module Delocalize
2
2
  class Railtie < Rails::Railtie
3
3
  initializer "delocalize" do |app|
4
- ActiveSupport.on_load :active_record do
5
- require 'delocalize/rails_ext/active_record'
4
+ ActiveSupport.on_load :action_controller do
5
+ # By default, we use ActionController::Parameters provided by strong_parameters. If it's
6
+ # not there, we fall back to our own replacement (Delocalize::Parameters).
7
+ if defined?(ActionController::Parameters)
8
+ ActionController::Parameters.send(:include, Delocalize::ParameterDelocalizing)
9
+ else
10
+ ActionController::Base.send(:include, Delocalize::DelocalizableParameters)
11
+ end
6
12
  end
7
-
8
- ActiveSupport.on_load :action_view do
9
- require 'delocalize/rails_ext/action_view'
10
- end
11
-
12
- require 'delocalize/rails_ext/time_zone'
13
13
  end
14
14
  end
15
15
  end
@@ -0,0 +1,3 @@
1
+ module Delocalize
2
+ VERSION = "1.0.0"
3
+ end
@@ -0,0 +1,56 @@
1
+ # encoding: utf-8
2
+
3
+ require 'test_helper'
4
+ require 'active_support/time'
5
+
6
+ describe Delocalize::Parsers::DateTime do
7
+ before do
8
+ Time.zone = 'Berlin' # make sure everything works as expected with TimeWithZone
9
+ @time_parser = Delocalize::Parsers::DateTime.new(Time)
10
+ @date_parser = Delocalize::Parsers::DateTime.new(Date)
11
+ end
12
+
13
+ after do
14
+ Timecop.return
15
+ end
16
+
17
+ # date
18
+ it "parses a date from a string" do
19
+ date = Date.civil(2009, 10, 19)
20
+ @date_parser.parse('19. Oktober 2009').must_equal date
21
+ @date_parser.parse('19.10.2009').must_equal date
22
+ end
23
+
24
+ it "parses a date without a year from a string, defaulting to the current year" do
25
+ date = Date.civil(Date.today.year, 10, 19)
26
+ @date_parser.parse('19. Okt.').must_equal date
27
+ @date_parser.parse('19.10.').must_equal date
28
+ end
29
+
30
+ # datetime
31
+ it "parses a datetime from a string" do
32
+ time = Time.zone.local(2009, 3, 1, 12, 0, 0)
33
+ @time_parser.parse('Sonntag, 1. März 2009, 12:00 Uhr').must_equal time
34
+ @time_parser.parse('1. März 2009, 12:00 Uhr').must_equal time
35
+ end
36
+
37
+ it "parses a datetime without a year from a string, defaulting to the current year" do
38
+ time = Time.zone.local(Time.now.year, 3, 1, 12, 0, 0)
39
+ @time_parser.parse('1. März, 12:00 Uhr').must_equal time
40
+ end
41
+
42
+ # time
43
+ it "parses a time from a string, defaulting to the current day" do
44
+ Timecop.freeze(Time.zone.local(2009, 3, 1, 12, 0, 0)) # prevent DST issues
45
+ time = Time.zone.local(2009, 3, 1, 9, 0, 0, 0)
46
+ @time_parser.parse('9:00 Uhr').must_equal time
47
+ end
48
+
49
+ it "doesn't parse date/time-like objects" do
50
+ date = Date.civil(2009, 10, 19)
51
+ time = Time.zone.local(2009, 3, 1, 12, 0, 0)
52
+
53
+ @date_parser.parse(date).must_equal date
54
+ @time_parser.parse(time).must_equal time
55
+ end
56
+ end
@@ -0,0 +1,30 @@
1
+ require 'test_helper'
2
+
3
+ describe Delocalize::Parsers::Number do
4
+ before do
5
+ @parser = Delocalize::Parsers::Number.new
6
+ end
7
+
8
+ it "parses a number from a string" do
9
+ @parser.parse('1.299,99').must_equal '1299.99'
10
+ end
11
+
12
+ it "parses a negative number from a string" do
13
+ @parser.parse('-1.299,99').must_equal '-1299.99'
14
+ end
15
+
16
+ it "parses an integer from a string" do
17
+ @parser.parse('1.299').must_equal '1299'
18
+ end
19
+
20
+ it "parses a negative integer from a string" do
21
+ @parser.parse('-1.299').must_equal '-1299'
22
+ end
23
+
24
+ it "doesn't change a number if it's already a numeric type" do
25
+ @parser.parse(1299.99).must_equal 1299.99
26
+ @parser.parse(-1299.99).must_equal -1299.99
27
+ @parser.parse(1299).must_equal 1299
28
+ @parser.parse(-1299).must_equal -1299
29
+ end
30
+ end
@@ -0,0 +1,171 @@
1
+ require 'test_helper'
2
+
3
+ parameters_classes = [Delocalize::Parameters]
4
+
5
+ if defined?(ActionController::Parameters)
6
+ # FIXME Can this happen automatically, e.g. by loading the Railtie?
7
+ ActionController::Parameters.send(:include, Delocalize::ParameterDelocalizing)
8
+ parameters_classes << ActionController::Parameters
9
+ end
10
+
11
+ parameters_classes.each do |parameters_class|
12
+ describe parameters_class do
13
+ before do
14
+ Time.zone = 'Berlin' # make sure everything works as expected with TimeWithZone
15
+ end
16
+
17
+ it "delocalizes top level params based on the given options" do
18
+ params = parameters_class.new(:released_on => '21. Mai 1986', :available_until => '25. Dezember 2013, 23:59 Uhr', :price => '1.299,99')
19
+
20
+ delocalized_params = params.delocalize(:released_on => :date, :available_until => :time, :price => :number)
21
+
22
+ delocalized_params[:released_on].must_equal Date.civil(1986, 5, 21)
23
+ delocalized_params[:available_until].must_equal Time.zone.local(2013, 12, 25, 23, 59)
24
+ delocalized_params[:price].must_equal '1299.99'
25
+ end
26
+
27
+ it "delocalizes nested params based on the given options" do
28
+ params = parameters_class.new(:product => { :released_on => '21. Mai 1986', :available_until => '25. Dezember 2013, 23:59 Uhr', :price => '1.299,99' })
29
+
30
+ delocalized_params = params.delocalize(:product => { :released_on => :date, :available_until => :time, :price => :number })
31
+
32
+ delocalized_params[:product][:released_on].must_equal Date.civil(1986, 5, 21)
33
+ delocalized_params[:product][:available_until].must_equal Time.zone.local(2013, 12, 25, 23, 59)
34
+ delocalized_params[:product][:price].must_equal '1299.99'
35
+ end
36
+
37
+ it "delocalizes field-for type params based on the given options" do
38
+ params = parameters_class.new(
39
+ :product => {
40
+ variant_attributes: {
41
+ "0" => { :released_on => '21. Mai 1986', :available_until => '25. Dezember 2013, 23:59 Uhr', :price => '1.299,99' },
42
+ "1" => { :released_on => '1. Juni 2001', :available_until => '12. November 2014, 00:00 Uhr', :price => '1.099,01' },
43
+ }
44
+ }
45
+ )
46
+
47
+ delocalized_params = params.delocalize(:product => { :variant_attributes => { :released_on => :date, :available_until => :time, :price => :number } })
48
+
49
+ delocalized_params[:product][:variant_attributes]['0'][:released_on].must_equal Date.civil(1986, 5, 21)
50
+ delocalized_params[:product][:variant_attributes]['0'][:available_until].must_equal Time.zone.local(2013, 12, 25, 23, 59)
51
+ delocalized_params[:product][:variant_attributes]['0'][:price].must_equal '1299.99'
52
+
53
+ delocalized_params[:product][:variant_attributes]['1'][:released_on].must_equal Date.civil(2001, 6, 1)
54
+ delocalized_params[:product][:variant_attributes]['1'][:available_until].must_equal Time.zone.local(2014, 11, 12, 00, 00)
55
+ delocalized_params[:product][:variant_attributes]['1'][:price].must_equal '1099.01'
56
+ end
57
+
58
+ it "delocalizes nested params on the key itself based on the given options" do
59
+ params = parameters_class.new(:product => { :released_on => '21. Mai 1986', :available_until => '25. Dezember 2013, 23:59 Uhr', :price => '1.299,99' })
60
+
61
+ product_params = params[:product].delocalize(:released_on => :date, :available_until => :time, :price => :number)
62
+
63
+ product_params[:released_on].must_equal Date.civil(1986, 5, 21)
64
+ product_params[:available_until].must_equal Time.zone.local(2013, 12, 25, 23, 59)
65
+ product_params[:price].must_equal '1299.99'
66
+ end
67
+
68
+ it "delocalizes deeply nested params for one-to-one based on the given options" do
69
+ params = parameters_class.new(:parent => { :child => { :child_date => '21. Mai 1986', :child_time => '25. Dezember 2013, 23:59 Uhr', :child_number => '1.299,99' } })
70
+
71
+ delocalized_params = params.delocalize(:parent => { :child => { :child_date => :date, :child_time => :time, :child_number => :number } })
72
+
73
+ delocalized_params[:parent][:child][:child_date].must_equal Date.civil(1986, 5, 21)
74
+ delocalized_params[:parent][:child][:child_time].must_equal Time.zone.local(2013, 12, 25, 23, 59)
75
+ delocalized_params[:parent][:child][:child_number].must_equal '1299.99'
76
+ end
77
+
78
+ it "delocalizes deeply nested params for one-to-one on the key itself based on the given options" do
79
+ params = parameters_class.new(:parent => { :child => { :child_date => '21. Mai 1986', :child_time => '25. Dezember 2013, 23:59 Uhr', :child_number => '1.299,99' } })
80
+
81
+ parent_params = params[:parent].delocalize(:child => { :child_date => :date, :child_time => :time, :child_number => :number })
82
+
83
+ parent_params[:child][:child_date].must_equal Date.civil(1986, 5, 21)
84
+ parent_params[:child][:child_time].must_equal Time.zone.local(2013, 12, 25, 23, 59)
85
+ parent_params[:child][:child_number].must_equal '1299.99'
86
+ end
87
+
88
+ it "delocalizes all the things at all the levels of all the types" do
89
+ delocalize_options = {
90
+ :top_level_date => :date,
91
+ :top_level_time => :time,
92
+ :top_level_number => :number,
93
+ :parent => {
94
+ :parent_date => :date,
95
+ :parent_time => :time,
96
+ :parent_number => :number,
97
+ :child => {
98
+ :child_date => :date,
99
+ :child_time => :time,
100
+ :child_number => :number
101
+ }
102
+ }
103
+ }
104
+
105
+ params = parameters_class.new(
106
+ :top_level_date => '21. Mai 1986',
107
+ :top_level_time => '25. Dezember 2013, 23:59 Uhr',
108
+ :top_level_number => '1.299,99',
109
+ :parent => {
110
+ :parent_date => '21. Mai 2004',
111
+ :parent_time => '24. Dezember 2013, 23:59 Uhr',
112
+ :parent_number => '999,99',
113
+ :child => {
114
+ :child_date => '21. Mai 2011',
115
+ :child_time => '31. Dezember 2013, 23:59 Uhr',
116
+ :child_number => '9.999'
117
+ }
118
+ }
119
+ )
120
+
121
+ delocalized_params = params.delocalize(delocalize_options)
122
+
123
+ delocalized_params[:top_level_date].must_equal Date.civil(1986, 5, 21)
124
+ delocalized_params[:top_level_time].must_equal Time.zone.local(2013, 12, 25, 23, 59)
125
+ delocalized_params[:top_level_number].must_equal '1299.99'
126
+
127
+ delocalized_params[:parent][:parent_date].must_equal Date.civil(2004, 5, 21)
128
+ delocalized_params[:parent][:parent_time].must_equal Time.zone.local(2013, 12, 24, 23, 59)
129
+ delocalized_params[:parent][:parent_number].must_equal '999.99'
130
+
131
+ delocalized_params[:parent][:child][:child_date].must_equal Date.civil(2011, 5, 21)
132
+ delocalized_params[:parent][:child][:child_time].must_equal Time.zone.local(2013, 12, 31, 23, 59)
133
+ delocalized_params[:parent][:child][:child_number].must_equal '9999'
134
+ end
135
+
136
+ # TODO Figure out deeply nested params for one-to-many relations.
137
+ # The problem is that one-to-many relations may be given as a hash or an array. Delocalize should
138
+ # be able both cases just fine.
139
+
140
+ it "fails for a non-existent type" do
141
+ params = parameters_class.new(:available_until => '25. Dezember 2013, 23:59 Uhr')
142
+
143
+ ->{ params.delocalize(:available_until => :datetime) }.must_raise(Delocalize::ParserNotFound)
144
+ end
145
+
146
+ it "keeps unconfigured parameters as they are while still delocalizing others" do
147
+ params = parameters_class.new(:released_on => '1986-05-21', :price => '1.299,99')
148
+
149
+ delocalized_params = params.delocalize(:price => :number)
150
+
151
+ delocalized_params[:released_on].must_equal '1986-05-21'
152
+ delocalized_params[:price].must_equal '1299.99'
153
+ end
154
+
155
+ it "doesn't raise when nested params given and which aren't defined in options" do
156
+ params = parameters_class.new(:parent => { :parent_date => '21. Mai 2004' })
157
+
158
+ ## Should not throw an error:
159
+ delocalized_params = params.delocalize({})
160
+ end
161
+
162
+ it "delocalizes arrays" do
163
+ params = parameters_class.new(:location => ['13,456', '51,234'], :interval => ['25. Dezember 2013', '31. Januar 2014'])
164
+
165
+ delocalized_params = params.delocalize(:location => [:number], interval: [:date])
166
+
167
+ delocalized_params[:location].must_equal ['13.456', '51.234']
168
+ delocalized_params[:interval].must_equal [Date.civil(2013, 12, 25), Date.civil(2014, 1, 31)]
169
+ end
170
+ end
171
+ end
@@ -5,21 +5,21 @@ require 'bundler'
5
5
 
6
6
  Bundler.require(:default, :development)
7
7
 
8
- require 'rails/all'
9
- require 'rails/test_help'
8
+ require 'minitest/autorun'
9
+ require 'minitest/spec'
10
+ require 'mocha/setup'
10
11
 
11
- require 'delocalize/rails_ext/action_view'
12
- require 'delocalize/rails_ext/active_record'
13
- require 'delocalize/rails_ext/time_zone'
12
+ require 'rails'
14
13
 
15
14
  de = {
16
15
  :date => {
17
16
  :input => {
18
- :formats => [:long, :short, :default]
17
+ :formats => [:long, :short, :short_with_name, :default]
19
18
  },
20
19
  :formats => {
21
20
  :default => "%d.%m.%Y",
22
- :short => "%e. %b",
21
+ :short => "%e.%m.",
22
+ :short_with_name => "%e. %b.",
23
23
  :long => "%e. %B %Y",
24
24
  :only_day => "%e"
25
25
  },
@@ -65,38 +65,4 @@ tt[:date][:formats][:default] = '%d|%m|%Y'
65
65
  I18n.backend.store_translations :de, de
66
66
  I18n.backend.store_translations :tt, tt
67
67
 
68
- I18n.enforce_available_locales = false
69
68
  I18n.locale = :de
70
-
71
- class NonArProduct
72
- attr_accessor :name, :price, :times_sold,
73
- :cant_think_of_a_sensible_time_field,
74
- :released_on, :published_at
75
- end
76
-
77
- class Product < ActiveRecord::Base
78
- end
79
-
80
- class ProductWithValidation < Product
81
- validates_numericality_of :price
82
- validates_presence_of :price
83
- end
84
-
85
- class ProductWithBusinessValidation < Product
86
- validates_numericality_of :price, :less_than => 10
87
- end
88
-
89
- config = YAML.load_file(File.dirname(__FILE__) + '/database.yml')
90
- ActiveRecord::Base.establish_connection(config['test'])
91
-
92
- ActiveRecord::Base.connection.create_table :products do |t|
93
- t.string :name
94
- t.date :released_on
95
- t.datetime :published_at
96
- t.time :cant_think_of_a_sensible_time_field
97
- t.decimal :price
98
- t.float :weight
99
- t.integer :times_sold
100
- t.decimal :some_value_with_default, :default => 0, :precision => 20, :scale => 2
101
- end
102
-
metadata CHANGED
@@ -1,48 +1,57 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: delocalize
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
5
- prerelease:
4
+ version: 1.0.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Clemens Kofler
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2014-08-06 00:00:00.000000000 Z
11
+ date: 2015-11-12 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: rails
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ! '>='
17
+ - - ">="
20
18
  - !ruby/object:Gem::Version
21
- version: '3.0'
19
+ version: '2'
22
20
  type: :runtime
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - ! '>='
24
+ - - ">="
28
25
  - !ruby/object:Gem::Version
29
- version: '3.0'
26
+ version: '2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: mocha
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
30
41
  - !ruby/object:Gem::Dependency
31
42
  name: timecop
32
43
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
44
  requirements:
35
- - - ~>
45
+ - - ">="
36
46
  - !ruby/object:Gem::Version
37
- version: 0.3.5
47
+ version: '0'
38
48
  type: :development
39
49
  prerelease: false
40
50
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
51
  requirements:
43
- - - ~>
52
+ - - ">="
44
53
  - !ruby/object:Gem::Version
45
- version: 0.3.5
54
+ version: '0'
46
55
  description: Delocalize is a tool for parsing localized dates/times and numbers.
47
56
  email: clemens@railway.at
48
57
  executables: []
@@ -50,55 +59,54 @@ extensions: []
50
59
  extra_rdoc_files:
51
60
  - README.markdown
52
61
  files:
53
- - lib/delocalize/i18n_ext.rb
54
- - lib/delocalize/localized_date_time_parser.rb
55
- - lib/delocalize/localized_numeric_parser.rb
56
- - lib/delocalize/rails_ext/action_view.rb
62
+ - MIT-LICENSE
63
+ - README.markdown
64
+ - lib/delocalize.rb
65
+ - lib/delocalize/delocalizable_parameters.rb
66
+ - lib/delocalize/parameter_delocalizing.rb
67
+ - lib/delocalize/parameters.rb
68
+ - lib/delocalize/parsers.rb
69
+ - lib/delocalize/parsers/date_time.rb
70
+ - lib/delocalize/parsers/number.rb
57
71
  - lib/delocalize/rails_ext/action_view_rails3.rb
58
72
  - lib/delocalize/rails_ext/action_view_rails4.rb
59
- - lib/delocalize/rails_ext/active_record.rb
60
73
  - lib/delocalize/rails_ext/active_record_rails3.rb
61
74
  - lib/delocalize/rails_ext/active_record_rails4.rb
62
- - lib/delocalize/rails_ext/time_zone.rb
63
75
  - lib/delocalize/railtie.rb
64
- - lib/delocalize/ruby_ext/date.rb
65
- - lib/delocalize/ruby_ext/datetime.rb
66
- - lib/delocalize/ruby_ext/numeric.rb
67
- - lib/delocalize/ruby_ext/time.rb
68
- - lib/delocalize/ruby_ext.rb
69
- - lib/delocalize.rb
70
- - README.markdown
71
- - MIT-LICENSE
76
+ - lib/delocalize/version.rb
72
77
  - test/database.yml
73
- - test/delocalize_test.rb
78
+ - test/date_time_parser_test.rb
79
+ - test/number_parser_test.rb
80
+ - test/parameters_test.rb
74
81
  - test/test_helper.rb
75
82
  homepage: http://github.com/clemens/delocalize
76
83
  licenses:
77
84
  - MIT
85
+ metadata: {}
78
86
  post_install_message:
79
87
  rdoc_options:
80
- - --charset=UTF-8
88
+ - "--charset=UTF-8"
81
89
  require_paths:
82
90
  - lib
83
91
  required_ruby_version: !ruby/object:Gem::Requirement
84
- none: false
85
92
  requirements:
86
- - - ! '>='
93
+ - - ">="
87
94
  - !ruby/object:Gem::Version
88
95
  version: '0'
89
96
  required_rubygems_version: !ruby/object:Gem::Requirement
90
- none: false
91
97
  requirements:
92
- - - ! '>='
98
+ - - ">="
93
99
  - !ruby/object:Gem::Version
94
100
  version: '0'
95
101
  requirements: []
96
102
  rubyforge_project:
97
- rubygems_version: 1.8.23
103
+ rubygems_version: 2.4.5.1
98
104
  signing_key:
99
- specification_version: 3
105
+ specification_version: 4
100
106
  summary: Localized date/time and number parsing
101
107
  test_files:
102
108
  - test/database.yml
103
- - test/delocalize_test.rb
109
+ - test/date_time_parser_test.rb
110
+ - test/number_parser_test.rb
111
+ - test/parameters_test.rb
104
112
  - test/test_helper.rb