mobility 0.2.3 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/CHANGELOG.md +16 -0
- data/Gemfile +6 -1
- data/Gemfile.lock +59 -57
- data/README.md +63 -18
- data/lib/mobility.rb +0 -1
- data/lib/mobility/active_record.rb +0 -1
- data/lib/mobility/active_record/translation.rb +1 -1
- data/lib/mobility/attributes.rb +22 -11
- data/lib/mobility/backends/active_record/table.rb +13 -1
- data/lib/mobility/configuration.rb +24 -3
- data/lib/mobility/plugins/active_model/dirty.rb +19 -1
- data/lib/mobility/plugins/active_record/attribute_methods.rb +39 -0
- data/lib/mobility/plugins/active_record/dirty.rb +77 -12
- data/lib/mobility/plugins/attribute_methods.rb +41 -0
- data/lib/mobility/plugins/dirty.rb +1 -5
- data/lib/mobility/plugins/fallbacks.rb +44 -19
- data/lib/mobility/plugins/fallthrough_accessors.rb +2 -2
- data/lib/mobility/plugins/locale_accessors.rb +6 -6
- data/lib/mobility/version.rb +1 -1
- metadata +14 -7
- metadata.gz.sig +0 -0
- data/lib/mobility/active_record/attribute_methods.rb +0 -36
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c134f78117865e131baf9ceecb0c902cb63abb08
|
4
|
+
data.tar.gz: 2076ecc0e3164b962d1f5147e0af81d2ba9baac3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f6ec9f5003e16ace7ea7a77136266af20f5c86beb1ebea6ae4e83598d20bdf4d14971d6f029c2b1bd74763c599287e362b7b3204c51660606ab2b371a4620842
|
7
|
+
data.tar.gz: 8eae38b70cb15cb0eeec7dfb51f72e4076268312bdd73d63a9fda7611414d116e5bd95771a3042ca080ea4495c335e50a66f5c92a1beb6994e2d1d8d4c9d3bb9
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data.tar.gz.sig
CHANGED
Binary file
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,21 @@
|
|
1
1
|
# Mobility Changelog
|
2
2
|
|
3
|
+
## 0.3
|
4
|
+
|
5
|
+
### 0.3.0 (November 30, 2017)
|
6
|
+
* `dup` support for table backend ([#84](https://github.com/shioyama/mobility/pull/84)). Thanks [@pwim](https://github.com/pwim)!
|
7
|
+
* Disable fallbacks when using locale/fallthrough accessors
|
8
|
+
([#86](https://github.com/shioyama/mobility/pull/86), [#87](https://github.com/shioyama/mobility/pull/87),
|
9
|
+
[#88](https://github.com/shioyama/mobility/pull/88), [#89](https://github.com/shioyama/mobility/pull/89))
|
10
|
+
* Convert AttributeMethods to plugin
|
11
|
+
([#102](https://github.com/shioyama/mobility/pull/102))
|
12
|
+
* Ensure `cache_key` is invalidated when updating translations
|
13
|
+
([#104](https://github.com/shioyama/mobility/pull/102)) Thanks
|
14
|
+
[@pwim](https://github.com/pwim)!
|
15
|
+
* Update dependency versions ([#107](https://github.com/shioyama/mobility/pull/107))
|
16
|
+
* Support new AR::Dirty methods ([#111](https://github.com/shioyama/mobility/pull/111))
|
17
|
+
* Use `public_send` in LocaleAccessors plugin ([#117](https://github.com/shioyama/mobility/pull/117))
|
18
|
+
|
3
19
|
## 0.2
|
4
20
|
|
5
21
|
### 0.2.3 (September 14, 2017)
|
data/Gemfile
CHANGED
@@ -9,6 +9,9 @@ group :development, :test do
|
|
9
9
|
gem 'activerecord', '>= 5.0', '< 5.1'
|
10
10
|
elsif ENV['RAILS_VERSION'] == '4.2'
|
11
11
|
gem 'activerecord', '>= 4.2.6', '< 5.0'
|
12
|
+
elsif ENV['RAILS_VERSION'] == '5.2'
|
13
|
+
gem 'activerecord', '>= 5.2.0.beta1'
|
14
|
+
gem 'railties', '>= 5.2.0.beta1'
|
12
15
|
else
|
13
16
|
gem 'activerecord', '>= 5.1', '< 5.2'
|
14
17
|
end
|
@@ -16,6 +19,8 @@ group :development, :test do
|
|
16
19
|
elsif ENV['ORM'] == 'sequel'
|
17
20
|
if ENV['SEQUEL_VERSION'] == '4.41'
|
18
21
|
gem 'sequel', '>= 4.41.0', '< 4.46.0'
|
22
|
+
elsif ENV['SEQUEL_VERSION'] == 'latest'
|
23
|
+
gem 'sequel', '>= 5.0.0'
|
19
24
|
else
|
20
25
|
gem 'sequel', '>= 4.46.0', '< 5.0'
|
21
26
|
end
|
@@ -27,7 +32,7 @@ group :development, :test do
|
|
27
32
|
gem 'guard-rspec'
|
28
33
|
gem 'pry-byebug'
|
29
34
|
gem 'sqlite3'
|
30
|
-
gem 'mysql2', '~> 0.
|
35
|
+
gem 'mysql2', '~> 0.4.9'
|
31
36
|
gem 'pg'
|
32
37
|
end
|
33
38
|
end
|
data/Gemfile.lock
CHANGED
@@ -1,45 +1,46 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
mobility (0.
|
5
|
-
i18n (>= 0.6.10, < 0.
|
4
|
+
mobility (0.3.0.pre.alpha)
|
5
|
+
i18n (>= 0.6.10, < 0.10)
|
6
6
|
request_store (~> 1.0)
|
7
7
|
|
8
8
|
GEM
|
9
9
|
remote: https://rubygems.org/
|
10
10
|
specs:
|
11
|
-
actionpack (5.
|
12
|
-
actionview (= 5.
|
13
|
-
activesupport (= 5.
|
11
|
+
actionpack (5.2.0.beta2)
|
12
|
+
actionview (= 5.2.0.beta2)
|
13
|
+
activesupport (= 5.2.0.beta2)
|
14
14
|
rack (~> 2.0)
|
15
|
-
rack-test (
|
15
|
+
rack-test (>= 0.6.3)
|
16
16
|
rails-dom-testing (~> 2.0)
|
17
17
|
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
18
|
-
actionview (5.
|
19
|
-
activesupport (= 5.
|
18
|
+
actionview (5.2.0.beta2)
|
19
|
+
activesupport (= 5.2.0.beta2)
|
20
20
|
builder (~> 3.1)
|
21
21
|
erubi (~> 1.4)
|
22
22
|
rails-dom-testing (~> 2.0)
|
23
23
|
rails-html-sanitizer (~> 1.0, >= 1.0.3)
|
24
|
-
activemodel (5.
|
25
|
-
activesupport (= 5.
|
26
|
-
activerecord (5.
|
27
|
-
activemodel (= 5.
|
28
|
-
activesupport (= 5.
|
29
|
-
arel (
|
30
|
-
activesupport (5.
|
24
|
+
activemodel (5.2.0.beta2)
|
25
|
+
activesupport (= 5.2.0.beta2)
|
26
|
+
activerecord (5.2.0.beta2)
|
27
|
+
activemodel (= 5.2.0.beta2)
|
28
|
+
activesupport (= 5.2.0.beta2)
|
29
|
+
arel (>= 9.0)
|
30
|
+
activesupport (5.2.0.beta2)
|
31
31
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
32
32
|
i18n (~> 0.7)
|
33
33
|
minitest (~> 5.1)
|
34
34
|
tzinfo (~> 1.1)
|
35
|
-
arel (
|
35
|
+
arel (9.0.0)
|
36
36
|
builder (3.2.3)
|
37
|
-
byebug (9.0
|
38
|
-
coderay (1.1.
|
37
|
+
byebug (9.1.0)
|
38
|
+
coderay (1.1.2)
|
39
39
|
concurrent-ruby (1.0.5)
|
40
|
-
|
40
|
+
crass (1.0.3)
|
41
|
+
database_cleaner (1.6.2)
|
41
42
|
diff-lcs (1.3)
|
42
|
-
erubi (1.
|
43
|
+
erubi (1.7.0)
|
43
44
|
ffi (1.9.18)
|
44
45
|
formatador (0.2.5)
|
45
46
|
generator_spec (0.9.4)
|
@@ -59,91 +60,92 @@ GEM
|
|
59
60
|
guard (~> 2.1)
|
60
61
|
guard-compat (~> 1.1)
|
61
62
|
rspec (>= 2.99.0, < 4.0)
|
62
|
-
i18n (0.
|
63
|
+
i18n (0.9.1)
|
64
|
+
concurrent-ruby (~> 1.0)
|
63
65
|
listen (3.1.5)
|
64
66
|
rb-fsevent (~> 0.9, >= 0.9.4)
|
65
67
|
rb-inotify (~> 0.9, >= 0.9.7)
|
66
68
|
ruby_dep (~> 1.2)
|
67
|
-
loofah (2.
|
69
|
+
loofah (2.1.1)
|
70
|
+
crass (~> 1.0.2)
|
68
71
|
nokogiri (>= 1.5.9)
|
69
72
|
lumberjack (1.0.12)
|
70
|
-
method_source (0.
|
71
|
-
mini_portile2 (2.
|
73
|
+
method_source (0.9.0)
|
74
|
+
mini_portile2 (2.3.0)
|
72
75
|
minitest (5.10.3)
|
73
|
-
mysql2 (0.
|
76
|
+
mysql2 (0.4.10)
|
74
77
|
nenv (0.3.0)
|
75
|
-
nokogiri (1.8.
|
76
|
-
mini_portile2 (~> 2.
|
78
|
+
nokogiri (1.8.1)
|
79
|
+
mini_portile2 (~> 2.3.0)
|
77
80
|
notiffany (0.1.1)
|
78
81
|
nenv (~> 0.1)
|
79
82
|
shellany (~> 0.0)
|
80
83
|
pg (0.21.0)
|
81
|
-
pry (0.
|
84
|
+
pry (0.11.3)
|
82
85
|
coderay (~> 1.1.0)
|
83
|
-
method_source (~> 0.
|
84
|
-
|
85
|
-
|
86
|
-
byebug (~> 9.0)
|
86
|
+
method_source (~> 0.9.0)
|
87
|
+
pry-byebug (3.5.1)
|
88
|
+
byebug (~> 9.1)
|
87
89
|
pry (~> 0.10)
|
88
90
|
rack (2.0.3)
|
89
|
-
rack-test (0.
|
90
|
-
rack (>= 1.0)
|
91
|
+
rack-test (0.8.2)
|
92
|
+
rack (>= 1.0, < 3)
|
91
93
|
rails-dom-testing (2.0.3)
|
92
94
|
activesupport (>= 4.2.0)
|
93
95
|
nokogiri (>= 1.6)
|
94
96
|
rails-html-sanitizer (1.0.3)
|
95
97
|
loofah (~> 2.0)
|
96
|
-
railties (5.
|
97
|
-
actionpack (= 5.
|
98
|
-
activesupport (= 5.
|
98
|
+
railties (5.2.0.beta2)
|
99
|
+
actionpack (= 5.2.0.beta2)
|
100
|
+
activesupport (= 5.2.0.beta2)
|
99
101
|
method_source
|
100
102
|
rake (>= 0.8.7)
|
101
103
|
thor (>= 0.18.1, < 2.0)
|
102
|
-
rake (
|
104
|
+
rake (12.3.0)
|
103
105
|
rb-fsevent (0.10.2)
|
104
106
|
rb-inotify (0.9.10)
|
105
107
|
ffi (>= 0.5.0, < 2)
|
106
108
|
request_store (1.3.2)
|
107
|
-
rspec (3.
|
108
|
-
rspec-core (~> 3.
|
109
|
-
rspec-expectations (~> 3.
|
110
|
-
rspec-mocks (~> 3.
|
111
|
-
rspec-core (3.
|
112
|
-
rspec-support (~> 3.
|
113
|
-
rspec-expectations (3.
|
109
|
+
rspec (3.7.0)
|
110
|
+
rspec-core (~> 3.7.0)
|
111
|
+
rspec-expectations (~> 3.7.0)
|
112
|
+
rspec-mocks (~> 3.7.0)
|
113
|
+
rspec-core (3.7.0)
|
114
|
+
rspec-support (~> 3.7.0)
|
115
|
+
rspec-expectations (3.7.0)
|
114
116
|
diff-lcs (>= 1.2.0, < 2.0)
|
115
|
-
rspec-support (~> 3.
|
116
|
-
rspec-mocks (3.
|
117
|
+
rspec-support (~> 3.7.0)
|
118
|
+
rspec-mocks (3.7.0)
|
117
119
|
diff-lcs (>= 1.2.0, < 2.0)
|
118
|
-
rspec-support (~> 3.
|
119
|
-
rspec-support (3.
|
120
|
+
rspec-support (~> 3.7.0)
|
121
|
+
rspec-support (3.7.0)
|
120
122
|
ruby_dep (1.5.0)
|
121
123
|
shellany (0.0.1)
|
122
|
-
slop (3.6.0)
|
123
124
|
sqlite3 (1.3.13)
|
124
|
-
thor (0.
|
125
|
+
thor (0.20.0)
|
125
126
|
thread_safe (0.3.6)
|
126
|
-
tzinfo (1.2.
|
127
|
+
tzinfo (1.2.4)
|
127
128
|
thread_safe (~> 0.1)
|
128
|
-
yard (0.9.
|
129
|
+
yard (0.9.12)
|
129
130
|
|
130
131
|
PLATFORMS
|
131
132
|
ruby
|
132
133
|
|
133
134
|
DEPENDENCIES
|
134
|
-
activerecord (>= 5.
|
135
|
+
activerecord (>= 5.2.0.beta1)
|
135
136
|
bundler (~> 1.12)
|
136
137
|
database_cleaner (~> 1.5, >= 1.5.3)
|
137
138
|
generator_spec (~> 0.9.4)
|
138
139
|
guard-rspec
|
139
140
|
mobility!
|
140
|
-
mysql2 (~> 0.
|
141
|
+
mysql2 (~> 0.4.9)
|
141
142
|
pg
|
142
143
|
pry-byebug
|
143
|
-
|
144
|
+
railties (>= 5.2.0.beta1)
|
145
|
+
rake (~> 12, >= 12.2.1)
|
144
146
|
rspec (~> 3.0)
|
145
147
|
sqlite3
|
146
148
|
yard (~> 0.9.0)
|
147
149
|
|
148
150
|
BUNDLED WITH
|
149
|
-
1.
|
151
|
+
1.16.0.pre.2
|
data/README.md
CHANGED
@@ -16,7 +16,8 @@ Mobility
|
|
16
16
|
Mobility is a gem for storing and retrieving translations as attributes on a
|
17
17
|
class. These translations could be the content of blog posts, captions on
|
18
18
|
images, tags on bookmarks, or anything else you might want to store in
|
19
|
-
different languages.
|
19
|
+
different languages. For examples of what Mobility can do, see the
|
20
|
+
<a href="#companies-using-mobility">Companies using Mobility</a> section below.
|
20
21
|
|
21
22
|
Storage of translations is handled by customizable "backends" which encapsulate
|
22
23
|
different storage strategies. The default, preferred way to store translations
|
@@ -41,13 +42,17 @@ Mobility](http://dejimata.com/2017/3/3/translating-with-mobility). See also the
|
|
41
42
|
works for future releases, and other pages of the [wiki][wiki] for more detail
|
42
43
|
on usage.
|
43
44
|
|
45
|
+
If you're coming from Globalize, be sure to also read the [Migrating from
|
46
|
+
Globalize](https://github.com/shioyama/mobility/wiki/Migrating-from-Globalize)
|
47
|
+
section of the wiki.
|
48
|
+
|
44
49
|
Installation
|
45
50
|
------------
|
46
51
|
|
47
52
|
Add this line to your application's Gemfile:
|
48
53
|
|
49
54
|
```ruby
|
50
|
-
gem 'mobility', '~> 0.
|
55
|
+
gem 'mobility', '~> 0.3.0'
|
51
56
|
```
|
52
57
|
|
53
58
|
Mobility is cryptographically signed. To be sure the gem you install hasn't
|
@@ -104,7 +109,7 @@ See [Getting Started](#quickstart) to get started translating your models.
|
|
104
109
|
### Sequel
|
105
110
|
|
106
111
|
Requirements:
|
107
|
-
- Sequel >= 4.0
|
112
|
+
- Sequel >= 4.0, < 5.0 (5.0 support is in the works)
|
108
113
|
|
109
114
|
You can extend `Mobility` just like in ActiveRecord, or you can use the
|
110
115
|
`mobility` plugin, which does the same thing:
|
@@ -222,7 +227,7 @@ locations, usually database columns. By default these values are stored as keys
|
|
222
227
|
tables, one for strings and one for text columns, but this can be easily
|
223
228
|
changed and/or customized (see the [Backends](#backends) section below).
|
224
229
|
|
225
|
-
### Getting and Setting Translations
|
230
|
+
### <a name="getset"></a> Getting and Setting Translations
|
226
231
|
|
227
232
|
The easiest way to get or set a translation is to use the getter and setter
|
228
233
|
methods described above (`word.name` and `word.name=`), but you may want to
|
@@ -309,6 +314,11 @@ word.name(locale: :fr)
|
|
309
314
|
#=> "mobilité"
|
310
315
|
```
|
311
316
|
|
317
|
+
Note that setting the locale this way will pass an option `locale: true` to the
|
318
|
+
backend and all plugins. Plugins may use this option to change their behavior
|
319
|
+
(passing the locale explicitly this way, for example, disables
|
320
|
+
[fallbacks](#fallbacks), see below for details).
|
321
|
+
|
312
322
|
You can also *set* the value of an attribute this way; however, since the
|
313
323
|
`word.name = <value>` syntax does not accept any options, the only way to do this is to
|
314
324
|
use `send` (this is included mostly for consistency):
|
@@ -387,8 +397,8 @@ translated attributes on a class:
|
|
387
397
|
```ruby
|
388
398
|
class Word < ApplicationRecord
|
389
399
|
extend Mobility
|
390
|
-
translates :name, type: :string, fallbacks: { de: :ja, fr: :ja }
|
391
|
-
translates :meaning, type: :text, fallbacks: { de: :ja, fr: :ja }
|
400
|
+
translates :name, type: :string, fallbacks: { de: :ja, fr: :ja }, locale_accessors: true
|
401
|
+
translates :meaning, type: :text, fallbacks: { de: :ja, fr: :ja }, locale_accessors: true
|
392
402
|
end
|
393
403
|
```
|
394
404
|
|
@@ -404,17 +414,20 @@ but not for other locales:
|
|
404
414
|
```ruby
|
405
415
|
Mobility.locale = :ja
|
406
416
|
word = Word.create(name: "モビリティ", meaning: "(名詞):動きやすさ、可動性")
|
407
|
-
|
417
|
+
Mobility.locale = :de
|
418
|
+
word.name
|
408
419
|
#=> "モビリティ"
|
409
|
-
word.meaning
|
420
|
+
word.meaning
|
410
421
|
#=> "(名詞):動きやすさ、可動性"
|
411
|
-
|
422
|
+
Mobility.locale = :fr
|
423
|
+
word.name
|
412
424
|
#=> "モビリティ"
|
413
|
-
word.meaning
|
425
|
+
word.meaning
|
414
426
|
#=> "(名詞):動きやすさ、可動性"
|
415
|
-
|
427
|
+
Mobility.locale = :ru
|
428
|
+
word.name
|
416
429
|
#=> nil
|
417
|
-
word.meaning
|
430
|
+
word.meaning
|
418
431
|
#=> nil
|
419
432
|
```
|
420
433
|
|
@@ -423,11 +436,14 @@ You can optionally disable fallbacks to get the real value for a given locale
|
|
423
436
|
passing `fallback: false` (*singular*, not plural) to the getter method:
|
424
437
|
|
425
438
|
```ruby
|
426
|
-
|
439
|
+
Mobility.locale = :de
|
440
|
+
word.meaning(fallback: false)
|
427
441
|
#=> nil
|
428
|
-
|
442
|
+
Mobility.locale = :fr
|
443
|
+
word.meaning(fallback: false)
|
429
444
|
#=> nil
|
430
|
-
|
445
|
+
Mobility.locale = :ja
|
446
|
+
word.meaning(fallback: false)
|
431
447
|
#=> "(名詞):動きやすさ、可動性"
|
432
448
|
```
|
433
449
|
|
@@ -439,11 +455,28 @@ Mobility.with_locale(:fr) do
|
|
439
455
|
word.meaning = "(nf): aptitude à bouger, à se déplacer, à changer, à évoluer"
|
440
456
|
end
|
441
457
|
word.save
|
442
|
-
|
458
|
+
Mobility.locale = :de
|
459
|
+
word.meaning(fallback: false)
|
443
460
|
#=> nil
|
444
|
-
word.meaning(
|
461
|
+
word.meaning(fallback: :fr)
|
445
462
|
#=> "(nf): aptitude à bouger, à se déplacer, à changer, à évoluer"
|
446
|
-
word.meaning(
|
463
|
+
word.meaning(fallback: [:ja, :fr])
|
464
|
+
#=> "(名詞):動きやすさ、可動性"
|
465
|
+
```
|
466
|
+
|
467
|
+
Also note that passing a `locale` option into an attribute reader or writer, or
|
468
|
+
using [locale accessors or fallthrough accessors](#getset) to get or set
|
469
|
+
any attribute value, will disable fallbacks (just like `fallback: false`).
|
470
|
+
(This will take precedence over any value of the `fallback` option.)
|
471
|
+
|
472
|
+
Continuing from the last example:
|
473
|
+
|
474
|
+
```ruby
|
475
|
+
word.meaning(locale: :de)
|
476
|
+
#=> nil
|
477
|
+
word.meaning_de
|
478
|
+
#=> nil
|
479
|
+
Mobility.with_locale(:de) { word.meaning }
|
447
480
|
#=> "(名詞):動きやすさ、可動性"
|
448
481
|
```
|
449
482
|
|
@@ -830,6 +863,18 @@ More Information
|
|
830
863
|
- [API documentation][docs]
|
831
864
|
- [Wiki][wiki]
|
832
865
|
|
866
|
+
<a name="#companies-using-mobility"></a>Companies using Mobility
|
867
|
+
------------------------
|
868
|
+
|
869
|
+
<img alt="Logos of companies using Mobility" src="./img/companies-using-mobility.png" style="width: 100%" />
|
870
|
+
|
871
|
+
- [Doorkeeper](https://www.doorkeeper.jp/)
|
872
|
+
- [Oreegano](https://www.oreegano.com/)
|
873
|
+
- [Venuu](https://venuu.fi)
|
874
|
+
- ... <sup>✱</sup>
|
875
|
+
|
876
|
+
<sup>✱</sup> <small>Post an issue or email me to add your company's name to this list.</small>
|
877
|
+
|
833
878
|
License
|
834
879
|
-------
|
835
880
|
|
data/lib/mobility.rb
CHANGED
@@ -89,7 +89,6 @@ module Mobility
|
|
89
89
|
|
90
90
|
if Loaded::ActiveRecord
|
91
91
|
model_class.include(ActiveRecord) if model_class < ::ActiveRecord::Base
|
92
|
-
model_class.include(ActiveRecord::AttributeMethods) if model_class.ancestors.include?(::ActiveRecord::AttributeMethods)
|
93
92
|
end
|
94
93
|
|
95
94
|
if Loaded::Sequel
|
@@ -4,7 +4,7 @@ module Mobility
|
|
4
4
|
class Translation < ::ActiveRecord::Base
|
5
5
|
self.abstract_class = true
|
6
6
|
|
7
|
-
belongs_to :translatable, polymorphic: true
|
7
|
+
belongs_to :translatable, polymorphic: true, touch: true
|
8
8
|
|
9
9
|
validates :key, presence: true, uniqueness: { scope: [:translatable_id, :translatable_type, :locale] }
|
10
10
|
validates :translatable, presence: true
|
data/lib/mobility/attributes.rb
CHANGED
@@ -19,7 +19,7 @@ like including a module. Creating an instance like this:
|
|
19
19
|
|
20
20
|
Attributes.new("title", backend: :my_backend, locale_accessors: [:en, :ja], cache: true, fallbacks: true)
|
21
21
|
|
22
|
-
will generate an anonymous module that behaves like this:
|
22
|
+
will generate an anonymous module that behaves (approximately) like this:
|
23
23
|
|
24
24
|
Module.new do
|
25
25
|
def title_backend
|
@@ -131,7 +131,7 @@ with other backends.
|
|
131
131
|
def initialize(*attribute_names, method: :accessor, backend: Mobility.default_backend, **backend_options)
|
132
132
|
raise ArgumentError, "method must be one of: reader, writer, accessor" unless %i[reader writer accessor].include?(method)
|
133
133
|
@method = method
|
134
|
-
@options = Mobility.default_options.merge(backend_options)
|
134
|
+
@options = Mobility.default_options.to_h.merge(backend_options)
|
135
135
|
@names = attribute_names.map(&:to_s)
|
136
136
|
raise Mobility::BackendRequired, "Backend option required if Mobility.config.default_backend is not set." if backend.nil?
|
137
137
|
@backend_name = backend
|
@@ -168,6 +168,17 @@ with other backends.
|
|
168
168
|
names.each(&block)
|
169
169
|
end
|
170
170
|
|
171
|
+
# Process options passed into accessor method before calling backend, and
|
172
|
+
# return locale
|
173
|
+
# @param [Hash] options Options hash passed to accessor method
|
174
|
+
# @return [Symbol] locale
|
175
|
+
def self.process_options!(options)
|
176
|
+
(options[:locale] || Mobility.locale).tap { |locale|
|
177
|
+
Mobility.enforce_available_locales!(locale)
|
178
|
+
options[:locale] &&= !!locale
|
179
|
+
}.to_sym
|
180
|
+
end
|
181
|
+
|
171
182
|
private
|
172
183
|
|
173
184
|
def define_backend(attribute)
|
@@ -179,24 +190,24 @@ with other backends.
|
|
179
190
|
end
|
180
191
|
|
181
192
|
def define_reader(attribute)
|
182
|
-
define_method attribute do
|
193
|
+
define_method attribute do |**options|
|
183
194
|
return super() if options.delete(:super)
|
184
|
-
Mobility.
|
185
|
-
mobility_backend_for(attribute).read(locale
|
195
|
+
locale = Mobility::Attributes.process_options!(options)
|
196
|
+
mobility_backend_for(attribute).read(locale, options)
|
186
197
|
end
|
187
198
|
|
188
|
-
define_method "#{attribute}?" do
|
199
|
+
define_method "#{attribute}?" do |**options|
|
189
200
|
return super() if options.delete(:super)
|
190
|
-
Mobility.
|
191
|
-
mobility_backend_for(attribute).present?(locale
|
201
|
+
locale = Mobility::Attributes.process_options!(options)
|
202
|
+
mobility_backend_for(attribute).present?(locale, options)
|
192
203
|
end
|
193
204
|
end
|
194
205
|
|
195
206
|
def define_writer(attribute)
|
196
|
-
define_method "#{attribute}=" do |value,
|
207
|
+
define_method "#{attribute}=" do |value, **options|
|
197
208
|
return super(value) if options.delete(:super)
|
198
|
-
Mobility.
|
199
|
-
mobility_backend_for(attribute).write(locale
|
209
|
+
locale = Mobility::Attributes.process_options!(options)
|
210
|
+
mobility_backend_for(attribute).write(locale, value, options)
|
200
211
|
end
|
201
212
|
end
|
202
213
|
|
@@ -136,7 +136,19 @@ columns to that table.
|
|
136
136
|
translation_class.belongs_to :translated_model,
|
137
137
|
class_name: name,
|
138
138
|
foreign_key: options[:foreign_key],
|
139
|
-
inverse_of: association_name
|
139
|
+
inverse_of: association_name,
|
140
|
+
touch: true
|
141
|
+
|
142
|
+
module_name = "MobilityArTable#{association_name.to_s.camelcase}"
|
143
|
+
unless const_defined?(module_name)
|
144
|
+
callback_methods = Module.new do
|
145
|
+
define_method :initialize_dup do |source|
|
146
|
+
super(source)
|
147
|
+
self.send("#{association_name}=", source.send(association_name).map(&:dup))
|
148
|
+
end
|
149
|
+
end
|
150
|
+
include const_set(module_name, callback_methods)
|
151
|
+
end
|
140
152
|
end
|
141
153
|
|
142
154
|
setup_query_methods(QueryMethods)
|
@@ -20,7 +20,17 @@ Stores shared Mobility configuration referenced by all backends.
|
|
20
20
|
# may not include the keys 'backend' or 'model_class'.
|
21
21
|
# @return [Hash]
|
22
22
|
attr_reader :default_options
|
23
|
+
|
24
|
+
# @deprecated The default_options= setter has been deprecated. Set each
|
25
|
+
# option on the default_options hash instead.
|
23
26
|
def default_options=(options)
|
27
|
+
warn %{
|
28
|
+
WARNING: The default_options= setter has been deprecated.
|
29
|
+
Set each option on the default_options hash instead, like this:
|
30
|
+
|
31
|
+
config.default_options[:fallbacks] = { ... }
|
32
|
+
config.default_options[:dirty] = true
|
33
|
+
}
|
24
34
|
if (keys = options.keys & RESERVED_OPTION_KEYS).present?
|
25
35
|
raise ReservedOptionKey,
|
26
36
|
"Default options may not contain the following reserved keys: #{keys.join(', ')}"
|
@@ -63,24 +73,35 @@ Stores shared Mobility configuration referenced by all backends.
|
|
63
73
|
@query_method = :i18n
|
64
74
|
@default_fallbacks = lambda { |fallbacks| I18n::Locale::Fallbacks.new(fallbacks) }
|
65
75
|
@default_accessor_locales = lambda { I18n.available_locales }
|
66
|
-
@default_options = {
|
76
|
+
@default_options = Options[{
|
67
77
|
cache: true,
|
68
78
|
dirty: false,
|
69
79
|
fallbacks: nil,
|
70
80
|
presence: true,
|
71
|
-
default: nil
|
72
|
-
|
81
|
+
default: nil,
|
82
|
+
attribute_methods: false
|
83
|
+
}]
|
73
84
|
@plugins = %i[
|
74
85
|
cache
|
75
86
|
dirty
|
76
87
|
fallbacks
|
77
88
|
presence
|
78
89
|
default
|
90
|
+
attribute_methods
|
79
91
|
fallthrough_accessors
|
80
92
|
locale_accessors
|
81
93
|
]
|
82
94
|
end
|
83
95
|
|
84
96
|
class ReservedOptionKey < Exception; end
|
97
|
+
|
98
|
+
class Options < Hash
|
99
|
+
def []=(key, _)
|
100
|
+
if RESERVED_OPTION_KEYS.include?(key)
|
101
|
+
raise Configuration::ReservedOptionKey, "Default options may not contain the following reserved key: #{key}"
|
102
|
+
end
|
103
|
+
super
|
104
|
+
end
|
105
|
+
end
|
85
106
|
end
|
86
107
|
end
|
@@ -30,8 +30,9 @@ value of the translated attribute if passed to it.
|
|
30
30
|
def write(locale, value, options = {})
|
31
31
|
locale_accessor = Mobility.normalize_locale_accessor(attribute, locale)
|
32
32
|
if model.changed_attributes.has_key?(locale_accessor) && model.changed_attributes[locale_accessor] == value
|
33
|
-
model.attributes_changed_by_setter.except!(locale_accessor)
|
33
|
+
model.send(:attributes_changed_by_setter).except!(locale_accessor)
|
34
34
|
elsif read(locale, options.merge(fallback: false)) != value
|
35
|
+
model.send(:mobility_changed_attributes) << locale_accessor
|
35
36
|
model.send(:attribute_will_change!, locale_accessor)
|
36
37
|
end
|
37
38
|
super
|
@@ -63,6 +64,10 @@ value of the translated attribute if passed to it.
|
|
63
64
|
private :restore_attribute!
|
64
65
|
end
|
65
66
|
|
67
|
+
def included(model_class)
|
68
|
+
model_class.include ChangedAttributes
|
69
|
+
end
|
70
|
+
|
66
71
|
private
|
67
72
|
|
68
73
|
# Get method suffixes. Creating an object just to get the list of
|
@@ -74,6 +79,19 @@ value of the translated attribute if passed to it.
|
|
74
79
|
include ::ActiveModel::Dirty
|
75
80
|
end.attribute_method_matchers.map(&:suffix).select { |m| m =~ /\A_/ }
|
76
81
|
end
|
82
|
+
|
83
|
+
# Tracks which translated attributes have been changed, separate from
|
84
|
+
# the default tracking of changes in ActiveModel/ActiveRecord Dirty.
|
85
|
+
# This is required in order for the Mobility ActiveRecord Dirty
|
86
|
+
# plugin to correctly read the value of locale accessors like
|
87
|
+
# +title_en+ in dirty tracking.
|
88
|
+
module ChangedAttributes
|
89
|
+
private
|
90
|
+
|
91
|
+
def mobility_changed_attributes
|
92
|
+
@mobility_changed_attributes ||= Set.new
|
93
|
+
end
|
94
|
+
end
|
77
95
|
end
|
78
96
|
end
|
79
97
|
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Mobility
|
2
|
+
module Plugins
|
3
|
+
=begin
|
4
|
+
|
5
|
+
Module builder adding translated attributes to #attributes hash on model
|
6
|
+
instance. See {Mobility::Plugins::AttributeMethods} for further details.
|
7
|
+
|
8
|
+
=end
|
9
|
+
module ActiveRecord
|
10
|
+
module TranslatedAttributes
|
11
|
+
def translated_attributes
|
12
|
+
{}
|
13
|
+
end
|
14
|
+
|
15
|
+
def attributes
|
16
|
+
super.merge(translated_attributes)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class AttributeMethods < Module
|
21
|
+
def initialize(*attribute_names)
|
22
|
+
include TranslatedAttributes
|
23
|
+
define_method :translated_attributes do
|
24
|
+
super().merge(attribute_names.inject({}) do |attributes, name|
|
25
|
+
attributes.merge(name.to_s => send(name))
|
26
|
+
end)
|
27
|
+
end
|
28
|
+
delegate :translated_attribute_names, to: :class
|
29
|
+
end
|
30
|
+
|
31
|
+
def included(model_class)
|
32
|
+
model_class.class_eval do
|
33
|
+
define_method :untranslated_attributes, ::ActiveRecord::Base.instance_method(:attributes)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -8,6 +8,17 @@ module Mobility
|
|
8
8
|
Dirty tracking for AR models. See {Mobility::Plugins::ActiveModel::Dirty} for
|
9
9
|
details on usage.
|
10
10
|
|
11
|
+
In addition to methods added by {Mobility::Plugins::ActiveModel::Diryt}, the
|
12
|
+
AR::Dirty plugin adds support for the following persistence-specific methods
|
13
|
+
(for a model with a translated attribute +title+):
|
14
|
+
- +saved_changes+
|
15
|
+
- +saved_change_to_title?+
|
16
|
+
- +saved_change_to_title+
|
17
|
+
- +title_before_last_save+
|
18
|
+
- +will_save_change_to_title?+
|
19
|
+
- +title_change_to_be_saved+
|
20
|
+
- +title_in_database+
|
21
|
+
|
11
22
|
=end
|
12
23
|
module ActiveRecord
|
13
24
|
module Dirty
|
@@ -19,7 +30,33 @@ details on usage.
|
|
19
30
|
def initialize(*attribute_names)
|
20
31
|
super
|
21
32
|
@attribute_names = attribute_names
|
33
|
+
define_method_overrides
|
34
|
+
define_attribute_methods if ::ActiveRecord::VERSION::STRING >= '5.1'
|
35
|
+
end
|
22
36
|
|
37
|
+
# Overrides +ActiveRecord::AttributeMethods::ClassMethods#has_attribute+ and
|
38
|
+
# +ActiveModel::AttributeMethods#_read_attribute+ to treat
|
39
|
+
# fallthrough attribute methods just like "real" attribute methods.
|
40
|
+
#
|
41
|
+
# @note Patching +has_attribute?+ is necessary as of AR 5.1 due to this commit[https://github.com/rails/rails/commit/4fed08fa787a316fa51f14baca9eae11913f5050].
|
42
|
+
# (I have voiced my opposition to this change here[https://github.com/rails/rails/pull/27963#issuecomment-310092787]).
|
43
|
+
# @param [Attributes] attributes
|
44
|
+
def included(model_class)
|
45
|
+
super
|
46
|
+
names = @attribute_names
|
47
|
+
method_name_regex = /\A(#{names.join('|'.freeze)})_([a-z]{2}(_[a-z]{2})?)(=?|\??)\z/.freeze
|
48
|
+
has_attribute = Module.new do
|
49
|
+
define_method :has_attribute? do |attr_name|
|
50
|
+
super(attr_name) || !!method_name_regex.match(attr_name)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
model_class.extend has_attribute
|
54
|
+
model_class.include ReadAttribute if ::ActiveRecord::VERSION::STRING >= '5.2'
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def define_method_overrides
|
23
60
|
changes_applied_method = ::ActiveRecord::VERSION::STRING < '5.1' ? :changes_applied : :changes_internally_applied
|
24
61
|
define_method changes_applied_method do
|
25
62
|
@previously_changed = changes
|
@@ -36,21 +73,49 @@ details on usage.
|
|
36
73
|
end
|
37
74
|
end
|
38
75
|
|
39
|
-
#
|
40
|
-
|
76
|
+
# For AR >= 5.1 only
|
77
|
+
def define_attribute_methods
|
78
|
+
define_method :saved_changes do
|
79
|
+
(@previously_changed ||= ActiveSupport::HashWithIndifferentAccess.new).merge(super())
|
80
|
+
end
|
81
|
+
|
82
|
+
@attribute_names.each do |name|
|
83
|
+
define_method :"saved_change_to_#{name}?" do
|
84
|
+
previous_changes.include?(Mobility.normalize_locale_accessor(name))
|
85
|
+
end
|
86
|
+
|
87
|
+
define_method :"saved_change_to_#{name}" do
|
88
|
+
previous_changes[Mobility.normalize_locale_accessor(name)]
|
89
|
+
end
|
90
|
+
|
91
|
+
define_method :"#{name}_before_last_save" do
|
92
|
+
previous_changes[Mobility.normalize_locale_accessor(name)].first
|
93
|
+
end
|
94
|
+
|
95
|
+
alias_method :"will_save_change_to_#{name}?", :"#{name}_changed?"
|
96
|
+
alias_method :"#{name}_change_to_be_saved", :"#{name}_change"
|
97
|
+
alias_method :"#{name}_in_database", :"#{name}_was"
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
# Overrides _read_attribute to correctly dispatch reads on translated
|
102
|
+
# attributes to their respective setters, rather than to
|
103
|
+
# +@attributes+, which would otherwise return +nil+.
|
41
104
|
#
|
42
|
-
#
|
43
|
-
#
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
super
|
105
|
+
# For background on why this is necessary, see:
|
106
|
+
# https://github.com/shioyama/mobility/issues/115
|
107
|
+
module ReadAttribute
|
108
|
+
# @note We first check if attributes has the key +attr+ to avoid
|
109
|
+
# doing any extra work in case this is a "normal"
|
110
|
+
# (non-translated) attribute.
|
111
|
+
def _read_attribute(attr, *args)
|
112
|
+
if @attributes.key?(attr)
|
113
|
+
super
|
114
|
+
else
|
115
|
+
mobility_changed_attributes.include?(attr) ? __send__(attr) : super
|
51
116
|
end
|
52
117
|
end
|
53
|
-
|
118
|
+
private :_read_attribute
|
54
119
|
end
|
55
120
|
end
|
56
121
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Mobility
|
2
|
+
module Plugins
|
3
|
+
=begin
|
4
|
+
|
5
|
+
Adds translated attribute names and values to the hash returned by #attributes.
|
6
|
+
Also adds a method #translated_attributes with names and values of translated
|
7
|
+
attributes only.
|
8
|
+
|
9
|
+
@note Adding translated attributes to +attributes+ can have unexpected
|
10
|
+
consequences, since these attributes do not have corresponding columns in the
|
11
|
+
model table. Using this plugin may lead to conflicts with other gems.
|
12
|
+
|
13
|
+
=end
|
14
|
+
module AttributeMethods
|
15
|
+
class << self
|
16
|
+
# Applies attribute_methods plugin for a given option value.
|
17
|
+
# @param [Attributes] attributes
|
18
|
+
# @param [Boolean] option Value of option
|
19
|
+
# @raise [ArgumentError] if model class does not support dirty tracking
|
20
|
+
def apply(attributes, option)
|
21
|
+
if option
|
22
|
+
include_attribute_methods_module(attributes.model_class, *attributes.names)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def include_attribute_methods_module(model_class, *attribute_names)
|
29
|
+
module_builder =
|
30
|
+
if Loaded::ActiveRecord && model_class.ancestors.include?(::ActiveRecord::AttributeMethods)
|
31
|
+
require "mobility/plugins/active_record/attribute_methods"
|
32
|
+
Plugins::ActiveRecord::AttributeMethods
|
33
|
+
else
|
34
|
+
raise ArgumentError, "#{model_class} does not support AttributeMethods plugin."
|
35
|
+
end
|
36
|
+
model_class.include module_builder.new(*attribute_names)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -14,11 +14,7 @@ details.
|
|
14
14
|
@note Dirty tracking can have unexpected results when combined with fallbacks.
|
15
15
|
A change in the fallback locale value will not mark an attribute falling
|
16
16
|
through to that locale as changed, even though it may look like it has
|
17
|
-
changed.
|
18
|
-
or blank to a new value, the change will be recorded as a change from that
|
19
|
-
fallback value, rather than from the nil or blank value. The specs are the
|
20
|
-
most reliable source of information on the interaction between dirty tracking
|
21
|
-
and fallbacks.
|
17
|
+
changed. See the specs for details on expected behavior.
|
22
18
|
|
23
19
|
=end
|
24
20
|
module Dirty
|
@@ -15,14 +15,20 @@ defaults to an instance of +I18n::Locale::Fallbacks+, but can be configured
|
|
15
15
|
If a hash is passed to the +fallbacks+ option, a new fallbacks instance will be
|
16
16
|
created for the model with the hash defining additional fallbacks.
|
17
17
|
|
18
|
-
In addition, fallbacks
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
locale
|
18
|
+
In addition, fallbacks are disabled in certain situation. To explicitly disable
|
19
|
+
fallbacks when reading and writing, you can pass the <tt>fallback: false</tt>
|
20
|
+
option to the reader method. This can be useful to determine the actual
|
21
|
+
value of the translated attribute, including a possible +nil+ value.
|
22
|
+
|
23
|
+
The other situation where fallbacks are disabled is when the locale is
|
24
|
+
specified explicitly, either by passing a `locale` option to the accessor or by
|
25
|
+
using locale or fallthrough accessors. (See example below.)
|
26
|
+
|
27
|
+
You can also pass a locale or array of locales to the +fallback+ option to use
|
28
|
+
that locale or locales that read, e.g. <tt>fallback: :fr</tt> would fetch the
|
29
|
+
French translation if the value in the current locale was +nil+, whereas
|
30
|
+
<tt>fallback: [:fr, :es]</tt> would try French, then Spanish if the value in
|
31
|
+
the current locale was +nil+.
|
26
32
|
|
27
33
|
@see https://github.com/svenfuchs/i18n/wiki/Fallbacks I18n Fallbacks
|
28
34
|
|
@@ -76,6 +82,26 @@ locale was +nil+.
|
|
76
82
|
#=> nil
|
77
83
|
post.title(fallback: :fr)
|
78
84
|
#=> "Mobilité"
|
85
|
+
|
86
|
+
@example Fallbacks disabled
|
87
|
+
class Post
|
88
|
+
translates :title, fallbacks: { :'fr' => 'en' }, locale_accessors: true
|
89
|
+
end
|
90
|
+
|
91
|
+
I18n.default_locale = :en
|
92
|
+
Mobility.locale = :en
|
93
|
+
post = Post.new(title: "Mobility")
|
94
|
+
|
95
|
+
Mobility.locale = :fr
|
96
|
+
post.title
|
97
|
+
#=> "Mobility"
|
98
|
+
post.title(fallback: false)
|
99
|
+
#=> nil
|
100
|
+
post.title(locale: :fr)
|
101
|
+
#=> nil
|
102
|
+
post.title_fr
|
103
|
+
#=> nil
|
104
|
+
|
79
105
|
=end
|
80
106
|
class Fallbacks < Module
|
81
107
|
# Applies fallbacks plugin to attributes.
|
@@ -92,17 +118,16 @@ locale was +nil+.
|
|
92
118
|
private
|
93
119
|
|
94
120
|
def define_read(fallbacks)
|
95
|
-
define_method :read do |locale, **options|
|
96
|
-
fallback
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
value = super(fallback_locale, options)
|
103
|
-
break value if Util.present?(value)
|
104
|
-
end
|
121
|
+
define_method :read do |locale, fallback: true, **options|
|
122
|
+
return super(locale, options) if !fallback || options[:locale]
|
123
|
+
|
124
|
+
locales = fallback == true ? fallbacks[locale] : [locale, *fallback]
|
125
|
+
locales.each do |fallback_locale|
|
126
|
+
value = super(fallback_locale, options)
|
127
|
+
return value if Util.present?(value)
|
105
128
|
end
|
129
|
+
|
130
|
+
super(locale, options)
|
106
131
|
end
|
107
132
|
end
|
108
133
|
|
@@ -112,7 +137,7 @@ locale was +nil+.
|
|
112
137
|
elsif option == true
|
113
138
|
Mobility.default_fallbacks
|
114
139
|
else
|
115
|
-
|
140
|
+
Hash.new { [] }
|
116
141
|
end
|
117
142
|
end
|
118
143
|
end
|
@@ -46,12 +46,12 @@ model class is generated.
|
|
46
46
|
def initialize(*attributes)
|
47
47
|
method_name_regex = /\A(#{attributes.join('|'.freeze)})_([a-z]{2}(_[a-z]{2})?)(=?|\??)\z/.freeze
|
48
48
|
|
49
|
-
define_method :method_missing do |method_name, *arguments, &block|
|
49
|
+
define_method :method_missing do |method_name, *arguments, **options, &block|
|
50
50
|
if method_name =~ method_name_regex
|
51
51
|
attribute = $1.to_sym
|
52
52
|
locale, suffix = $2.split('_'.freeze)
|
53
53
|
locale = "#{locale}-#{suffix.upcase}".freeze if suffix
|
54
|
-
|
54
|
+
public_send("#{attribute}#{$4}".freeze, *arguments, **options, locale: locale.to_sym)
|
55
55
|
else
|
56
56
|
super(method_name, *arguments, &block)
|
57
57
|
end
|
@@ -58,14 +58,14 @@ If no locales are passed as an option to the initializer,
|
|
58
58
|
|
59
59
|
define_method "#{name}_#{normalized_locale}" do |**options|
|
60
60
|
return super() if options.delete(:super)
|
61
|
-
warn warning_message if options
|
62
|
-
|
61
|
+
warn warning_message if options[:locale]
|
62
|
+
public_send(name, **options, locale: locale)
|
63
63
|
end
|
64
64
|
|
65
65
|
define_method "#{name}_#{normalized_locale}?" do |**options|
|
66
66
|
return super() if options.delete(:super)
|
67
|
-
warn warning_message if options
|
68
|
-
|
67
|
+
warn warning_message if options[:locale]
|
68
|
+
public_send("#{name}?", **options, locale: locale)
|
69
69
|
end
|
70
70
|
end
|
71
71
|
|
@@ -75,8 +75,8 @@ If no locales are passed as an option to the initializer,
|
|
75
75
|
|
76
76
|
define_method "#{name}_#{normalized_locale}=" do |value, **options|
|
77
77
|
return super(value) if options.delete(:super)
|
78
|
-
warn warning_message if options
|
79
|
-
|
78
|
+
warn warning_message if options[:locale]
|
79
|
+
public_send("#{name}=", value, **options, locale: locale)
|
80
80
|
end
|
81
81
|
end
|
82
82
|
end
|
data/lib/mobility/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mobility
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chris Salzberg
|
@@ -30,7 +30,7 @@ cert_chain:
|
|
30
30
|
eGDROPZoL5RXwiOnRbexxa7dcAxMrDfGB/hpiunIPWPsi4n5P7K/6OO/sGVMl9xv
|
31
31
|
SZBPXjzrHdyOFLBYXB+PG7s3F/4=
|
32
32
|
-----END CERTIFICATE-----
|
33
|
-
date: 2017-
|
33
|
+
date: 2017-11-30 00:00:00.000000000 Z
|
34
34
|
dependencies:
|
35
35
|
- !ruby/object:Gem::Dependency
|
36
36
|
name: request_store
|
@@ -55,7 +55,7 @@ dependencies:
|
|
55
55
|
version: 0.6.10
|
56
56
|
- - "<"
|
57
57
|
- !ruby/object:Gem::Version
|
58
|
-
version: '0.
|
58
|
+
version: '0.10'
|
59
59
|
type: :runtime
|
60
60
|
prerelease: false
|
61
61
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -65,7 +65,7 @@ dependencies:
|
|
65
65
|
version: 0.6.10
|
66
66
|
- - "<"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '0.
|
68
|
+
version: '0.10'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: bundler
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -106,14 +106,20 @@ dependencies:
|
|
106
106
|
requirements:
|
107
107
|
- - "~>"
|
108
108
|
- !ruby/object:Gem::Version
|
109
|
-
version: '
|
109
|
+
version: '12'
|
110
|
+
- - ">="
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: 12.2.1
|
110
113
|
type: :development
|
111
114
|
prerelease: false
|
112
115
|
version_requirements: !ruby/object:Gem::Requirement
|
113
116
|
requirements:
|
114
117
|
- - "~>"
|
115
118
|
- !ruby/object:Gem::Version
|
116
|
-
version: '
|
119
|
+
version: '12'
|
120
|
+
- - ">="
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: 12.2.1
|
117
123
|
- !ruby/object:Gem::Dependency
|
118
124
|
name: rspec
|
119
125
|
requirement: !ruby/object:Gem::Requirement
|
@@ -163,7 +169,6 @@ files:
|
|
163
169
|
- lib/mobility/active_model.rb
|
164
170
|
- lib/mobility/active_model/backend_resetter.rb
|
165
171
|
- lib/mobility/active_record.rb
|
166
|
-
- lib/mobility/active_record/attribute_methods.rb
|
167
172
|
- lib/mobility/active_record/backend_resetter.rb
|
168
173
|
- lib/mobility/active_record/model_translation.rb
|
169
174
|
- lib/mobility/active_record/string_translation.rb
|
@@ -221,7 +226,9 @@ files:
|
|
221
226
|
- lib/mobility/plugins/active_model.rb
|
222
227
|
- lib/mobility/plugins/active_model/dirty.rb
|
223
228
|
- lib/mobility/plugins/active_record.rb
|
229
|
+
- lib/mobility/plugins/active_record/attribute_methods.rb
|
224
230
|
- lib/mobility/plugins/active_record/dirty.rb
|
231
|
+
- lib/mobility/plugins/attribute_methods.rb
|
225
232
|
- lib/mobility/plugins/cache.rb
|
226
233
|
- lib/mobility/plugins/cache/translation_cacher.rb
|
227
234
|
- lib/mobility/plugins/default.rb
|
metadata.gz.sig
CHANGED
Binary file
|
@@ -1,36 +0,0 @@
|
|
1
|
-
module Mobility
|
2
|
-
module ActiveRecord
|
3
|
-
=begin
|
4
|
-
|
5
|
-
Included into model if model has +ActiveRecord::AttributeMethods+ among its
|
6
|
-
ancestors.
|
7
|
-
|
8
|
-
=end
|
9
|
-
module AttributeMethods
|
10
|
-
delegate :translated_attribute_names, to: :class
|
11
|
-
|
12
|
-
# Adds translated attributes to +attributes+.
|
13
|
-
# @return [Array<String>] Model attributes
|
14
|
-
# @!method attributes
|
15
|
-
def self.included(model)
|
16
|
-
attributes_method = Module.new do
|
17
|
-
def attributes
|
18
|
-
super.merge(translated_attributes)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
model.class_eval do
|
22
|
-
alias_method :untranslated_attributes, :attributes
|
23
|
-
include attributes_method
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
# Translated attributes defined on model.
|
28
|
-
# @return [Array<String>] Translated attributes
|
29
|
-
def translated_attributes
|
30
|
-
translated_attribute_names.inject({}) do |attributes, name|
|
31
|
-
attributes.merge(name.to_s => send(name))
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|