i18n_alchemy 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +9 -1
- data/README.md +79 -0
- data/lib/i18n_alchemy.rb +22 -1
- data/lib/i18n_alchemy/association_parser.rb +15 -11
- data/lib/i18n_alchemy/attributes_parsing.rb +50 -0
- data/lib/i18n_alchemy/date_parser.rb +5 -1
- data/lib/i18n_alchemy/proxy.rb +73 -65
- data/lib/i18n_alchemy/version.rb +1 -1
- data/test/action_view_test.rb +1 -1
- data/test/custom_parsers/my_custom_date_parser.rb +14 -0
- data/test/db/test_schema.rb +2 -1
- data/test/i18n_alchemy/date_parser_test.rb +13 -1
- data/test/i18n_alchemy/numeric_parser_test.rb +1 -1
- data/test/i18n_alchemy/proxy/attributes_parsing_test.rb +142 -0
- data/test/i18n_alchemy/proxy/methods_test.rb +52 -0
- data/test/i18n_alchemy/proxy_test.rb +16 -147
- data/test/i18n_alchemy/time_parser_test.rb +2 -2
- data/test/locale/en.yml +1 -0
- data/test/locale/jp.yml +15 -0
- data/test/locale/pt.yml +1 -0
- data/test/models/product.rb +25 -0
- data/test/models/supplier.rb +4 -0
- data/test/models/user.rb +6 -0
- data/test/models_test.rb +7 -0
- data/test/test_helper.rb +26 -5
- metadata +69 -26
data/CHANGELOG.md
CHANGED
@@ -1,4 +1,12 @@
|
|
1
|
-
##
|
1
|
+
## v0.1.0 - 2013-2-27
|
2
|
+
|
3
|
+
* Fix json serialization to delegate to the target object instead of the proxy
|
4
|
+
* Improve localization for non-AR objects
|
5
|
+
* Allow custom parsers to accept a parser module
|
6
|
+
* Add support for localizing methods
|
7
|
+
* Add support for custom parsers ([@caironoleto][https://github.com/caironoleto])
|
8
|
+
|
9
|
+
## v0.0.1 - 2012-5-8
|
2
10
|
|
3
11
|
* Basic localization for numeric, date and time attributes
|
4
12
|
* Accept hash of attributes on localized call
|
data/README.md
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
## I18nAlchemy
|
2
2
|
|
3
|
+
[![Build Status](https://secure.travis-ci.org/carlosantoniodasilva/i18n_alchemy.png)](http://travis-ci.org/carlosantoniodasilva/i18n_alchemy)
|
4
|
+
|
3
5
|
I18n date/number parsing/localization
|
4
6
|
|
5
7
|
I18nAlchemy aims to handle date, time and number parsing, based on current I18n locale format. The main idea is to have ORMs, such as ActiveRecord for now, to automatically accept dates/numbers given in the current locale format, and return these values localized as well.
|
@@ -85,6 +87,83 @@ I18n.with_locale :pt do
|
|
85
87
|
end
|
86
88
|
```
|
87
89
|
|
90
|
+
### Localizing methods
|
91
|
+
|
92
|
+
Given a product model with a `total` method, that is a simple calculation of `quantity * price`, you can tell **I18n::Alchemy** to localize that method for you together with the attributes:
|
93
|
+
|
94
|
+
```ruby
|
95
|
+
class Product < ActiveRecord::Base
|
96
|
+
include I18n::Alchemy
|
97
|
+
localize :total, :using => :number
|
98
|
+
|
99
|
+
def total
|
100
|
+
quantity * price
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
@product = Product.first
|
105
|
+
@product.price = 1.99
|
106
|
+
@product.quantity = 10
|
107
|
+
|
108
|
+
@product.total # => 19.90
|
109
|
+
@localized.total # => "19,90"
|
110
|
+
```
|
111
|
+
|
112
|
+
If the method has a writer method, in this case `total=`, that'd get a parsed version for input values as well.
|
113
|
+
|
114
|
+
With `localize` is possible to localize objects that aren't inheriting from `ActiveRecord::Base`, as long that
|
115
|
+
your class have both reader and writer methods available:
|
116
|
+
|
117
|
+
```ruby
|
118
|
+
class Product
|
119
|
+
include I18n::Alchemy
|
120
|
+
localize :released_at, :using => :date
|
121
|
+
|
122
|
+
attr_accessor :released_at
|
123
|
+
end
|
124
|
+
```
|
125
|
+
|
126
|
+
### Custom Parsers
|
127
|
+
|
128
|
+
If you want to customize the way an attribute is parsed/localized, you can create a custom parser that looks like this:
|
129
|
+
|
130
|
+
```ruby
|
131
|
+
module MyCustomDateParser
|
132
|
+
include I18n::Alchemy::DateParser
|
133
|
+
extend self
|
134
|
+
|
135
|
+
def localize(value)
|
136
|
+
I18n.localize value, :format => :custom
|
137
|
+
end
|
138
|
+
|
139
|
+
protected
|
140
|
+
|
141
|
+
def i18n_format
|
142
|
+
I18n.t(:custom, :scope => [:date, :formats])
|
143
|
+
end
|
144
|
+
end
|
145
|
+
```
|
146
|
+
|
147
|
+
And then just configure the attribute you want to use with this new parser:
|
148
|
+
|
149
|
+
```ruby
|
150
|
+
class Product < ActiveRecord::Base
|
151
|
+
include I18n::Alchemy
|
152
|
+
custom_parsers :released_month => MyCustomDateParser
|
153
|
+
end
|
154
|
+
```
|
155
|
+
|
156
|
+
By doing this, **I18n::Alchemy** will be set up to use your custom parser for that particular attribute, which in this case will make use of the `:custom` date format in your i18n locale.
|
157
|
+
|
158
|
+
If you are using `localize`, you can mix the custom parsers with your existing configuration:
|
159
|
+
|
160
|
+
```ruby
|
161
|
+
class Product < ActiveRecord::Base
|
162
|
+
include I18n::Alchemy
|
163
|
+
localize :total, :using => MyCustomNumberParser
|
164
|
+
end
|
165
|
+
```
|
166
|
+
|
88
167
|
## I18n configuration
|
89
168
|
|
90
169
|
Right now the lib uses the same configuration for numeric, date and time values from Rails:
|
data/lib/i18n_alchemy.rb
CHANGED
@@ -1,17 +1,38 @@
|
|
1
1
|
require "date"
|
2
|
-
require "
|
2
|
+
require "active_support"
|
3
|
+
require "active_support/core_ext/class/attribute"
|
3
4
|
require "i18n"
|
4
5
|
require "i18n_alchemy/date_parser"
|
5
6
|
require "i18n_alchemy/time_parser"
|
6
7
|
require "i18n_alchemy/numeric_parser"
|
7
8
|
require "i18n_alchemy/attribute"
|
8
9
|
require "i18n_alchemy/association_parser"
|
10
|
+
require "i18n_alchemy/attributes_parsing"
|
9
11
|
require "i18n_alchemy/proxy"
|
10
12
|
|
11
13
|
module I18n
|
12
14
|
module Alchemy
|
15
|
+
extend ActiveSupport::Concern
|
16
|
+
|
13
17
|
def localized(attributes=nil, *args)
|
14
18
|
I18n::Alchemy::Proxy.new(self, attributes, *args)
|
15
19
|
end
|
20
|
+
|
21
|
+
included do
|
22
|
+
class_attribute :localized_methods,
|
23
|
+
:instance_reader => false, :instance_writer => false
|
24
|
+
self.localized_methods = {}
|
25
|
+
end
|
26
|
+
|
27
|
+
module ClassMethods
|
28
|
+
def localize(*methods)
|
29
|
+
options = methods.extract_options!
|
30
|
+
parser = options[:using]
|
31
|
+
methods = methods.each_with_object({}) do |method_name, hash|
|
32
|
+
hash[method_name] = parser
|
33
|
+
end
|
34
|
+
self.localized_methods = self.localized_methods.merge(methods)
|
35
|
+
end
|
36
|
+
end
|
16
37
|
end
|
17
38
|
end
|
@@ -4,10 +4,8 @@ module I18n
|
|
4
4
|
attr_reader :target_class, :association_name
|
5
5
|
|
6
6
|
def initialize(target_class, association_name)
|
7
|
-
@target_class
|
7
|
+
@target_class = target_class
|
8
8
|
@association_name = association_name
|
9
|
-
@association = @target_class.reflect_on_association(@association_name)
|
10
|
-
@proxy = @association.klass.new.localized
|
11
9
|
end
|
12
10
|
|
13
11
|
# Parse nested attributes for one-to-one and collection association
|
@@ -20,15 +18,11 @@ module I18n
|
|
20
18
|
# parse(:posts_attributes => { "81u21udjsndja" => {:title => 'Foo!'}, "akmsams" => {:title => 'Baz!'}})
|
21
19
|
#
|
22
20
|
def parse(attributes)
|
23
|
-
if
|
24
|
-
attributes =
|
25
|
-
|
26
|
-
else
|
27
|
-
attributes
|
28
|
-
end
|
29
|
-
attributes.collect { |value_attributes| @proxy.send(:parse_attributes, value_attributes) }
|
21
|
+
if association.macro == :has_many
|
22
|
+
attributes = attributes.is_a?(Hash) ? attributes.values : attributes
|
23
|
+
attributes.map { |value_attributes| proxy.send(:parse_attributes, value_attributes) }
|
30
24
|
else
|
31
|
-
|
25
|
+
proxy.send(:parse_attributes, attributes)
|
32
26
|
end
|
33
27
|
end
|
34
28
|
|
@@ -44,6 +38,16 @@ module I18n
|
|
44
38
|
def association_name_attributes
|
45
39
|
"#{association_name}_attributes"
|
46
40
|
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def association
|
45
|
+
@association ||= @target_class.reflect_on_association(@association_name)
|
46
|
+
end
|
47
|
+
|
48
|
+
def proxy
|
49
|
+
@proxy ||= @association.klass.new.localized
|
50
|
+
end
|
47
51
|
end
|
48
52
|
end
|
49
53
|
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module I18n
|
2
|
+
module Alchemy
|
3
|
+
module AttributesParsing
|
4
|
+
def attributes=(attributes)
|
5
|
+
@target.attributes = parse_attributes(attributes)
|
6
|
+
end
|
7
|
+
|
8
|
+
# This method is added to the proxy even thought it does not exist in
|
9
|
+
# Rails 3.0 (only >= 3.1).
|
10
|
+
def assign_attributes(attributes, *args)
|
11
|
+
if @target.respond_to?(:assign_attributes)
|
12
|
+
@target.assign_attributes(parse_attributes(attributes), *args)
|
13
|
+
else
|
14
|
+
self.attributes = attributes
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def update_attributes(attributes, *args)
|
19
|
+
@target.update_attributes(parse_attributes(attributes), *args)
|
20
|
+
end
|
21
|
+
|
22
|
+
def update_attributes!(attributes, *args)
|
23
|
+
@target.update_attributes!(parse_attributes(attributes), *args)
|
24
|
+
end
|
25
|
+
|
26
|
+
def update_attribute(attribute, value)
|
27
|
+
attributes = parse_attributes(attribute => value)
|
28
|
+
@target.update_attribute(attribute, attributes.values.first)
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def parse_attributes(attributes)
|
34
|
+
attributes = attributes.stringify_keys
|
35
|
+
|
36
|
+
@localized_attributes.each do |column_name, attribute|
|
37
|
+
next unless attributes.key?(column_name)
|
38
|
+
attributes[column_name] = attribute.parse(attributes[column_name])
|
39
|
+
end
|
40
|
+
@localized_associations.each do |association_parser|
|
41
|
+
association_name = association_parser.association_name_attributes
|
42
|
+
next unless attributes.key?(association_name)
|
43
|
+
attributes[association_name] = association_parser.parse(attributes[association_name])
|
44
|
+
end
|
45
|
+
|
46
|
+
attributes
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -20,7 +20,11 @@ module I18n
|
|
20
20
|
protected
|
21
21
|
|
22
22
|
def build_object(parsed_date)
|
23
|
-
Date.new(*parsed_date
|
23
|
+
Date.new(*extract_date(parsed_date))
|
24
|
+
end
|
25
|
+
|
26
|
+
def extract_date(parsed_date)
|
27
|
+
parsed_date.values_at(:year, :mon, :mday).compact
|
24
28
|
end
|
25
29
|
|
26
30
|
def i18n_format
|
data/lib/i18n_alchemy/proxy.rb
CHANGED
@@ -2,62 +2,37 @@ module I18n
|
|
2
2
|
module Alchemy
|
3
3
|
# Depend on AS::BasicObject which has a "blank slate" - no methods.
|
4
4
|
class Proxy < ActiveSupport::BasicObject
|
5
|
+
include AttributesParsing
|
6
|
+
|
5
7
|
# TODO: cannot assume _id is always a foreign key.
|
6
8
|
# Find a better way to find that and skip these columns.
|
7
9
|
def initialize(target, attributes=nil, *args)
|
8
10
|
@target = target
|
9
|
-
@localized_attributes = {}
|
10
|
-
|
11
|
-
@target.class.columns.each do |column|
|
12
|
-
next if column.primary || column.name.ends_with?("_id")
|
13
11
|
|
14
|
-
|
15
|
-
|
16
|
-
create_localized_attribute(column.name, parser)
|
17
|
-
define_localized_methods(column.name)
|
18
|
-
end
|
19
|
-
end
|
12
|
+
@localized_attributes = {}
|
13
|
+
@localized_associations = []
|
20
14
|
|
21
|
-
|
22
|
-
|
15
|
+
build_methods
|
16
|
+
if active_record_compatible?
|
17
|
+
build_attributes
|
18
|
+
build_associations
|
23
19
|
end
|
24
20
|
|
25
21
|
assign_attributes(attributes, *args) if attributes
|
26
22
|
end
|
27
23
|
|
28
|
-
def attributes=(attributes)
|
29
|
-
@target.attributes = parse_attributes(attributes)
|
30
|
-
end
|
31
|
-
|
32
|
-
# This method is added to the proxy even thought it does not exist in
|
33
|
-
# Rails 3.0 (only >= 3.1).
|
34
|
-
def assign_attributes(attributes, *args)
|
35
|
-
if @target.respond_to?(:assign_attributes)
|
36
|
-
@target.assign_attributes(parse_attributes(attributes), *args)
|
37
|
-
else
|
38
|
-
self.attributes = attributes
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
def update_attributes(attributes, *args)
|
43
|
-
@target.update_attributes(parse_attributes(attributes), *args)
|
44
|
-
end
|
45
|
-
|
46
|
-
def update_attributes!(attributes, *args)
|
47
|
-
@target.update_attributes!(parse_attributes(attributes), *args)
|
48
|
-
end
|
49
|
-
|
50
|
-
def update_attribute(attribute, value)
|
51
|
-
attributes = parse_attributes(attribute => value)
|
52
|
-
@target.update_attribute(attribute, attributes.values.first)
|
53
|
-
end
|
54
|
-
|
55
24
|
# Override to_param to always return the +proxy.to_param+. This allow us
|
56
25
|
# to integrate with action view.
|
57
26
|
def to_param
|
58
27
|
@target.to_param
|
59
28
|
end
|
60
29
|
|
30
|
+
# Override to_json to always call +to_json+ on the target object, instead of
|
31
|
+
# serializing the proxy object, that may issue circular references on Ruby 1.8.
|
32
|
+
def to_json(options = nil)
|
33
|
+
@target.to_json(options)
|
34
|
+
end
|
35
|
+
|
61
36
|
# Override to_model to always return the proxy, otherwise it returns the
|
62
37
|
# target object. This allows us to integrate with action view.
|
63
38
|
def to_model
|
@@ -83,54 +58,87 @@ module I18n
|
|
83
58
|
|
84
59
|
private
|
85
60
|
|
61
|
+
def active_record_compatible?
|
62
|
+
target_class = @target.class
|
63
|
+
target_class.respond_to?(:columns) && target_class.respond_to?(:nested_attributes_options)
|
64
|
+
end
|
65
|
+
|
66
|
+
def build_attributes
|
67
|
+
@target.class.columns.each do |column|
|
68
|
+
column_name = column.name
|
69
|
+
next if column.primary || column_name.ends_with?("_id") || @localized_attributes.key?(column_name)
|
70
|
+
|
71
|
+
parser = detect_parser_from_column(column)
|
72
|
+
build_attribute(column_name, parser)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def build_methods
|
77
|
+
@target.class.localized_methods.each_pair do |method, parser_type|
|
78
|
+
method = method.to_s
|
79
|
+
parser = detect_parser(parser_type)
|
80
|
+
build_attribute(method, parser)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def build_associations
|
85
|
+
@target.class.nested_attributes_options.each_key do |association_name|
|
86
|
+
create_localized_association(association_name)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def build_attribute(name, parser)
|
91
|
+
return unless parser
|
92
|
+
create_localized_attribute(name, parser)
|
93
|
+
define_localized_methods(name)
|
94
|
+
end
|
95
|
+
|
96
|
+
def create_localized_association(association_name)
|
97
|
+
@localized_associations <<
|
98
|
+
AssociationParser.new(@target.class, association_name)
|
99
|
+
end
|
100
|
+
|
86
101
|
def create_localized_attribute(column_name, parser)
|
87
102
|
@localized_attributes[column_name] =
|
88
|
-
|
103
|
+
Attribute.new(@target, column_name, parser)
|
89
104
|
end
|
90
105
|
|
91
106
|
def define_localized_methods(column_name)
|
107
|
+
target = @target
|
92
108
|
class << self; self; end.instance_eval do
|
93
109
|
define_method(column_name) do
|
94
110
|
@localized_attributes[column_name].read
|
95
111
|
end
|
96
112
|
|
97
113
|
# Before type cast must be localized to integrate with action view.
|
98
|
-
|
114
|
+
method_name = "#{column_name}_before_type_cast"
|
115
|
+
define_method(method_name) do
|
99
116
|
@localized_attributes[column_name].read
|
100
|
-
end
|
117
|
+
end if target.respond_to?(method_name)
|
101
118
|
|
102
|
-
|
119
|
+
method_name = "#{column_name}="
|
120
|
+
define_method(method_name) do |value|
|
103
121
|
@localized_attributes[column_name].write(value)
|
104
|
-
end
|
122
|
+
end if target.respond_to?(method_name)
|
105
123
|
end
|
106
124
|
end
|
107
125
|
|
108
|
-
def
|
109
|
-
|
110
|
-
|
126
|
+
def detect_parser_from_column(column)
|
127
|
+
detect_parser(column.number? ? :number : column.type)
|
128
|
+
end
|
129
|
+
|
130
|
+
def detect_parser(type_or_parser)
|
131
|
+
case type_or_parser
|
132
|
+
when :number
|
111
133
|
NumericParser
|
112
|
-
when
|
134
|
+
when :date
|
113
135
|
DateParser
|
114
|
-
when
|
136
|
+
when :datetime, :timestamp
|
115
137
|
TimeParser
|
138
|
+
when ::Module
|
139
|
+
type_or_parser
|
116
140
|
end
|
117
141
|
end
|
118
|
-
|
119
|
-
def parse_attributes(attributes)
|
120
|
-
attributes = attributes.stringify_keys
|
121
|
-
|
122
|
-
@localized_attributes.each do |column_name, attribute|
|
123
|
-
next unless attributes.key?(column_name)
|
124
|
-
attributes[column_name] = attribute.parse(attributes[column_name])
|
125
|
-
end
|
126
|
-
@localized_associations.each do |association_parser|
|
127
|
-
association_attributes = association_parser.association_name_attributes
|
128
|
-
next unless attributes.key?(association_attributes)
|
129
|
-
attributes[association_attributes] = association_parser.parse(attributes[association_attributes])
|
130
|
-
end
|
131
|
-
|
132
|
-
attributes
|
133
|
-
end
|
134
142
|
end
|
135
143
|
end
|
136
144
|
end
|
data/lib/i18n_alchemy/version.rb
CHANGED
data/test/action_view_test.rb
CHANGED
data/test/db/test_schema.rb
CHANGED
@@ -11,6 +11,7 @@ ActiveRecord::Schema.define do
|
|
11
11
|
t.decimal :price
|
12
12
|
t.integer :quantity
|
13
13
|
t.date :released_at
|
14
|
+
t.date :released_month
|
14
15
|
t.datetime :updated_at
|
15
16
|
t.timestamp :last_sale_at
|
16
17
|
t.references :supplier
|
@@ -19,7 +20,7 @@ ActiveRecord::Schema.define do
|
|
19
20
|
|
20
21
|
create_table :suppliers do |t|
|
21
22
|
t.string :name
|
22
|
-
t.
|
23
|
+
t.timestamp :created_at
|
23
24
|
end
|
24
25
|
|
25
26
|
create_table :accounts do |t|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require "test_helper"
|
2
2
|
|
3
|
-
class DateParserTest <
|
3
|
+
class DateParserTest < I18n::Alchemy::TestCase
|
4
4
|
def setup
|
5
5
|
@parser = I18n::Alchemy::DateParser
|
6
6
|
@date = Date.new(2011, 12, 31)
|
@@ -20,6 +20,12 @@ class DateParserTest < MiniTest::Unit::TestCase
|
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
|
+
def test_parsers_string_dates_with_implicit_day
|
24
|
+
I18n.with_locale :jp do
|
25
|
+
assert_equal "2011-12-01", @parser.parse("12/2011")
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
23
29
|
def test_parsers_returns_the_given_string_when_invalid_date
|
24
30
|
assert_equal "31/12/2011", @parser.parse("31/12/2011")
|
25
31
|
end
|
@@ -37,4 +43,10 @@ class DateParserTest < MiniTest::Unit::TestCase
|
|
37
43
|
assert_equal "31/12/2011", @parser.localize(@date)
|
38
44
|
end
|
39
45
|
end
|
46
|
+
|
47
|
+
def test_localizes_date_values_with_implicit_day
|
48
|
+
I18n.with_locale :jp do
|
49
|
+
assert_equal "12/2011", @parser.localize(@date)
|
50
|
+
end
|
51
|
+
end
|
40
52
|
end
|
@@ -0,0 +1,142 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class ProxyAttributesParsingTest < I18n::Alchemy::ProxyTestCase
|
4
|
+
# Attributes
|
5
|
+
def test_initializes_proxy_with_attributes
|
6
|
+
@localized = @product.localized(
|
7
|
+
:name => "Banana", :price => "0,99", :released_at => "28/02/2011")
|
8
|
+
|
9
|
+
assert_equal 0.99, @product.price
|
10
|
+
assert_equal "0,99", @localized.price
|
11
|
+
|
12
|
+
assert_equal Date.new(2011, 2, 28), @product.released_at
|
13
|
+
assert_equal "28/02/2011", @localized.released_at
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_initializes_proxy_with_attributes_and_skips_mass_assignment_security_protection_when_without_protection_is_used
|
17
|
+
@localized = @product.localized(attributes_hash, :without_protection => true)
|
18
|
+
if support_assign_attributes_without_protection?
|
19
|
+
assert_equal 'My Precious!', @localized.my_precious
|
20
|
+
else
|
21
|
+
assert_nil @localized.my_precious
|
22
|
+
end
|
23
|
+
assert_equal 1, @localized.quantity
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_assign_attributes
|
27
|
+
@localized.assign_attributes(:price => '1,99')
|
28
|
+
assert_equal "1,99", @localized.price
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_mass_assigning_invalid_attribute
|
32
|
+
assert_raises(ActiveRecord::UnknownAttributeError) do
|
33
|
+
@localized.assign_attributes('i_dont_even_exist' => 40)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_new_with_attr_protected_attributes
|
38
|
+
@localized.assign_attributes(attributes_hash)
|
39
|
+
assert_nil @localized.my_precious
|
40
|
+
assert_equal 1, @localized.quantity
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_assign_attributes_skips_mass_assignment_security_protection_when_without_protection_is_used
|
44
|
+
@localized.assign_attributes(attributes_hash, :without_protection => true)
|
45
|
+
if support_assign_attributes_without_protection?
|
46
|
+
assert_equal 'My Precious!', @localized.my_precious
|
47
|
+
else
|
48
|
+
assert_nil @localized.my_precious
|
49
|
+
end
|
50
|
+
assert_equal 1, @localized.quantity
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_assign_attributes_does_not_change_given_attributes_hash
|
54
|
+
assert_attributes_hash_is_not_changed(attributes = attributes_hash) do
|
55
|
+
@localized.assign_attributes(attributes)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_attributes_assignment
|
60
|
+
@localized.attributes = { :price => '1,99' }
|
61
|
+
assert_equal "1,99", @localized.price
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_attributes_assignment_does_not_change_given_attributes_hash
|
65
|
+
assert_attributes_hash_is_not_changed(attributes = attributes_hash) do
|
66
|
+
@localized.attributes = attributes
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_update_attributes
|
71
|
+
@localized.update_attributes(:price => '2,88')
|
72
|
+
assert_equal '2,88', @localized.price
|
73
|
+
assert_equal 2.88, @product.reload.price
|
74
|
+
end
|
75
|
+
|
76
|
+
def test_update_attributes_does_not_change_given_attributes_hash
|
77
|
+
assert_attributes_hash_is_not_changed(attributes = attributes_hash) do
|
78
|
+
@localized.update_attributes(attributes)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def test_update_attributes!
|
83
|
+
@localized.update_attributes!(:price => '2,88')
|
84
|
+
assert_equal '2,88', @localized.price
|
85
|
+
assert_equal 2.88, @product.reload.price
|
86
|
+
end
|
87
|
+
|
88
|
+
def test_update_attributes_bang_does_not_change_given_attributes_hash
|
89
|
+
assert_attributes_hash_is_not_changed(attributes = attributes_hash) do
|
90
|
+
@localized.update_attributes!(attributes)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def test_update_attribute
|
95
|
+
@localized.update_attribute(:price, '2,88')
|
96
|
+
assert_equal '2,88', @localized.price
|
97
|
+
assert_equal 2.88, @product.reload.price
|
98
|
+
end
|
99
|
+
|
100
|
+
# Nested Attributes
|
101
|
+
def test_should_assign_for_nested_attributes_for_collection_association
|
102
|
+
@supplier_localized.assign_attributes(:products_attributes => [{:price => '1,99'}, {:price => '2,93'}])
|
103
|
+
assert_equal 2, @supplier_localized.products.size
|
104
|
+
assert_equal '1,99', @supplier_localized.products.first.localized.price
|
105
|
+
assert_equal '2,93', @supplier_localized.products.last.localized.price
|
106
|
+
end
|
107
|
+
|
108
|
+
def test_should_assign_for_nested_attributes_passing_a_hash_for_collection_with_unique_keys
|
109
|
+
@supplier_localized.assign_attributes(:products_attributes => {"0" => {:price => '2,93', "_destroy"=>"false"}, "1" => {:price => '2,85', "_destroy" => "false"}})
|
110
|
+
prices = @supplier.products.map { |p| p.localized.price }.sort
|
111
|
+
assert_equal ['2,85', '2,93'], prices
|
112
|
+
end
|
113
|
+
|
114
|
+
def test_should_assign_for_nested_attributes_for_one_to_one_association
|
115
|
+
@supplier_localized.assign_attributes(:account_attributes => {:account_number => 10, :total_money => '100,87'})
|
116
|
+
account = @supplier_localized.account
|
117
|
+
assert_equal 10, account.account_number
|
118
|
+
assert_equal '100,87', account.localized.total_money
|
119
|
+
end
|
120
|
+
|
121
|
+
def test_update_attributes_for_nested_attributes
|
122
|
+
@supplier_localized.update_attributes(:account_attributes => {:total_money => '99,87'})
|
123
|
+
assert_equal '99,87', @supplier_localized.account.localized.total_money
|
124
|
+
end
|
125
|
+
|
126
|
+
def test_attributes_assignment_for_nested
|
127
|
+
@supplier_localized.attributes = {:account_attributes => {:total_money => '88,12'}}
|
128
|
+
assert_equal '88,12', @supplier_localized.account.localized.total_money
|
129
|
+
end
|
130
|
+
|
131
|
+
private
|
132
|
+
|
133
|
+
def attributes_hash
|
134
|
+
{ :my_precious => 'My Precious!', :quantity => 1 }
|
135
|
+
end
|
136
|
+
|
137
|
+
def assert_attributes_hash_is_not_changed(attributes)
|
138
|
+
yield
|
139
|
+
assert_equal 1, attributes[:quantity]
|
140
|
+
assert_equal 'My Precious!', attributes[:my_precious]
|
141
|
+
end
|
142
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class ProxyMethodsTest < I18n::Alchemy::ProxyTestCase
|
4
|
+
def test_localizes_numeric_methods
|
5
|
+
@product.price = 1.99
|
6
|
+
@product.quantity = 10
|
7
|
+
|
8
|
+
assert_equal 19.90, @product.total
|
9
|
+
assert_equal "19,90", @localized.total
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_localizes_date_methods
|
13
|
+
@product.released_at = Date.new(2011, 2, 28)
|
14
|
+
assert_equal "05/03/2011", @localized.estimated_delivery_at
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_localizes_time_methods
|
18
|
+
@product.last_sale_at = Time.mktime(2011, 2, 28, 13, 25, 30)
|
19
|
+
assert_equal "05/03/2011 23:59:59", @localized.estimated_last_comission_payment_at
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_create_existent_writer_methods_for_parsing_input
|
23
|
+
@localized.total = "9,99"
|
24
|
+
assert_equal "9.99", @product.total
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_does_not_create_non_existent_writers
|
28
|
+
assert_raises NoMethodError do
|
29
|
+
@localized.estimated_delivery_at = nil
|
30
|
+
end
|
31
|
+
assert_raises NoMethodError do
|
32
|
+
@localized.estimated_last_comission_payment_at = nil
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_does_not_create_before_type_cast_for_methods
|
37
|
+
assert_raises NoMethodError do
|
38
|
+
@localized.total_before_type_cast
|
39
|
+
end
|
40
|
+
assert_raises NoMethodError do
|
41
|
+
@localized.estimated_delivery_at_before_type_cast
|
42
|
+
end
|
43
|
+
assert_raises NoMethodError do
|
44
|
+
@localized.estimated_last_comission_payment_at_before_type_cast
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_localize_non_activerecord_models
|
49
|
+
@user.created_at = Date.new(2012, 2, 28)
|
50
|
+
assert_equal "28/02/2012", @user_localized.created_at
|
51
|
+
end
|
52
|
+
end
|
@@ -1,19 +1,6 @@
|
|
1
1
|
require "test_helper"
|
2
2
|
|
3
|
-
class ProxyTest <
|
4
|
-
def setup
|
5
|
-
@product = Product.new
|
6
|
-
@localized = @product.localized
|
7
|
-
@supplier = Supplier.new
|
8
|
-
@supplier_localized = @supplier.localized
|
9
|
-
|
10
|
-
I18n.locale = :pt
|
11
|
-
end
|
12
|
-
|
13
|
-
def teardown
|
14
|
-
I18n.locale = :en
|
15
|
-
end
|
16
|
-
|
3
|
+
class ProxyTest < I18n::Alchemy::ProxyTestCase
|
17
4
|
def test_delegates_orm_methods_to_target_object
|
18
5
|
assert @product.new_record?
|
19
6
|
assert @localized.save!(:name => "foo", :price => 1.99)
|
@@ -39,6 +26,11 @@ class ProxyTest < MiniTest::Unit::TestCase
|
|
39
26
|
assert_equal 1, @localized.id
|
40
27
|
end
|
41
28
|
|
29
|
+
def test_to_json
|
30
|
+
@supplier.products << @product
|
31
|
+
assert_equal @supplier.to_json, @supplier_localized.to_json
|
32
|
+
end
|
33
|
+
|
42
34
|
def test_to_param
|
43
35
|
assert_equal @product.to_param, @localized.to_param
|
44
36
|
end
|
@@ -161,142 +153,19 @@ class ProxyTest < MiniTest::Unit::TestCase
|
|
161
153
|
assert_equal "28/02/2011 13:25:30", @localized.last_sale_at_before_type_cast
|
162
154
|
end
|
163
155
|
|
164
|
-
#
|
165
|
-
def
|
166
|
-
@localized =
|
167
|
-
|
168
|
-
|
169
|
-
assert_equal 0.99, @product.price
|
170
|
-
assert_equal "0,99", @localized.price
|
171
|
-
|
172
|
-
assert_equal Date.new(2011, 2, 28), @product.released_at
|
173
|
-
assert_equal "28/02/2011", @localized.released_at
|
174
|
-
end
|
175
|
-
|
176
|
-
def test_initializes_proxy_with_attributes_and_skips_mass_assignment_security_protection_when_without_protection_is_used
|
177
|
-
@localized = @product.localized(attributes_hash, :without_protection => true)
|
178
|
-
if support_assign_attributes_without_protection?
|
179
|
-
assert_equal 'My Precious!', @localized.my_precious
|
180
|
-
else
|
181
|
-
assert_nil @localized.my_precious
|
182
|
-
end
|
183
|
-
assert_equal 1, @localized.quantity
|
184
|
-
end
|
185
|
-
|
186
|
-
def test_assign_attributes
|
187
|
-
@localized.assign_attributes(:price => '1,99')
|
188
|
-
assert_equal "1,99", @localized.price
|
189
|
-
end
|
190
|
-
|
191
|
-
def test_mass_assigning_invalid_attribute
|
192
|
-
assert_raises(ActiveRecord::UnknownAttributeError) do
|
193
|
-
@localized.assign_attributes('i_dont_even_exist' => 40)
|
194
|
-
end
|
195
|
-
end
|
196
|
-
|
197
|
-
def test_new_with_attr_protected_attributes
|
198
|
-
@localized.assign_attributes(attributes_hash)
|
199
|
-
assert_nil @localized.my_precious
|
200
|
-
assert_equal 1, @localized.quantity
|
201
|
-
end
|
202
|
-
|
203
|
-
def test_assign_attributes_skips_mass_assignment_security_protection_when_without_protection_is_used
|
204
|
-
@localized.assign_attributes(attributes_hash, :without_protection => true)
|
205
|
-
if support_assign_attributes_without_protection?
|
206
|
-
assert_equal 'My Precious!', @localized.my_precious
|
207
|
-
else
|
208
|
-
assert_nil @localized.my_precious
|
209
|
-
end
|
210
|
-
assert_equal 1, @localized.quantity
|
211
|
-
end
|
212
|
-
|
213
|
-
def test_assign_attributes_does_not_change_given_attributes_hash
|
214
|
-
assert_attributes_hash_is_not_changed(attributes = attributes_hash) do
|
215
|
-
@localized.assign_attributes(attributes)
|
216
|
-
end
|
156
|
+
# Custom parser
|
157
|
+
def test_parses_date_attribute_input_with_custom_parser
|
158
|
+
@localized.released_month = "02/2011"
|
159
|
+
assert_equal Date.new(2011, 2, 1), @product.released_month
|
217
160
|
end
|
218
161
|
|
219
|
-
def
|
220
|
-
@
|
221
|
-
assert_equal "
|
222
|
-
end
|
223
|
-
|
224
|
-
def test_attributes_assignment_does_not_change_given_attributes_hash
|
225
|
-
assert_attributes_hash_is_not_changed(attributes = attributes_hash) do
|
226
|
-
@localized.attributes = attributes
|
227
|
-
end
|
228
|
-
end
|
229
|
-
|
230
|
-
def test_update_attributes
|
231
|
-
@localized.update_attributes(:price => '2,88')
|
232
|
-
assert_equal '2,88', @localized.price
|
233
|
-
assert_equal 2.88, @product.reload.price
|
234
|
-
end
|
235
|
-
|
236
|
-
def test_update_attributes_does_not_change_given_attributes_hash
|
237
|
-
assert_attributes_hash_is_not_changed(attributes = attributes_hash) do
|
238
|
-
@localized.update_attributes(attributes)
|
239
|
-
end
|
240
|
-
end
|
241
|
-
|
242
|
-
def test_update_attributes!
|
243
|
-
@localized.update_attributes!(:price => '2,88')
|
244
|
-
assert_equal '2,88', @localized.price
|
245
|
-
assert_equal 2.88, @product.reload.price
|
246
|
-
end
|
247
|
-
|
248
|
-
def test_update_attributes_bang_does_not_change_given_attributes_hash
|
249
|
-
assert_attributes_hash_is_not_changed(attributes = attributes_hash) do
|
250
|
-
@localized.update_attributes!(attributes)
|
251
|
-
end
|
252
|
-
end
|
253
|
-
|
254
|
-
def test_update_attribute
|
255
|
-
@localized.update_attribute(:price, '2,88')
|
256
|
-
assert_equal '2,88', @localized.price
|
257
|
-
assert_equal 2.88, @product.reload.price
|
258
|
-
end
|
259
|
-
|
260
|
-
# Nested Attributes
|
261
|
-
def test_should_assign_for_nested_attributes_for_collection_association
|
262
|
-
@supplier_localized.assign_attributes(:products_attributes => [{:price => '1,99'}, {:price => '2,93'}])
|
263
|
-
assert_equal 2, @supplier_localized.products.size
|
264
|
-
assert_equal '1,99', @supplier_localized.products.first.localized.price
|
265
|
-
assert_equal '2,93', @supplier_localized.products.last.localized.price
|
266
|
-
end
|
267
|
-
|
268
|
-
def test_should_assign_for_nested_attributes_passing_a_hash_for_collection_with_unique_keys
|
269
|
-
@supplier_localized.assign_attributes(:products_attributes => {"0" => {:price => '2,93', "_destroy"=>"false"}, "1" => {:price => '2,85', "_destroy" => "false"}})
|
270
|
-
prices = @supplier.products.map { |p| p.localized.price }.sort
|
271
|
-
assert_equal ['2,85', '2,93'], prices
|
272
|
-
end
|
273
|
-
|
274
|
-
def test_should_assign_for_nested_attributes_for_one_to_one_association
|
275
|
-
@supplier_localized.assign_attributes(:account_attributes => {:account_number => 10, :total_money => '100,87'})
|
276
|
-
account = @supplier_localized.account
|
277
|
-
assert_equal 10, account.account_number
|
278
|
-
assert_equal '100,87', account.localized.total_money
|
279
|
-
end
|
280
|
-
|
281
|
-
def test_update_attributes_for_nested_attributes
|
282
|
-
@supplier_localized.update_attributes(:account_attributes => {:total_money => '99,87'})
|
283
|
-
assert_equal '99,87', @supplier_localized.account.localized.total_money
|
284
|
-
end
|
285
|
-
|
286
|
-
def test_attributes_assignment_for_nested
|
287
|
-
@supplier_localized.attributes = {:account_attributes => {:total_money => '88,12'}}
|
288
|
-
assert_equal '88,12', @supplier_localized.account.localized.total_money
|
289
|
-
end
|
290
|
-
|
291
|
-
private
|
292
|
-
|
293
|
-
def attributes_hash
|
294
|
-
{ :my_precious => 'My Precious!', :quantity => 1 }
|
162
|
+
def test_localizes_date_attribute_output_with_custom_parser
|
163
|
+
@product.released_month = Date.new(2011, 2, 1)
|
164
|
+
assert_equal "02/2011", @localized.released_month
|
295
165
|
end
|
296
166
|
|
297
|
-
def
|
298
|
-
|
299
|
-
assert_equal
|
300
|
-
assert_equal 'My Precious!', attributes[:my_precious]
|
167
|
+
def test_localizes_date_attribute_before_type_cast_output_with_custom_parser
|
168
|
+
@product.released_month = Date.new(2011, 2, 1)
|
169
|
+
assert_equal "02/2011", @localized.released_month_before_type_cast
|
301
170
|
end
|
302
171
|
end
|
@@ -47,7 +47,7 @@ module BaseTimeParserTest
|
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
50
|
-
class TimeParserTest <
|
50
|
+
class TimeParserTest < I18n::Alchemy::TestCase
|
51
51
|
def setup
|
52
52
|
@parser = I18n::Alchemy::TimeParser
|
53
53
|
@time = Time.mktime(2011, 12, 31, 12, 15, 45)
|
@@ -57,7 +57,7 @@ class TimeParserTest < MiniTest::Unit::TestCase
|
|
57
57
|
end
|
58
58
|
|
59
59
|
|
60
|
-
class DateTimeParserTest <
|
60
|
+
class DateTimeParserTest < I18n::Alchemy::TestCase
|
61
61
|
def setup
|
62
62
|
@parser = I18n::Alchemy::TimeParser
|
63
63
|
@time = DateTime.new(2011, 12, 31, 12, 15, 45)
|
data/test/locale/en.yml
CHANGED
data/test/locale/jp.yml
ADDED
data/test/locale/pt.yml
CHANGED
data/test/models/product.rb
CHANGED
@@ -1,11 +1,36 @@
|
|
1
1
|
class Product < ActiveRecord::Base
|
2
2
|
include I18n::Alchemy
|
3
|
+
localize :total, :using => :number
|
4
|
+
localize :estimated_delivery_at, :using => :date
|
5
|
+
localize :estimated_last_comission_payment_at, :using => :timestamp
|
6
|
+
localize :released_month, :using => MyCustomDateParser
|
3
7
|
|
4
8
|
attr_protected :my_precious
|
5
9
|
|
6
10
|
belongs_to :supplier
|
7
11
|
|
12
|
+
def initialize(*)
|
13
|
+
super
|
14
|
+
@total = nil
|
15
|
+
end
|
16
|
+
|
8
17
|
def method_with_block
|
9
18
|
yield "called!"
|
10
19
|
end
|
20
|
+
|
21
|
+
def estimated_last_comission_payment_at
|
22
|
+
(last_sale_at + 5.days).end_of_day if last_sale_at?
|
23
|
+
end
|
24
|
+
|
25
|
+
def estimated_delivery_at
|
26
|
+
released_at + 5.days if released_at?
|
27
|
+
end
|
28
|
+
|
29
|
+
def total
|
30
|
+
@total || (quantity * price if quantity? && price?)
|
31
|
+
end
|
32
|
+
|
33
|
+
def total=(new_total)
|
34
|
+
@total = new_total
|
35
|
+
end
|
11
36
|
end
|
data/test/models/supplier.rb
CHANGED
data/test/models/user.rb
ADDED
data/test/models_test.rb
ADDED
data/test/test_helper.rb
CHANGED
@@ -7,6 +7,7 @@ MiniTest::Unit.autorun
|
|
7
7
|
|
8
8
|
require "i18n_alchemy"
|
9
9
|
require "action_view"
|
10
|
+
require "active_record"
|
10
11
|
|
11
12
|
# Setup I18n after other requires to make sure our locales will override any
|
12
13
|
# ActiveSupport / ActionView defaults.
|
@@ -15,12 +16,32 @@ I18n.locale = :en
|
|
15
16
|
I18n.load_path << Dir[File.expand_path("../locale/*.yml", __FILE__)]
|
16
17
|
|
17
18
|
require "db/test_schema"
|
19
|
+
Dir["test/custom_parsers/*.rb"].each { |file| require File.expand_path(file) }
|
18
20
|
Dir["test/models/*.rb"].each { |file| require File.expand_path(file) }
|
19
21
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
22
|
+
module I18n::Alchemy
|
23
|
+
class TestCase < MiniTest::Unit::TestCase
|
24
|
+
# AR 3.0 does not have assign_attributes and without_protection option, so we
|
25
|
+
# are going to skip such tests in this version.
|
26
|
+
def support_assign_attributes_without_protection?
|
27
|
+
@support_assign_attributes ||= ActiveRecord::VERSION::STRING >= "3.1.0"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class ProxyTestCase < TestCase
|
32
|
+
def setup
|
33
|
+
@product = Product.new
|
34
|
+
@localized = @product.localized
|
35
|
+
@supplier = Supplier.new
|
36
|
+
@supplier_localized = @supplier.localized
|
37
|
+
@user = User.new
|
38
|
+
@user_localized = @user.localized
|
39
|
+
|
40
|
+
I18n.locale = :pt
|
41
|
+
end
|
42
|
+
|
43
|
+
def teardown
|
44
|
+
I18n.locale = :en
|
45
|
+
end
|
25
46
|
end
|
26
47
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: i18n_alchemy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2013-02-28 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
|
-
name:
|
16
|
-
requirement:
|
15
|
+
name: activesupport
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
@@ -21,21 +21,15 @@ dependencies:
|
|
21
21
|
version: '3.0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements:
|
25
|
-
- !ruby/object:Gem::Dependency
|
26
|
-
name: activesupport
|
27
|
-
requirement: &70234292606460 !ruby/object:Gem::Requirement
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
28
25
|
none: false
|
29
26
|
requirements:
|
30
27
|
- - ~>
|
31
28
|
- !ruby/object:Gem::Version
|
32
29
|
version: '3.0'
|
33
|
-
type: :runtime
|
34
|
-
prerelease: false
|
35
|
-
version_requirements: *70234292606460
|
36
30
|
- !ruby/object:Gem::Dependency
|
37
31
|
name: i18n
|
38
|
-
requirement:
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
39
33
|
none: false
|
40
34
|
requirements:
|
41
35
|
- - ~>
|
@@ -43,21 +37,31 @@ dependencies:
|
|
43
37
|
version: '0.5'
|
44
38
|
type: :runtime
|
45
39
|
prerelease: false
|
46
|
-
version_requirements:
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0.5'
|
47
46
|
- !ruby/object:Gem::Dependency
|
48
|
-
name:
|
49
|
-
requirement:
|
47
|
+
name: actionpack
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
50
49
|
none: false
|
51
50
|
requirements:
|
52
51
|
- - ~>
|
53
52
|
- !ruby/object:Gem::Version
|
54
|
-
version: 0
|
53
|
+
version: '3.0'
|
55
54
|
type: :development
|
56
55
|
prerelease: false
|
57
|
-
version_requirements:
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3.0'
|
58
62
|
- !ruby/object:Gem::Dependency
|
59
|
-
name:
|
60
|
-
requirement:
|
63
|
+
name: activerecord
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
61
65
|
none: false
|
62
66
|
requirements:
|
63
67
|
- - ~>
|
@@ -65,18 +69,44 @@ dependencies:
|
|
65
69
|
version: '3.0'
|
66
70
|
type: :development
|
67
71
|
prerelease: false
|
68
|
-
version_requirements:
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ~>
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '3.0'
|
69
78
|
- !ruby/object:Gem::Dependency
|
70
79
|
name: minitest
|
71
|
-
requirement:
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
72
81
|
none: false
|
73
82
|
requirements:
|
74
83
|
- - ~>
|
75
84
|
- !ruby/object:Gem::Version
|
76
|
-
version:
|
85
|
+
version: 4.3.2
|
77
86
|
type: :development
|
78
87
|
prerelease: false
|
79
|
-
version_requirements:
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ~>
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: 4.3.2
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: rake
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ~>
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: 10.0.2
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ~>
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: 10.0.2
|
80
110
|
description: I18n date/number parsing/localization
|
81
111
|
email:
|
82
112
|
- carlosantoniodasilva@gmail.com
|
@@ -89,6 +119,7 @@ files:
|
|
89
119
|
- README.md
|
90
120
|
- lib/i18n_alchemy/association_parser.rb
|
91
121
|
- lib/i18n_alchemy/attribute.rb
|
122
|
+
- lib/i18n_alchemy/attributes_parsing.rb
|
92
123
|
- lib/i18n_alchemy/date_parser.rb
|
93
124
|
- lib/i18n_alchemy/numeric_parser.rb
|
94
125
|
- lib/i18n_alchemy/proxy.rb
|
@@ -96,16 +127,22 @@ files:
|
|
96
127
|
- lib/i18n_alchemy/version.rb
|
97
128
|
- lib/i18n_alchemy.rb
|
98
129
|
- test/action_view_test.rb
|
130
|
+
- test/custom_parsers/my_custom_date_parser.rb
|
99
131
|
- test/db/test_schema.rb
|
100
132
|
- test/i18n_alchemy/date_parser_test.rb
|
101
133
|
- test/i18n_alchemy/numeric_parser_test.rb
|
134
|
+
- test/i18n_alchemy/proxy/attributes_parsing_test.rb
|
135
|
+
- test/i18n_alchemy/proxy/methods_test.rb
|
102
136
|
- test/i18n_alchemy/proxy_test.rb
|
103
137
|
- test/i18n_alchemy/time_parser_test.rb
|
104
138
|
- test/locale/en.yml
|
139
|
+
- test/locale/jp.yml
|
105
140
|
- test/locale/pt.yml
|
106
141
|
- test/models/account.rb
|
107
142
|
- test/models/product.rb
|
108
143
|
- test/models/supplier.rb
|
144
|
+
- test/models/user.rb
|
145
|
+
- test/models_test.rb
|
109
146
|
- test/test_helper.rb
|
110
147
|
homepage: ''
|
111
148
|
licenses: []
|
@@ -121,7 +158,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
121
158
|
version: '0'
|
122
159
|
segments:
|
123
160
|
- 0
|
124
|
-
hash:
|
161
|
+
hash: 2006072931743591474
|
125
162
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
126
163
|
none: false
|
127
164
|
requirements:
|
@@ -130,23 +167,29 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
130
167
|
version: '0'
|
131
168
|
segments:
|
132
169
|
- 0
|
133
|
-
hash:
|
170
|
+
hash: 2006072931743591474
|
134
171
|
requirements: []
|
135
172
|
rubyforge_project: i18n_alchemy
|
136
|
-
rubygems_version: 1.8.
|
173
|
+
rubygems_version: 1.8.23
|
137
174
|
signing_key:
|
138
175
|
specification_version: 3
|
139
176
|
summary: I18n date/number parsing/localization
|
140
177
|
test_files:
|
141
178
|
- test/action_view_test.rb
|
179
|
+
- test/custom_parsers/my_custom_date_parser.rb
|
142
180
|
- test/db/test_schema.rb
|
143
181
|
- test/i18n_alchemy/date_parser_test.rb
|
144
182
|
- test/i18n_alchemy/numeric_parser_test.rb
|
183
|
+
- test/i18n_alchemy/proxy/attributes_parsing_test.rb
|
184
|
+
- test/i18n_alchemy/proxy/methods_test.rb
|
145
185
|
- test/i18n_alchemy/proxy_test.rb
|
146
186
|
- test/i18n_alchemy/time_parser_test.rb
|
147
187
|
- test/locale/en.yml
|
188
|
+
- test/locale/jp.yml
|
148
189
|
- test/locale/pt.yml
|
149
190
|
- test/models/account.rb
|
150
191
|
- test/models/product.rb
|
151
192
|
- test/models/supplier.rb
|
193
|
+
- test/models/user.rb
|
194
|
+
- test/models_test.rb
|
152
195
|
- test/test_helper.rb
|