mobility 0.8.10 → 1.0.0.beta2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/CHANGELOG.md +66 -0
  5. data/Gemfile +50 -18
  6. data/Gemfile.lock +36 -101
  7. data/README.md +183 -91
  8. data/Rakefile +6 -4
  9. data/lib/mobility.rb +44 -166
  10. data/lib/mobility/arel.rb +1 -1
  11. data/lib/mobility/arel/nodes/pg_ops.rb +1 -1
  12. data/lib/mobility/backend.rb +27 -51
  13. data/lib/mobility/backends.rb +20 -0
  14. data/lib/mobility/backends/active_record.rb +4 -0
  15. data/lib/mobility/backends/active_record/column.rb +2 -0
  16. data/lib/mobility/backends/active_record/container.rb +6 -7
  17. data/lib/mobility/backends/active_record/hstore.rb +3 -1
  18. data/lib/mobility/backends/active_record/json.rb +2 -0
  19. data/lib/mobility/backends/active_record/jsonb.rb +2 -0
  20. data/lib/mobility/backends/active_record/key_value.rb +6 -4
  21. data/lib/mobility/backends/active_record/pg_hash.rb +1 -1
  22. data/lib/mobility/backends/active_record/serialized.rb +6 -0
  23. data/lib/mobility/backends/active_record/table.rb +6 -4
  24. data/lib/mobility/backends/column.rb +0 -6
  25. data/lib/mobility/backends/container.rb +10 -1
  26. data/lib/mobility/backends/hash.rb +39 -0
  27. data/lib/mobility/backends/hash_valued.rb +4 -0
  28. data/lib/mobility/backends/hstore.rb +0 -1
  29. data/lib/mobility/backends/json.rb +0 -1
  30. data/lib/mobility/backends/jsonb.rb +1 -2
  31. data/lib/mobility/backends/key_value.rb +31 -26
  32. data/lib/mobility/backends/null.rb +2 -0
  33. data/lib/mobility/backends/sequel.rb +5 -2
  34. data/lib/mobility/backends/sequel/column.rb +2 -0
  35. data/lib/mobility/backends/sequel/container.rb +6 -6
  36. data/lib/mobility/backends/sequel/hstore.rb +3 -1
  37. data/lib/mobility/backends/sequel/json.rb +3 -0
  38. data/lib/mobility/backends/sequel/jsonb.rb +3 -1
  39. data/lib/mobility/backends/sequel/key_value.rb +8 -6
  40. data/lib/mobility/backends/sequel/serialized.rb +6 -0
  41. data/lib/mobility/backends/sequel/table.rb +5 -2
  42. data/lib/mobility/backends/serialized.rb +1 -3
  43. data/lib/mobility/backends/table.rb +29 -26
  44. data/lib/mobility/pluggable.rb +56 -0
  45. data/lib/mobility/plugin.rb +260 -0
  46. data/lib/mobility/plugins.rb +27 -24
  47. data/lib/mobility/plugins/active_model.rb +17 -0
  48. data/lib/mobility/plugins/active_model/cache.rb +26 -0
  49. data/lib/mobility/plugins/active_model/dirty.rb +119 -78
  50. data/lib/mobility/plugins/active_record.rb +34 -0
  51. data/lib/mobility/plugins/active_record/backend.rb +25 -0
  52. data/lib/mobility/plugins/active_record/cache.rb +28 -0
  53. data/lib/mobility/plugins/active_record/dirty.rb +34 -17
  54. data/lib/mobility/plugins/active_record/query.rb +48 -34
  55. data/lib/mobility/plugins/active_record/uniqueness_validation.rb +60 -0
  56. data/lib/mobility/plugins/attribute_methods.rb +29 -20
  57. data/lib/mobility/plugins/attributes.rb +72 -0
  58. data/lib/mobility/plugins/backend.rb +161 -0
  59. data/lib/mobility/plugins/backend_reader.rb +34 -0
  60. data/lib/mobility/plugins/cache.rb +68 -26
  61. data/lib/mobility/plugins/default.rb +22 -17
  62. data/lib/mobility/plugins/dirty.rb +12 -33
  63. data/lib/mobility/plugins/fallbacks.rb +52 -44
  64. data/lib/mobility/plugins/fallthrough_accessors.rb +25 -25
  65. data/lib/mobility/plugins/locale_accessors.rb +22 -35
  66. data/lib/mobility/plugins/presence.rb +28 -21
  67. data/lib/mobility/plugins/query.rb +8 -17
  68. data/lib/mobility/plugins/reader.rb +50 -0
  69. data/lib/mobility/plugins/sequel.rb +34 -0
  70. data/lib/mobility/plugins/sequel/backend.rb +25 -0
  71. data/lib/mobility/plugins/sequel/cache.rb +24 -0
  72. data/lib/mobility/plugins/sequel/dirty.rb +33 -22
  73. data/lib/mobility/plugins/sequel/query.rb +21 -6
  74. data/lib/mobility/plugins/writer.rb +44 -0
  75. data/lib/mobility/translations.rb +95 -0
  76. data/lib/mobility/version.rb +12 -1
  77. data/lib/rails/generators/mobility/templates/initializer.rb +96 -78
  78. metadata +28 -27
  79. metadata.gz.sig +0 -0
  80. data/lib/mobility/active_model.rb +0 -4
  81. data/lib/mobility/active_model/backend_resetter.rb +0 -26
  82. data/lib/mobility/active_record.rb +0 -23
  83. data/lib/mobility/active_record/backend_resetter.rb +0 -26
  84. data/lib/mobility/active_record/uniqueness_validator.rb +0 -60
  85. data/lib/mobility/attributes.rb +0 -324
  86. data/lib/mobility/backend/orm_delegator.rb +0 -44
  87. data/lib/mobility/backend_resetter.rb +0 -50
  88. data/lib/mobility/configuration.rb +0 -138
  89. data/lib/mobility/fallbacks.rb +0 -28
  90. data/lib/mobility/interface.rb +0 -0
  91. data/lib/mobility/loaded.rb +0 -4
  92. data/lib/mobility/plugins/active_record/attribute_methods.rb +0 -38
  93. data/lib/mobility/plugins/cache/translation_cacher.rb +0 -40
  94. data/lib/mobility/sequel.rb +0 -9
  95. data/lib/mobility/sequel/backend_resetter.rb +0 -23
  96. data/lib/mobility/translates.rb +0 -73
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dd8355a959c296a84759983153fc1233f69aa78cc78228b4b20f0f467372da3d
4
- data.tar.gz: 58da1ee48b36cd40c2e1b12edfea91ab22034090c57638f301908dcebf3f9145
3
+ metadata.gz: 2346e4ef46985b520c5feea3577a6644f213e1fe89e3dfd5960f3347c72a1134
4
+ data.tar.gz: df38726f94dca7139a3eb9cf838b27dfede5378c34290a5298e7dcde01bf3c90
5
5
  SHA512:
