human_attribute_values 1.0.0 → 1.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG.md +25 -0
- data/README.md +35 -7
- data/lib/human_attribute_values.rb +2 -0
- data/lib/human_attribute_values/human_attribute_value.rb +17 -14
- data/lib/human_attribute_values/version.rb +3 -1
- data/test/active_model_test.rb +71 -0
- data/test/{human_attribute_values_test.rb → active_record_test.rb} +22 -14
- data/test/dummy/Rakefile +3 -1
- data/test/dummy/app/assets/config/manifest.js +3 -0
- data/test/dummy/app/controllers/application_controller.rb +2 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/models/active_model_child.rb +4 -0
- data/test/dummy/app/models/active_model_grand_child.rb +4 -0
- data/test/dummy/app/models/active_model_model.rb +7 -0
- data/test/dummy/app/models/active_model_parent.rb +7 -0
- data/test/dummy/app/models/active_model_sibling.rb +4 -0
- data/test/dummy/app/models/boolean_model.rb +2 -0
- data/test/dummy/app/models/child.rb +2 -0
- data/test/dummy/app/models/enum_model.rb +2 -0
- data/test/dummy/app/models/file_model.rb +7 -0
- data/test/dummy/app/models/grand_child.rb +2 -0
- data/test/dummy/app/models/lexicon.rb +3 -1
- data/test/dummy/app/models/numeric_model.rb +2 -0
- data/test/dummy/app/models/parent.rb +2 -0
- data/test/dummy/app/models/sibling.rb +2 -0
- data/test/dummy/app/models/the_answer.rb +3 -0
- data/test/dummy/config.ru +3 -1
- data/test/dummy/config/application.rb +4 -3
- data/test/dummy/config/boot.rb +4 -2
- data/test/dummy/config/environment.rb +3 -1
- data/test/dummy/config/environments/development.rb +2 -0
- data/test/dummy/config/environments/production.rb +2 -0
- data/test/dummy/config/environments/test.rb +4 -2
- data/test/dummy/config/initializers/backtrace_silencers.rb +2 -0
- data/test/dummy/config/initializers/filter_parameter_logging.rb +2 -0
- data/test/dummy/config/initializers/inflections.rb +2 -0
- data/test/dummy/config/initializers/mime_types.rb +2 -0
- data/test/dummy/config/initializers/secret_token.rb +2 -0
- data/test/dummy/config/initializers/session_store.rb +2 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +2 -0
- data/test/dummy/config/locales/en.yml +38 -1
- data/test/dummy/config/routes.rb +2 -0
- data/test/dummy/db/migrate/20150127220502_create_the_answers.rb +5 -1
- data/test/dummy/db/migrate/20150131153819_create_parents.rb +4 -1
- data/test/dummy/db/migrate/20150131161322_create_boolean_models.rb +4 -1
- data/test/dummy/db/migrate/20150131162551_create_numeric_models.rb +4 -1
- data/test/dummy/db/migrate/20150131164609_create_lexicons.rb +4 -3
- data/test/dummy/db/migrate/20150131170613_create_enum_models.rb +4 -1
- data/test/dummy/db/schema.rb +28 -30
- data/test/dummy/db/test.sqlite3 +0 -0
- data/test/dummy/log/test.log +1003 -2618
- data/test/dummy/test/models/boolean_model_test.rb +2 -0
- data/test/dummy/test/models/child_test.rb +2 -0
- data/test/dummy/test/models/enum_model_test.rb +2 -0
- data/test/dummy/test/models/grand_child_test.rb +2 -0
- data/test/dummy/test/models/lexicon_test.rb +2 -0
- data/test/dummy/test/models/numeric_model_test.rb +2 -0
- data/test/dummy/test/models/sibling_test.rb +2 -0
- data/test/dummy/test/models/the_answer_test.rb +2 -0
- data/test/test_helper.rb +6 -4
- metadata +97 -76
- data/Rakefile +0 -32
- data/lib/tasks/human_attribute_value_tasks.rake +0 -4
- data/test/dummy/db/development.sqlite3 +0 -0
- data/test/dummy/log/development.log +0 -310
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 9bf3ef8dbbc1af598f4127f79107630115af5bce63f4ab15b3c071b175a84706
|
4
|
+
data.tar.gz: 138d8b185d3642412d4b7c47310c5ea2dab45cb04d1b167538cbd9b4af1f0616
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 96aa93382dc9817f6c87efffb829c11e5ef84752b2f63ad31c160e3836163a0f64f0f0138ec40882a6b99152d6a22dbac08538978359b6e7d8c4245d82645d4a
|
7
|
+
data.tar.gz: d4c94332f5a6b74ae988874179ba0b5dc02a0b784fac8286e153717977fd059d2b10f5724d301f6b5a0cb537f9b1bd9d0d9f12814979354c09a2b873031f1d53
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# Changelog
|
2
|
+
All notable changes to this project will be documented in this file.
|
3
|
+
|
4
|
+
Please keep to the changelog format described on [keepachangelog.com](http://keepachangelog.com).
|
5
|
+
|
6
|
+
This project adheres to [Semantic Versioning](http://semver.org/).
|
7
|
+
|
8
|
+
## [1.2.1] - 2019-02-08
|
9
|
+
### Added
|
10
|
+
- Support for rails 6 beta
|
11
|
+
|
12
|
+
## [1.2.0] - 2018-10-21
|
13
|
+
### Fixed
|
14
|
+
- Replace dots for all types of values (not only Numeric)
|
15
|
+
### Removed
|
16
|
+
- Drop support for EOL rubies (2.2.10 and below)
|
17
|
+
|
18
|
+
## [1.1.1] - 2018-09-01
|
19
|
+
### Added
|
20
|
+
- Added a changelog.
|
21
|
+
- Also include HumanAttributeValues into ActiveModel::Model.
|
22
|
+
### Changed
|
23
|
+
- Instead of aborting and returning '' for associations of ActiveRecord::Base the lookup now proceeds with `assoc_attribute.to_s` as key (not meant to be done anyways).
|
24
|
+
### Removed
|
25
|
+
- Drop support for rails 4.1.8, including HumanAttributeValues into ActiveModel::Model does not add class method.
|
data/README.md
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
[![Build Status](https://travis-ci.org/RST-J/human_attribute_values.svg?branch=master)](https://travis-ci.org/RST-J/human_attribute_values)
|
3
3
|
[![Gem Version](https://badge.fury.io/rb/human_attribute_values.svg)](http://badge.fury.io/rb/human_attribute_values)
|
4
4
|
|
5
|
-
human_attribute_values is a Rails plugin which provides translation for model attribute values using the Rails I18n API (analogously to [human_attribute_name](
|
5
|
+
human_attribute_values is a Rails plugin which provides translation for model attribute values using the Rails I18n API (analogously to [human_attribute_name](https://apidock.com/rails/v4.2.7/ActiveModel/Translation/human_attribute_name)).
|
6
6
|
|
7
7
|
## Installation
|
8
8
|
```
|
@@ -10,16 +10,22 @@ gem install human_attribute_values
|
|
10
10
|
```
|
11
11
|
|
12
12
|
## Supported versions
|
13
|
-
* Rails: >= 4.
|
14
|
-
* Ruby: MRI >= 2.0
|
13
|
+
* Rails: >= 4.2.10
|
14
|
+
* Ruby: MRI >= 2.3.0
|
15
15
|
|
16
16
|
## Usage
|
17
|
-
The gem defines ``human_attribute_value``
|
18
|
-
To translate a value it uses the I18n API. The translations are looked up from the current locale file under the key ``'activerecord.values.model_name.attribute_name.value'`` by default.
|
17
|
+
The gem defines ``human_attribute_value`` as instance and class method on ``ActiveRecord::Base`` and ``ActiveModel::Model``.
|
18
|
+
To translate a value it uses the I18n API. The translations are looked up from the current locale file under the key ``'activerecord.values.model_name.attribute_name.value'`` respectively ``'activemodel.values.model_name.attribute_name.value'`` by default.
|
19
19
|
|
20
|
-
Locale:
|
20
|
+
### Locale:
|
21
21
|
```yml
|
22
22
|
en:
|
23
|
+
activemodel:
|
24
|
+
values:
|
25
|
+
file_model:
|
26
|
+
content_type:
|
27
|
+
application/pdf: PDF
|
28
|
+
application/vnd_openxmlformats-officedocument_spreadsheetml_sheet: Excel/Calc
|
23
29
|
activerecord:
|
24
30
|
values:
|
25
31
|
schroedinger:
|
@@ -28,8 +34,10 @@ en:
|
|
28
34
|
alive: You opened the box and kitty purrs.
|
29
35
|
```
|
30
36
|
|
31
|
-
Translations:
|
37
|
+
### Translations:
|
32
38
|
```ruby
|
39
|
+
# For ActiveRecord
|
40
|
+
|
33
41
|
class Schroedinger < ActiveRecord::Base
|
34
42
|
enum cat_status: {dead_and_alive: 0, alive: 1, dead: 2}
|
35
43
|
end
|
@@ -46,6 +54,22 @@ Schroedinger.human_attribute_value(:cat_status, :alive)
|
|
46
54
|
Schroedinger.human_attribute_value(:cat_status, :dead)
|
47
55
|
=> "dead"
|
48
56
|
|
57
|
+
# For ActiveModel (the same except the lookup namespace)
|
58
|
+
class FileModel
|
59
|
+
include ActiveModel::Model
|
60
|
+
|
61
|
+
attr_accessor :content_type
|
62
|
+
end
|
63
|
+
|
64
|
+
file = FileModel.new(content_type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
|
65
|
+
file.human_attribute_value(:content_type)
|
66
|
+
=> "Excel/Calc"
|
67
|
+
|
68
|
+
FileModel.human_attribute_value(:content_type, 'application/pdf')
|
69
|
+
=> "PDF"
|
70
|
+
|
71
|
+
FileModel.human_attribute_value(:content_type, 'text/plain')
|
72
|
+
=> "text/plain"
|
49
73
|
```
|
50
74
|
|
51
75
|
### Boolean values
|
@@ -72,5 +96,9 @@ en:
|
|
72
96
|
'42': 'the answer to life, the universe and everything'
|
73
97
|
```
|
74
98
|
|
99
|
+
### Strings and Symbols
|
100
|
+
Starting with version 1.2.0, dots in strings and symbols (actually in all values) are also replaced by an underscore for the lookup (before this was only done for numbers).
|
101
|
+
|
102
|
+
|
75
103
|
### Child classes
|
76
104
|
For models with single table inheritance (STI), the lookup will start with the translations for the class and go up through the class hierarchy and use the translation for the closest parent if there is any.
|
@@ -1,25 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module HumanAttributeValues
|
2
4
|
extend ActiveSupport::Concern
|
3
5
|
|
4
|
-
included {}
|
5
|
-
|
6
6
|
def human_attribute_value(attribute, options = {})
|
7
|
-
value =
|
7
|
+
value = public_send(attribute)
|
8
8
|
self.class.human_attribute_value(attribute, value, options)
|
9
9
|
end
|
10
10
|
|
11
11
|
module ClassMethods
|
12
12
|
def human_attribute_value(attribute, value, options = {})
|
13
|
-
return '' if value.nil?
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
parts = attribute.to_s.split(".")
|
13
|
+
return '' if value.nil? || value == ''
|
14
|
+
|
15
|
+
options = {count: 1}.merge!(options)
|
16
|
+
parts = attribute.to_s.split('.')
|
18
17
|
attribute = parts.pop
|
19
|
-
namespace = parts.join(
|
20
|
-
value_scope = "#{
|
18
|
+
namespace = parts.join('/') unless parts.empty?
|
19
|
+
value_scope = "#{i18n_scope}.values"
|
20
|
+
|
21
21
|
# dots would mean a new nesting level in YAML files
|
22
|
-
key = value.
|
22
|
+
key = value.to_s.tr('.', '_')
|
23
|
+
|
23
24
|
if namespace
|
24
25
|
defaults = lookup_ancestors.map do |klass|
|
25
26
|
:"#{value_scope}.#{klass.model_name.i18n_key}/#{namespace}.#{attribute}.#{key}"
|
@@ -30,14 +31,16 @@ module HumanAttributeValues
|
|
30
31
|
:"#{value_scope}.#{klass.model_name.i18n_key}.#{attribute}.#{key}"
|
31
32
|
end
|
32
33
|
end
|
34
|
+
|
33
35
|
defaults << :"values.#{attribute}.#{key}"
|
34
36
|
defaults << options.delete(:default) if options[:default]
|
35
37
|
defaults << value.to_s
|
38
|
+
|
36
39
|
options[:default] = defaults
|
37
|
-
I18n.
|
40
|
+
I18n.t(defaults.shift, **options)
|
38
41
|
end
|
39
42
|
end
|
40
43
|
end
|
41
44
|
|
42
|
-
|
43
|
-
|
45
|
+
ActiveRecord::Base.include HumanAttributeValues
|
46
|
+
ActiveModel::Model.include HumanAttributeValues
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'test_helper'
|
4
|
+
|
5
|
+
class ActiveModelTest < ActiveSupport::TestCase
|
6
|
+
test 'value with count config' do
|
7
|
+
instance = ActiveModelModel.new
|
8
|
+
instance.string_attr = 'goose'
|
9
|
+
assert_equal('one goose', instance.human_attribute_value(:string_attr), 'should use the mapping for count option 1 by default')
|
10
|
+
assert_equal('one goose', instance.human_attribute_value(:string_attr, count: 1), 'should use the mapping for count option 1 when explicitly specified')
|
11
|
+
assert_equal('some geese', instance.human_attribute_value(:string_attr, count: 2), 'should use the mapping for count other if count is not 1')
|
12
|
+
end
|
13
|
+
|
14
|
+
test 'value without count config' do
|
15
|
+
instance = ActiveModelModel.new
|
16
|
+
instance.integer_attr = 2
|
17
|
+
assert_equal('odd prime', instance.human_attribute_value(:integer_attr), 'should successfully translate without a count option')
|
18
|
+
assert_equal('odd prime', instance.human_attribute_value(:integer_attr, count: 1), 'should successfully translate with count option 1')
|
19
|
+
assert_equal('odd prime', instance.human_attribute_value(:integer_attr, count: 2), 'should successfully translate with count option 2')
|
20
|
+
end
|
21
|
+
|
22
|
+
test 'mime type definition with a dot' do
|
23
|
+
instance = ActiveModelModel.new
|
24
|
+
instance.string_attr = 'application/x-my.mime1'
|
25
|
+
assert_equal('Custom Mime Type 1', instance.human_attribute_value(:string_attr), 'should successfully translate the mime type with dot')
|
26
|
+
|
27
|
+
instance.string_attr = 'application/x-my.untranslated_mime'
|
28
|
+
assert_equal('application/x-my.untranslated_mime', instance.human_attribute_value(:string_attr), 'should return the unmodified value for an untranslated mime type with dot')
|
29
|
+
end
|
30
|
+
|
31
|
+
test 'hierarchy resolution for STI models' do
|
32
|
+
grandchild = ActiveModelGrandChild.new
|
33
|
+
grandchild.inherited_attr = :one
|
34
|
+
assert_equal('active model grandchild value 1', grandchild.human_attribute_value(:inherited_attr), 'should use value for the actual class if present')
|
35
|
+
|
36
|
+
grandchild.inherited_attr = :two
|
37
|
+
assert_equal('active model child value 2', grandchild.human_attribute_value(:inherited_attr), 'should use value for the direct ancestor if it has a mapping')
|
38
|
+
|
39
|
+
grandchild.inherited_attr = :three
|
40
|
+
assert_equal('active model parent value 3', grandchild.human_attribute_value(:inherited_attr), 'should use value for the first parent class which has a mapping for the value')
|
41
|
+
|
42
|
+
grandchild.inherited_attr = :four
|
43
|
+
assert_equal('four', grandchild.human_attribute_value(:inherited_attr), 'should yield the value if there is no mapping in the type hierarchy')
|
44
|
+
end
|
45
|
+
|
46
|
+
test 'resolution of boolean values' do
|
47
|
+
instance = ActiveModelModel.new
|
48
|
+
instance.boolean_attr = false
|
49
|
+
assert_equal('This is false', instance.human_attribute_value(:boolean_attr), 'should translate boolean false')
|
50
|
+
|
51
|
+
instance.boolean_attr = true
|
52
|
+
assert_equal('true', instance.human_attribute_value(:boolean_attr), 'should return the stringified boolean if there is no mapping')
|
53
|
+
end
|
54
|
+
|
55
|
+
test 'resolution for numeric values' do
|
56
|
+
instance = ActiveModelModel.new
|
57
|
+
instance.decimal_attr = '2.71'.to_d
|
58
|
+
instance.float_attr = 3.14
|
59
|
+
instance.integer_attr = 9001
|
60
|
+
assert_equal('e', instance.human_attribute_value(:decimal_attr), 'should translate a decimal')
|
61
|
+
assert_equal('Pi', instance.human_attribute_value(:float_attr), 'should translate a float')
|
62
|
+
assert_equal('over 9000', instance.human_attribute_value(:integer_attr), 'should translate an integer')
|
63
|
+
|
64
|
+
instance.decimal_attr = '9.99'.to_d
|
65
|
+
instance.float_attr = 1.5
|
66
|
+
instance.integer_attr = 1001
|
67
|
+
assert_equal('9.99', instance.human_attribute_value(:decimal_attr), 'should return the stringified decimal if there is no mapping')
|
68
|
+
assert_equal('1.5', instance.human_attribute_value(:float_attr), 'should return the stringified float if there is no mapping')
|
69
|
+
assert_equal('1001', instance.human_attribute_value(:integer_attr), 'should return the stringified integer if there is no mapping')
|
70
|
+
end
|
71
|
+
end
|
@@ -1,25 +1,31 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
test "truth" do
|
5
|
-
assert_kind_of Module, HumanAttributeValues
|
6
|
-
end
|
3
|
+
require 'test_helper'
|
7
4
|
|
8
|
-
|
5
|
+
class ActiveRecordTest < ActiveSupport::TestCase
|
6
|
+
test 'attribute with count config' do
|
9
7
|
answer = TheAnswer.new(ultimate_truth: '42')
|
10
8
|
assert_equal('was calculated by Deep Thought', answer.human_attribute_value(:ultimate_truth), 'should use the mapping for count option 1 by default')
|
11
9
|
assert_equal('was calculated by Deep Thought', answer.human_attribute_value(:ultimate_truth, count: 1), 'should use the mapping for count option 1 when explicitly specified')
|
12
10
|
assert_equal('there is only one ultimate answer', answer.human_attribute_value(:ultimate_truth, count: 2), 'should use the mapping for count other if count is not 1')
|
13
11
|
end
|
14
12
|
|
15
|
-
test
|
13
|
+
test 'attribute without count config' do
|
16
14
|
answer = TheAnswer.new(ultimate_truth: 'wissen ist Nacht')
|
17
15
|
assert_equal('coined by Prof. Dr. Abdul Nachtigaller', answer.human_attribute_value(:ultimate_truth), 'should successfully translate without a count option')
|
18
16
|
assert_equal('coined by Prof. Dr. Abdul Nachtigaller', answer.human_attribute_value(:ultimate_truth, count: 1), 'should successfully translate with count option 1')
|
19
17
|
assert_equal('coined by Prof. Dr. Abdul Nachtigaller', answer.human_attribute_value(:ultimate_truth, count: 2), 'should successfully translate with count option 2')
|
20
18
|
end
|
21
19
|
|
22
|
-
test
|
20
|
+
test 'mime type definition with a dot' do
|
21
|
+
answer = TheAnswer.new(ultimate_truth: 'application/x-my.mime2')
|
22
|
+
assert_equal('Custom Mime Type 2', answer.human_attribute_value(:ultimate_truth), 'should successfully translate the mime type with dot')
|
23
|
+
|
24
|
+
answer.ultimate_truth = 'application/x-my.untranslated_mime'
|
25
|
+
assert_equal('application/x-my.untranslated_mime', answer.human_attribute_value(:ultimate_truth), 'should return the unmodified value for an untranslated mime type with dot')
|
26
|
+
end
|
27
|
+
|
28
|
+
test 'hierarchy resolution for STI models' do
|
23
29
|
grandchild = GrandChild.new(field: '1')
|
24
30
|
assert_equal('grandchild value 1', grandchild.human_attribute_value(:field), 'should use value for the actual class if present')
|
25
31
|
|
@@ -33,7 +39,7 @@ class HumanAttributeValuesTest < ActiveSupport::TestCase
|
|
33
39
|
assert_equal('4', grandchild.human_attribute_value(:field), 'should yield the value if there is no mapping in the type hierarchy')
|
34
40
|
end
|
35
41
|
|
36
|
-
test
|
42
|
+
test 'resolution of boolean values' do
|
37
43
|
boolean_model = BooleanModel.new(boolean_field: true)
|
38
44
|
assert_equal('This is true', boolean_model.human_attribute_value(:boolean_field), 'should translate boolean true')
|
39
45
|
|
@@ -41,7 +47,7 @@ class HumanAttributeValuesTest < ActiveSupport::TestCase
|
|
41
47
|
assert_equal('false', boolean_model.human_attribute_value(:boolean_field), 'should return the stringified boolean if there is no mapping')
|
42
48
|
end
|
43
49
|
|
44
|
-
test
|
50
|
+
test 'resolution for numeric values' do
|
45
51
|
numeric_model = NumericModel.new(integer_field: 1, decimal_field: 1.0)
|
46
52
|
assert_equal('One', numeric_model.human_attribute_value(:integer_field), 'should translate an integer')
|
47
53
|
assert_equal('One point zero', numeric_model.human_attribute_value(:decimal_field), 'should translate a decimal')
|
@@ -52,12 +58,14 @@ class HumanAttributeValuesTest < ActiveSupport::TestCase
|
|
52
58
|
assert_equal('2.0', numeric_model.human_attribute_value(:decimal_field), 'should return the stringified decimal if there is no mapping')
|
53
59
|
end
|
54
60
|
|
55
|
-
test
|
56
|
-
lexicon = Lexicon.new
|
57
|
-
|
61
|
+
test 'resolution for associations' do
|
62
|
+
lexicon = Lexicon.new
|
63
|
+
the_answer = TheAnswer.new(lexicon: lexicon)
|
64
|
+
assert_equal(lexicon.to_s, the_answer.human_attribute_value(:lexicon), 'should return .to_s for associations 1')
|
65
|
+
assert_equal(lexicon.the_answers.to_s, lexicon.human_attribute_value(:the_answers), 'should return .to_s for associations 2')
|
58
66
|
end
|
59
67
|
|
60
|
-
test
|
68
|
+
test 'resolution for enums' do
|
61
69
|
enum_model = EnumModel.new(status: :dead_and_alive)
|
62
70
|
assert_equal('The box has not been opened yet', enum_model.human_attribute_value(:status), 'should use the enumerated values for lookup')
|
63
71
|
|
data/test/dummy/Rakefile
CHANGED
@@ -1,6 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# Add your own tasks in files placed in lib/tasks ending in .rake,
|
2
4
|
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
|
3
5
|
|
4
|
-
require File.expand_path('
|
6
|
+
require File.expand_path('config/application', __dir__)
|
5
7
|
|
6
8
|
Dummy::Application.load_tasks
|