6
- metadata.gz: bcf5520b40769d00e0a848f6a18865c74ec3a48b74a83c421ad5bca89e19e9ccb86e66b6d7538e57f88a44737bc9bcc0b122f3fa4d1659a0a596c21237b4e1f6
7
- data.tar.gz: 12b2ea52538025521a472c9f1b03cc165e677534e559174076a1c6142a6f53b81406636d52715dab7c3aa91fdc16644f1f6e8e61739631e9f841a105cfa1394f
6
+ metadata.gz: 236ad0894645f98bf2a21c6848b4ba439da84b24862a56f6fca878889a6cd9a79108711923961d2f9ee75b6a6ee8482fcefff213b5433736fa507332db0cc253
7
+ data.tar.gz: a3e78f97d08d26e18ac8187b961097e686c3fc5650f45ae84fb4aa1aad1ccd0970410f2b9e887d8618ed6c1a09e559b1fe3fd0428df591de011961a0c2da1379
Binary file
data.tar.gz.sig CHANGED
Binary file
@@ -1,7 +1,73 @@
1
1
  # Mobility Changelog
2
2
 
3
+ ## 1.0
4
+
5
+ 1.0 is a rewrite of many internals of the gem. Please see the [wiki page on v1.0](https://github.com/shioyama/mobility/wiki/Introduction-to-Mobility-v1.0) for more details on how to upgrade.
6
+
7
+ ## 1.0.0.beta2 (pre-release)
8
+
9
+ - Refactor attributes & backend plugins and make `mobility_attributes` public
10
+ ([#462](https://github.com/shioyama/mobility/pull/462))
11
+ - Make attribute_methods plugin depend on attributes
12
+ ([#461](https://github.com/shioyama/mobility/pull/461))
13
+
14
+ ## 1.0.0.beta1 (pre-release)
15
+
16
+ - Remove `Mobility::Backend#apply_plugin`
17
+ ([#454](https://github.com/shioyama/mobility/pull/454))
18
+ - Instance exec configure block if it takes no arguments
19
+ ([#456](https://github.com/shioyama/mobility/pull/456))
20
+ - Raise an exception if invalid options are passed to Translations initializer
21
+ ([#457](https://github.com/shioyama/mobility/pull/457/files))
22
+ - Fix Ruby 2.7 deprecation warnings
23
+ ([#460](https://github.com/shioyama/mobility/pull/460))
24
+
25
+ ## 1.0.0.alpha (pre-release)
26
+
27
+ - Default fallbacks plugin to `true` when enabled
28
+ ([#447](https://github.com/shioyama/mobility/pull/447))
29
+ - Remove `Mobility::Backend.method_name`
30
+ ([#400](https://github.com/shioyama/mobility/pull/400))
31
+ - Remove `translated_attribute_names` as alias for `mobility_attributes`
32
+ ([#402](https://github.com/shioyama/mobility/pull/402))
33
+ - Move `_backend` methods into `backend_reader` plugin
34
+ ([#403](https://github.com/shioyama/mobility/pull/403))
35
+ - Replace `Configuration#query_method` configuration with Query plugin option
36
+ ([#414](https://github.com/shioyama/mobility/pull/414))
37
+ - Remove `Mobility::Configuration#default_accessor_locales`. Use plugin option
38
+ to configure global default instead.
39
+ ([#424](https://github.com/shioyama/mobility/pull/424))
40
+ - Pass `model_class` to `Mobility::Backend#configure` via class method rather
41
+ than on options hash ([#429](https://github.com/shioyama/mobility/pull/429))
42
+ - Remove `Mobility.new_fallbacks` and `Configuration#fallbacks_generator`
43
+ ([#433](https://github.com/shioyama/mobility/pull/433))
44
+ - Rename `backend_name` to `backend`
45
+ ([#443](https://github.com/shioyama/mobility/pull/443))
46
+ - Remove `Configuration#accessor_method`
47
+ ([#450](https://github.com/shioyama/mobility/pull/450))
48
+ - Rename `Mobility::Attributes` to `Mobility::Translations`
49
+ - Remove `Mobility::Configuration` altogether
50
+ ([#452](https://github.com/shioyama/mobility/pull/452))
51
+
3
52
  ## 0.8
4
53
 
54
+ ### 0.8.13 (May 27, 2020)
55
+
56
+ * Fix fallthrough accessor method_missing not passing all options to super
57
+ ([#364](https://github.com/shioyama/mobility/pull/364),
58
+ [#384](https://github.com/shioyama/mobility/pull/384),
59
+ [#377](https://github.com/shioyama/mobility/pull/377), thanks
60
+ [doits](https://github.com/doits)!)
61
+
62
+ ### 0.8.12 (May 15, 2020)
63
+
64
+ (yanked)
65
+
66
+ ### 0.8.11 (May 14, 2020)
67
+ * Handle select with block
68
+ ([#359](https://github.com/shioyama/mobility/pull/359), thanks
69
+ [dlcmh](https://github.com/dlcmh)!)
70
+
5
71
  ### 0.8.10 (February 11, 2020)
6
72
  * Enforce case_sensitive comparison for Rails 6.1
7
73
  ([#333](https://github.com/shioyama/mobility/pull/333), thanks [morozRed](https://github.com/morozRed)!)
data/Gemfile CHANGED
@@ -3,41 +3,73 @@ source 'https://rubygems.org'
3
3
  # Specify your gem's dependencies in mobility.gemspec
4
4
  gemspec
5
5
 
6
+ orm, orm_version = ENV['ORM'], ENV['ORM_VERSION']
7
+
6
8
  group :development, :test do
7
- if ENV['ORM'] == 'active_record'
8
- if ENV['RAILS_VERSION'] == '5.0'
9
- gem 'activerecord', '>= 5.0', '< 5.1'
10
- elsif ENV['RAILS_VERSION'] == '4.2'
9
+ case orm
10
+ when 'active_record'
11
+ orm_version ||= '6.0'
12
+ case orm_version
13
+ when '4.2'
11
14
  gem 'activerecord', '>= 4.2.6', '< 5.0'
12
- elsif ENV['RAILS_VERSION'] == '5.1'
15
+ when '5.0'
16
+ gem 'activerecord', '>= 5.0', '< 5.1'
17
+ when '5.1'
13
18
  gem 'activerecord', '>= 5.1', '< 5.2'
14
- elsif ENV['RAILS_VERSION'] == '5.2'
19
+ when '5.2'
15
20
  gem 'activerecord', '>= 5.2.0', '< 5.3'
16
21
  gem 'railties', '>= 5.2.0.rc2', '< 5.3'
17
- else # Default is Rails 6.0
22
+ when '6.0'
18
23
  gem 'activerecord', '>= 6.0.0', '< 6.1'
24
+ when '6.1'
25
+ git 'https://github.com/rails/rails.git' do
26
+ gem 'activerecord'
27
+ gem 'activesupport'
28
+ end
29
+ else
30
+ raise ArgumentError, 'Invalid ActiveRecord version'
19
31
  end
20
- gem "generator_spec", '~> 0.9.4'
21
- elsif ENV['ORM'] == 'sequel'
22
- if ENV['SEQUEL_VERSION'] == '4'
32
+ when 'sequel'
33
+ orm_version ||= '5'
34
+ case orm_version
35
+ when '4'
23
36
  gem 'sequel', '>= 4.46.0', '< 5.0'
24
- else
37
+ when '5'
25
38
  gem 'sequel', '>= 5.0.0', '< 6.0.0'
39
+ else
40
+ raise ArgumentError, 'Invalid Sequel version'
26
41
  end
42
+ when nil, ''
43
+ else
44
+ raise ArgumentError, "Invalid ORM: #{orm}"
27
45
  end
28
46
 
29
- gem 'allocation_stats' if ENV['TEST_PERFORMANCE']
47
+ gem 'allocation_stats' if ENV['FEATURE'] == 'performance'
48
+
49
+ if ENV['FEATURE'] == 'rails'
50
+ gem 'rails'
51
+ gem 'generator_spec', '~> 0.9.4'
52
+ end
30
53
 
31
54
  platforms :ruby do
32
55
  gem 'guard-rspec'
33
56
  gem 'pry-byebug'
34
- if ENV['ORM'] == 'active_record' && ENV['RAILS_VERSION'] < '5.2'
35
- gem 'sqlite3', '~> 1.3.13'
36
- else
37
- gem 'sqlite3', '~> 1.4.1'
57
+ case ENV['DB']
58
+ when 'sqlite3'
59
+ if orm == 'active_record' && orm_version < '5.2'
60
+ gem 'sqlite3', '~> 1.3.13'
61
+ else
62
+ gem 'sqlite3', '~> 1.4.1'
63
+ end
64
+ when 'mysql'
65
+ gem 'mysql2'
66
+ when 'postgres'
67
+ if orm == 'active_record' && orm_version < '5.0'
68
+ gem 'pg', '< 1.0'
69
+ else
70
+ gem 'pg'
71
+ end
38
72
  end
39
- gem 'mysql2', '~> 0.4.9'
40
- gem 'pg', '< 1.0'
41
73
  end
42
74
  end
43
75
 
@@ -1,54 +1,22 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- mobility (1.0.alpha.1)
4
+ mobility (1.0.0.beta2)
5
5
  i18n (>= 0.6.10, < 2)
6
6
  request_store (~> 1.0)
7
7
 
8
8
  GEM
9
9
  remote: https://rubygems.org/
10
10
  specs:
11
- actionpack (4.2.11.1)
12
- actionview (= 4.2.11.1)
13
- activesupport (= 4.2.11.1)
14
- rack (~> 1.6)
15
- rack-test (~> 0.6.2)
16
- rails-dom-testing (~> 1.0, >= 1.0.5)
17
- rails-html-sanitizer (~> 1.0, >= 1.0.2)
18
- actionview (4.2.11.1)
19
- activesupport (= 4.2.11.1)
20
- builder (~> 3.1)
21
- erubis (~> 2.7.0)
22
- rails-dom-testing (~> 1.0, >= 1.0.5)
23
- rails-html-sanitizer (~> 1.0, >= 1.0.3)
24
- activemodel (4.2.11.1)
25
- activesupport (= 4.2.11.1)
26
- builder (~> 3.1)
27
- activerecord (4.2.11.1)
28
- activemodel (= 4.2.11.1)
29
- activesupport (= 4.2.11.1)
30
- arel (~> 6.0)
31
- activesupport (4.2.11.1)
32
- i18n (~> 0.7)
33
- minitest (~> 5.1)
34
- thread_safe (~> 0.3, >= 0.3.4)
35
- tzinfo (~> 1.1)
36
- arel (6.0.4)
37
- benchmark-ips (2.7.2)
38
- builder (3.2.3)
39
- byebug (11.0.1)
40
- coderay (1.1.2)
41
- concurrent-ruby (1.1.5)
42
- crass (1.0.5)
43
- database_cleaner (1.7.0)
44
- diff-lcs (1.3)
45
- erubis (2.7.0)
46
- ffi (1.11.1)
11
+ benchmark-ips (2.8.3)
12
+ byebug (11.1.3)
13
+ coderay (1.1.3)
14
+ concurrent-ruby (1.1.7)
15
+ database_cleaner (1.8.5)
16
+ diff-lcs (1.4.4)
17
+ ffi (1.13.1)
47
18
  formatador (0.2.5)
48
- generator_spec (0.9.4)
49
- activesupport (>= 3.0.0)
50
- railties (>= 3.0.0)
51
- guard (2.15.1)
19
+ guard (2.16.2)
52
20
  formatador (>= 0.2.4)
53
21
  listen (>= 2.7, < 4.0)
54
22
  lumberjack (>= 1.0.12, < 2.0)
@@ -62,92 +30,59 @@ GEM
62
30
  guard (~> 2.1)
63
31
  guard-compat (~> 1.1)
64
32
  rspec (>= 2.99.0, < 4.0)
65
- i18n (0.9.5)
33
+ i18n (1.8.5)
66
34
  concurrent-ruby (~> 1.0)
67
- listen (3.2.0)
35
+ listen (3.2.1)
68
36
  rb-fsevent (~> 0.10, >= 0.10.3)
69
37
  rb-inotify (~> 0.9, >= 0.9.10)
70
- loofah (2.3.1)
71
- crass (~> 1.0.2)
72
- nokogiri (>= 1.5.9)
73
- lumberjack (1.0.13)
74
- method_source (0.9.2)
75
- mini_portile2 (2.4.0)
76
- minitest (5.12.2)
77
- mysql2 (0.4.10)
38
+ lumberjack (1.2.8)
39
+ method_source (1.0.0)
78
40
  nenv (0.3.0)
79
- nokogiri (1.10.4)
80
- mini_portile2 (~> 2.4.0)
81
41
  notiffany (0.1.3)
82
42
  nenv (~> 0.1)
83
43
  shellany (~> 0.0)
84
- pg (0.21.0)
85
- pry (0.12.2)
86
- coderay (~> 1.1.0)
87
- method_source (~> 0.9.0)
88
- pry-byebug (3.7.0)
44
+ pry (0.13.1)
45
+ coderay (~> 1.1)
46
+ method_source (~> 1.0)
47
+ pry-byebug (3.9.0)
89
48
  byebug (~> 11.0)
90
- pry (~> 0.10)
91
- rack (1.6.11)
92
- rack-test (0.6.3)
93
- rack (>= 1.0)
94
- rails-deprecated_sanitizer (1.0.3)
95
- activesupport (>= 4.2.0.alpha)
96
- rails-dom-testing (1.0.9)
97
- activesupport (>= 4.2.0, < 5.0)
98
- nokogiri (~> 1.6)
99
- rails-deprecated_sanitizer (>= 1.0.1)
100
- rails-html-sanitizer (1.3.0)
101
- loofah (~> 2.3)
102
- railties (4.2.11.1)
103
- actionpack (= 4.2.11.1)
104
- activesupport (= 4.2.11.1)
105
- rake (>= 0.8.7)
106
- thor (>= 0.18.1, < 2.0)
49
+ pry (~> 0.13.0)
50
+ rack (2.2.3)
107
51
  rake (12.3.3)
108
- rb-fsevent (0.10.3)
109
- rb-inotify (0.10.0)
52
+ rb-fsevent (0.10.4)
53
+ rb-inotify (0.10.1)
110
54
  ffi (~> 1.0)
111
- request_store (1.4.1)
55
+ request_store (1.5.0)
112
56
  rack (>= 1.4)
113
- rspec (3.9.0)
114
- rspec-core (~> 3.9.0)
115
- rspec-expectations (~> 3.9.0)
116
- rspec-mocks (~> 3.9.0)
117
- rspec-core (3.9.0)
118
- rspec-support (~> 3.9.0)
119
- rspec-expectations (3.9.0)
57
+ rspec (3.10.0)
58
+ rspec-core (~> 3.10.0)
59
+ rspec-expectations (~> 3.10.0)
60
+ rspec-mocks (~> 3.10.0)
61
+ rspec-core (3.10.0)
62
+ rspec-support (~> 3.10.0)
63
+ rspec-expectations (3.10.0)
120
64
  diff-lcs (>= 1.2.0, < 2.0)
121
- rspec-support (~> 3.9.0)
122
- rspec-mocks (3.9.0)
65
+ rspec-support (~> 3.10.0)
66
+ rspec-mocks (3.10.0)
123
67
  diff-lcs (>= 1.2.0, < 2.0)
124
- rspec-support (~> 3.9.0)
125
- rspec-support (3.9.0)
68
+ rspec-support (~> 3.10.0)
69
+ rspec-support (3.10.0)
126
70
  shellany (0.0.1)
127
- sqlite3 (1.3.13)
128
- thor (0.20.3)
129
- thread_safe (0.3.6)
130
- tzinfo (1.2.5)
131
- thread_safe (~> 0.1)
132
- yard (0.9.20)
71
+ thor (1.0.1)
72
+ yard (0.9.25)
133
73
 
134
74
  PLATFORMS
135
75
  ruby
136
76
 
137
77
  DEPENDENCIES
138
- activerecord (>= 4.2.6, < 5.0)
139
78
  benchmark-ips
140
79
  database_cleaner (~> 1.5, >= 1.5.3)
141
- generator_spec (~> 0.9.4)
142
80
  guard-rspec
143
81
  mobility!
144
- mysql2 (~> 0.4.9)
145
- pg (< 1.0)
146
82
  pry-byebug
147
83
  rake (~> 12, >= 12.2.1)
148
84
  rspec (~> 3.0)
149
- sqlite3 (~> 1.3.13)
150
85
  yard (~> 0.9.0)
151
86
 
152
87
  BUNDLED WITH
153
- 1.17.3
88
+ 2.1.4
data/README.md CHANGED
@@ -2,16 +2,22 @@ Mobility
2
2
  ========
3
3
 
4
4
  [![Gem Version](https://badge.fury.io/rb/mobility.svg)][gem]
5
- [![Build Status](https://travis-ci.org/shioyama/mobility.svg?branch=master)][travis]
5
+ [![Build Status](https://github.com/shioyama/mobility/workflows/CI/badge.svg)][actions]
6
6
  [![Code Climate](https://api.codeclimate.com/v1/badges/72200f2b00c339ec4537/maintainability.svg)][codeclimate]
7
7
  [![Gitter Chat](https://badges.gitter.im/mobility-ruby/mobility.svg)](https://gitter.im/mobility-ruby/mobility)
8
8
 
9
9
  [gem]: https://rubygems.org/gems/mobility
10
- [travis]: https://travis-ci.org/shioyama/mobility
10
+ [actions]: https://github.com/shioyama/mobility/actions
11
11
  [codeclimate]: https://codeclimate.com/github/shioyama/mobility
12
12
  [docs]: http://www.rubydoc.info/gems/mobility
13
13
  [wiki]: https://github.com/shioyama/mobility/wiki
14
14
 
15
+ **This is the readme for the [`master`](https://github.com/shioyama/mobility)
16
+ branch, which corresponds to v1.0.0.beta, a pre-release version of Mobility.
17
+ If you are using an earlier version (0.8.x or earlier), you probably want the
18
+ readme on the [0-8-stable
19
+ branch](https://github.com/shioyama/mobility/tree/0-8-stable).**
20
+
15
21
  Mobility is a gem for storing and retrieving translations as attributes on a
16
22
  class. These translations could be the content of blog posts, captions on
17
23
  images, tags on bookmarks, or anything else you might want to store in
@@ -36,10 +42,10 @@ and [Sequel](http://sequel.jeremyevans.net/) ORM, with support for other
36
42
  platforms planned.
37
43
 
38
44
  For a detailed introduction to Mobility, see [Translating with
39
- Mobility](http://dejimata.com/2017/3/3/translating-with-mobility). See also the
40
- [Roadmap](https://github.com/shioyama/mobility/wiki/Roadmap) for what's in the
41
- works for future releases, and other pages of the [wiki][wiki] for more detail
42
- on usage.
45
+ Mobility](http://dejimata.com/2017/3/3/translating-with-mobility). See also my
46
+ talk at RubyConf 2018, [Building Generic
47
+ Software](https://www.youtube.com/watch?v=RZkemV_-__A), where I explain the
48
+ thinking behind Mobility's design.
43
49
 
44
50
  If you're coming from Globalize, be sure to also read the [Migrating from
45
51
  Globalize](https://github.com/shioyama/mobility/wiki/Migrating-from-Globalize)
@@ -48,22 +54,15 @@ section of the wiki.
48
54
  Installation
49
55
  ------------
50
56
 
51
- Add this line to your application's Gemfile:
57
+ To use the latest pre-version of Mobility 1.0, add this line to your
58
+ application's Gemfile:
52
59
 
53
60
  ```ruby
54
- gem 'mobility', '~> 0.8.10'
55
- ```
56
-
57
- Mobility is cryptographically signed. To be sure the gem you install hasn't
58
- been tampered with, add my public key as a trusted certificate and install:
59
-
60
- ```
61
- gem cert --add <(curl -Ls https://raw.github.com/shioyama/mobility/master/certs/shioyama.pem)
62
- gem install mobility -P MediumSecurity
61
+ gem 'mobility', '~> 1.0.0.beta2'
63
62
  ```
64
63
 
65
- The MediumSecurity trust profile will verify signed gems, but allow the
66
- installation of unsigned dependencies.
64
+ For the latest stable version of Mobility, see the readme on the
65
+ [0-8-stable](https://github.com/shioyama/mobility/tree/0-8-stable) branch.
67
66
 
68
67
  ### ActiveRecord (Rails)
69
68
 
@@ -72,7 +71,7 @@ Requirements:
72
71
 
73
72
  (Support for most backends and features is also supported with
74
73
  ActiveRecord/Rails 4.2, but there are some tests still failing. To see exactly
75
- what might not work, check pending specs in Rails 4.2 Travis builds.)
74
+ what might not work, check pending specs in Rails 4.2 builds.)
76
75
 
77
76
  To translate attributes on a model, extend `Mobility`, then call `translates`
78
77
  passing in one or more attributes as well as a hash of options (see below).
@@ -89,36 +88,52 @@ rails generate mobility:install
89
88
  the `--without_tables` option here to skip the migration generation.)
90
89
 
91
90
  The generator will create an initializer file `config/initializers/mobility.rb`
92
- with the lines:
91
+ which looks something like this:
93
92
 
94
93
  ```ruby
95
94
  Mobility.configure do |config|
96
- config.default_backend = :key_value
97
- config.accessor_method = :translates
98
- config.query_method = :i18n
95
+ # PLUGINS
96
+
97
+ config.plugins do
98
+ backend :key_value
99
+
100
+ active_record
101
+
102
+ reader
103
+ writer
104
+
105
+ # ...
106
+ end
99
107
  end
100
108
  ```
101
109
 
102
- To use a different default backend, set `default_backend` to another value (see
103
- possibilities [below](#backends)).
110
+ Each method call inside the block passed to `config.plugins` declares a plugin,
111
+ along with an optional default. To use a different default backend, you can
112
+ change the default passed to the `backend` plugin, like this:
113
+
114
+ ```diff
115
+ Mobility.configure do |config|
116
+ # PLUGINS
117
+
118
+ config.plugins do
119
+ - backend :key_value
120
+ + backend :table
121
+ ```
104
122
 
105
- You will likely also want to set default values for the various translation
106
- options described below. You can set these defaults by assigning values to keys
107
- on the `config.default_options` hash. Below, we turn on the Dirty plugin by
108
- default, so it will be enabled for all models.
123
+ See other possible backends in the [backends section](#backends).
109
124
 
110
125
  You can also set defaults for backend-specific options. Below, we set the
111
- default `type` option for the KeyValue backend to `:string` (this is
112
- unnecessary and will be ignored if you are using a different backend).
126
+ default `type` option for the KeyValue backend to `:string`.
113
127
 
114
128
  ```diff
115
129
  Mobility.configure do |config|
116
- config.default_backend = :key_value
117
- config.accessor_method = :translates
118
- config.query_method = :i18n
119
- + config.default_options[:dirty] = true
120
- + config.default_options[:type] = :string
121
- end
130
+ # PLUGINS
131
+
132
+ config.plugins do
133
+ - backend :key_value
134
+ + backend :key_value, type: :string
135
+ end
136
+ end
122
137
  ```
123
138
 
124
139
  We will assume the configuration above in the examples that follow. Other
@@ -132,6 +147,16 @@ See [Getting Started](#quickstart) to get started translating your models.
132
147
  Requirements:
133
148
  - Sequel >= 4.0
134
149
 
150
+ When configuring Mobility, ensure that you include the `sequel` plugin:
151
+
152
+ ```diff
153
+ config.plugins do
154
+ backend :key_value
155
+
156
+ - active_record
157
+ + sequel
158
+ ```
159
+
135
160
  You can extend `Mobility` just like in ActiveRecord, or you can use the
136
161
  `mobility` plugin, which does the same thing:
137
162
 
@@ -143,8 +168,8 @@ end
143
168
  ```
144
169
 
145
170
  Otherwise everything is (almost) identical to AR, with the exception that there
146
- is no equivalent to a Rails generator (so you will need to create the migration
147
- for any translation table(s) yourself, using Rails generators as a reference).
171
+ is no equivalent to a Rails generator, so you will need to create the migration
172
+ for any translation table(s) yourself, using Rails generators as a reference.
148
173
 
149
174
  The models in examples below all inherit from `ApplicationRecord`, but
150
175
  everything works exactly the same if the parent class is `Sequel::Model`.
@@ -259,15 +284,25 @@ changed and/or customized (see the [Backends](#backends) section below).
259
284
  ### <a name="getset"></a> Getting and Setting Translations
260
285
 
261
286
  The easiest way to get or set a translation is to use the getter and setter
262
- methods described above (`word.name` and `word.name=`), but you may want to
263
- access the value of an attribute in a specific locale, independent of the
264
- current value of `I18n.locale` (or `Mobility.locale`). There are a few ways to
265
- do this.
287
+ methods described above (`word.name` and `word.name=`), enabled by including
288
+ the `reader` and `writer` plugins.
289
+
290
+ You may also want to access the value of an attribute in a specific locale,
291
+ independent of the current value of `I18n.locale` (or `Mobility.locale`). There
292
+ are a few ways to do this.
266
293
 
267
294
  The first way is to define locale-specific methods, one for each locale you
268
295
  want to access directly on a given attribute. These are called "locale
269
- accessors" in Mobility, and they can be defined by passing a `locale_accessors`
270
- option when defining translated attributes on the model class:
296
+ accessors" in Mobility, and can be enabled by including the `locale_accessors`
297
+ plugin, with a default set of accessors:
298
+
299
+ ```diff
300
+ config.plugins do
301
+ # ...
302
+ + locale_accessors [:en, :ja]
303
+ ```
304
+
305
+ You can also override this default from `translates` in any model:
271
306
 
272
307
  ```ruby
273
308
  class Word < ApplicationRecord
@@ -296,24 +331,23 @@ word.name_ru
296
331
  #=> NoMethodError: undefined method `name_ru' for #<Word id: ... >
297
332
  ```
298
333
 
299
- To generate methods for all locales in `I18n.available_locales` (at the time
300
- the model is first loaded), use `locale_accessors: true`.
334
+ With no plugin option (or a default of `true`), Mobility generates methods for
335
+ all locales in `I18n.available_locales` at the time the model is first loaded.
301
336
 
302
- An alternative to using the `locale_accessors` option is to use the
303
- `fallthrough_accessors` option, with `fallthrough_accessors: true`. This uses
304
- Ruby's [`method_missing`](http://apidock.com/ruby/BasicObject/method_missing)
305
- method to implicitly define the same methods as above, but supporting any
306
- locale without any method definitions. (Locale accessors and fallthrough
307
- locales can be used together without conflict, with locale accessors taking
308
- precedence if defined for a given locale.)
337
+ An alternative to using the `locale_accessors` plugin is to use the
338
+ `fallthrough_accessors` plugin. This uses Ruby's
339
+ [`method_missing`](http://apidock.com/ruby/BasicObject/method_missing) method
340
+ to implicitly define the same methods as above, but supporting any locale
341
+ without any method definitions. (Locale accessors and fallthrough locales can
342
+ be used together without conflict, with locale accessors taking precedence if
343
+ defined for a given locale.)
309
344
 
310
- For example, if we define `Word` this way:
345
+ Ensure the plugin is enabled:
311
346
 
312
- ```ruby
313
- class Word < ApplicationRecord
314
- extend Mobility
315
- translates :name, fallthrough_accessors: true
316
- end
347
+ ```diff
348
+ config.plugins do
349
+ # ...
350
+ + fallthrough_accessors
317
351
  ```
318
352
 
319
353
  ... then we can access any locale we want, without specifying them upfront:
@@ -374,11 +408,24 @@ word.name_backend.read(:en)
374
408
  ```
375
409
 
376
410
  Internally, all methods for accessing translated attributes ultimately end up
377
- reading and writing from the backend instance this way.
411
+ reading and writing from the backend instance this way. (The `write` methods
412
+ do not call underlying backend's methods to persist the change. This is up to
413
+ the user, so e.g. with ActiveRecord you should call `save` write the changes to
414
+ the database).
378
415
 
379
- The `write` methods do not call underlying backend's methods to persist the change.
380
- This is up to the user (e.g. with ActiveRecord you should call `save` write
381
- the changes to the database).
416
+ Note that accessor methods are defined in an included module, so you can wrap
417
+ reads or writes in custom logic:
418
+
419
+ ```ruby
420
+ class Post < ApplicationRecord
421
+ extend Mobility
422
+ translates :title
423
+
424
+ def title(*)
425
+ super.reverse
426
+ end
427
+ end
428
+ ```
382
429
 
383
430
  ### Setting the Locale
384
431
 
@@ -419,15 +466,28 @@ details on how to configure it for your use case.
419
466
 
420
467
  ### <a name="fallbacks"></a>Fallbacks
421
468
 
422
- Mobility offers basic support for translation fallbacks. To enable fallbacks,
423
- pass a hash with fallbacks for each locale as an option when defining
469
+ Mobility offers basic support for translation fallbacks. First, enable the
470
+ `fallbacks` plugin:
471
+
472
+ ```diff
473
+ config.plugins do
474
+ # ...
475
+ + fallbacks
476
+ + locale_accessors
477
+ ```
478
+
479
+ Fallbacks will require `fallthrough_accessors` to handle methods like
480
+ `title_en`, which are used to track changes. For performance reasons it's
481
+ generally best to also enable the `locale_accessors` plugin as shown above.
482
+
483
+ Now pass a hash with fallbacks for each locale as an option when defining
424
484
  translated attributes on a class:
425
485
 
426
486
  ```ruby
427
487
  class Word < ApplicationRecord
428
488
  extend Mobility
429
- translates :name, fallbacks: { de: :ja, fr: :ja }, locale_accessors: true
430
- translates :meaning, fallbacks: { de: :ja, fr: :ja }, locale_accessors: true
489
+ translates :name, fallbacks: { de: :ja, fr: :ja }
490
+ translates :meaning, fallbacks: { de: :ja, fr: :ja }
431
491
  end
432
492
  ```
433
493
 
@@ -516,7 +576,16 @@ fallbacks](https://github.com/svenfuchs/i18n/wiki/Fallbacks).
516
576
 
517
577
  ### <a name="default"></a>Default values
518
578
 
519
- Another option is to assign a default value, which will be used if the result of a fetch would otherwise be `nil`:
579
+ Another option is to assign a default value, using the `default` plugin:
580
+
581
+ ```diff
582
+ config.plugins do
583
+ # ...
584
+ + default 'foo'
585
+ ```
586
+
587
+ Here we've set a "default default" of `'foo'`, which will be returned if a fetch would
588
+ otherwise return `nil`. This can be overridden from model classes:
520
589
 
521
590
  ```ruby
522
591
  class Word < ApplicationRecord
@@ -558,24 +627,29 @@ support it. Currently this is models which include
558
627
  [dirty](http://sequel.jeremyevans.net/rdoc-plugins/classes/Sequel/Plugins/Dirty.html)
559
628
  plugin).
560
629
 
561
- Enabling dirty tracking is as simple as sending the `dirty: true` option when
562
- defining a translated attribute. The way dirty tracking works is somewhat
563
- dependent on the model class (ActiveModel or Sequel); we will describe the
564
- ActiveModel implementation here.
630
+ First, ensure the `dirty` plugin is enabled in your configuration, and that you
631
+ have enabled an ORM plugin (either `active_record` or `sequel`), since the
632
+ dirty plugin will depend on one of these being enabled.
633
+
634
+ ```diff
635
+ config.plugins do
636
+ # ...
637
+ active_record
638
+ + dirty
639
+ ```
640
+
641
+ (Once enabled globally, the dirty plugin can be selectively disabled on classes
642
+ by passing `dirty: false` to `translates`.)
565
643
 
566
- First, enable dirty tracking (note that this is a persisted AR model, although
567
- dirty tracking is not specific to AR and works for non-persisted models as well):
644
+ Take this ActiveRecord class:
568
645
 
569
646
  ```ruby
570
647
  class Post < ApplicationRecord
571
648
  extend Mobility
572
- translates :title, dirty: true
649
+ translates :title
573
650
  end
574
651
  ```
575
652
 
576
- (If you want to enable dirty tracking on all models, set the
577
- `config.default_options[:dirty]` option in your Mobility configuration.)
578
-
579
653
  Let's assume we start with a post with a title in English and Japanese:
580
654
 
581
655
  ```ruby
@@ -637,9 +711,6 @@ For performance reasons, it is highly recommended that when using the Dirty
637
711
  plugin, you also enable [locale accessors](#getset) for all locales which will
638
712
  be used, so that methods like `title_en` above are defined; otherwise they will
639
713
  be caught by `method_missing` (using fallthrough accessors), which is much slower.
640
- The easiest way to do this is to set `config.default_options[:locale_accessors]
641
- = true` in your Mobility config, and make sure that `I18n.available_locales`
642
- includes all locales you use in production.
643
714
 
644
715
  For more details on dirty tracking, see the [API
645
716
  documentation](http://www.rubydoc.info/gems/mobility/Mobility/Plugins/Dirty).
@@ -647,9 +718,17 @@ documentation](http://www.rubydoc.info/gems/mobility/Mobility/Plugins/Dirty).
647
718
  ### Cache
648
719
 
649
720
  The Mobility cache caches localized values that have been fetched once so they
650
- can be quickly retrieved again. The cache is enabled by default and should
651
- generally only be disabled when debugging; this can be done by passing `cache:
652
- false` when defining an attribute, like this:
721
+ can be quickly retrieved again. The cache plugin is included in the default
722
+ configuration created by the install generator:
723
+
724
+ ```diff
725
+ config.plugins do
726
+ # ...
727
+ + cache
728
+ ```
729
+
730
+ It can be disabled selectively per model by passing `cache: false` when
731
+ defining an attribute, like this:
653
732
 
654
733
  ```ruby
655
734
  class Word < ApplicationRecord
@@ -659,7 +738,8 @@ end
659
738
  ```
660
739
 
661
740
  You can also turn off the cache for a single fetch by passing `cache: false` to
662
- the getter method, i.e. `post.title(cache: false)`.
741
+ the getter method, i.e. `post.title(cache: false)`. To remove the cache plugin
742
+ entirely, remove the `cache` line from the global plugins configuration.
663
743
 
664
744
  The cache is normally just a hash with locale keys and string (translation)
665
745
  values, but some backends (e.g. KeyValue and Table backends) have slightly more
@@ -667,11 +747,23 @@ complex implementations.
667
747
 
668
748
  ### <a name="querying"></a>Querying
669
749
 
670
- Mobility backends also support querying on translated attributes, in two
671
- different ways. The first is via query methods like `where` (and `not` and
672
- `find_by` in ActiveRecord, and `except` in Sequel). To query this way, use the
673
- `i18n` class method, which will return a model relation or dataset extended
674
- with Mobility-specific query method overrides.
750
+ Mobility backends also support querying on translated attributes. To enable
751
+ this feature, include the `query` plugin, and ensure you also have an ORM
752
+ plugin enabled (`active_record` or `sequel`):
753
+
754
+ ```diff
755
+ config.plugins do
756
+ # ...
757
+ active_record
758
+ + query
759
+ ```
760
+
761
+ Querying defines a scope or dataset class method, whose default name is `i18n`.
762
+ You can override this by passing a default in the configuration, like
763
+ `query :t` to use a name `t`.
764
+
765
+ Querying is supported in two different ways. The first is via query methods
766
+ like `where` (and `not` and `find_by` in ActiveRecord, and `except` in Sequel).
675
767
 
676
768
  So for ActiveRecord, assuming a model using KeyValue as its default backend:
677
769