mobility 0.1.20 → 0.2.0
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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +2 -0
- data/CHANGELOG.md +17 -0
- data/CONTRIBUTING.md +55 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +2 -56
- data/README.md +64 -15
- data/Rakefile +17 -17
- data/lib/mobility.rb +43 -40
- data/lib/mobility/active_model.rb +0 -1
- data/lib/mobility/active_model/backend_resetter.rb +1 -1
- data/lib/mobility/active_record.rb +8 -15
- data/lib/mobility/active_record/backend_resetter.rb +2 -0
- data/lib/mobility/active_record/model_translation.rb +1 -1
- data/lib/mobility/active_record/string_translation.rb +2 -0
- data/lib/mobility/active_record/text_translation.rb +2 -0
- data/lib/mobility/attributes.rb +74 -71
- data/lib/mobility/backend.rb +64 -25
- data/lib/mobility/backend/orm_delegator.rb +17 -7
- data/lib/mobility/backend/stringify_locale.rb +18 -0
- data/lib/mobility/backend_resetter.rb +8 -5
- data/lib/mobility/backends.rb +4 -0
- data/lib/mobility/backends/active_record.rb +20 -0
- data/lib/mobility/{backend → backends}/active_record/column.rb +25 -13
- data/lib/mobility/{backend → backends}/active_record/column/query_methods.rb +5 -3
- data/lib/mobility/backends/active_record/hstore.rb +29 -0
- data/lib/mobility/{backend → backends}/active_record/hstore/query_methods.rb +2 -2
- data/lib/mobility/{backend → backends}/active_record/jsonb.rb +6 -6
- data/lib/mobility/{backend → backends}/active_record/jsonb/query_methods.rb +4 -2
- data/lib/mobility/{backend → backends}/active_record/key_value.rb +10 -44
- data/lib/mobility/{backend → backends}/active_record/key_value/query_methods.rb +4 -2
- data/lib/mobility/{backend/active_record/hash_valued.rb → backends/active_record/pg_hash.rb} +13 -21
- data/lib/mobility/{backend → backends}/active_record/query_methods.rb +2 -2
- data/lib/mobility/{backend → backends}/active_record/serialized.rb +12 -28
- data/lib/mobility/{backend → backends}/active_record/serialized/query_methods.rb +5 -8
- data/lib/mobility/{backend → backends}/active_record/table.rb +11 -60
- data/lib/mobility/{backend → backends}/active_record/table/query_methods.rb +5 -3
- data/lib/mobility/{backend → backends}/column.rb +8 -4
- data/lib/mobility/backends/hash_valued.rb +29 -0
- data/lib/mobility/{backend → backends}/hstore.rb +4 -4
- data/lib/mobility/{backend → backends}/jsonb.rb +4 -4
- data/lib/mobility/backends/key_value.rb +111 -0
- data/lib/mobility/{backend → backends}/null.rb +4 -4
- data/lib/mobility/backends/sequel.rb +20 -0
- data/lib/mobility/backends/sequel/column.rb +52 -0
- data/lib/mobility/{backend → backends}/sequel/column/query_methods.rb +5 -3
- data/lib/mobility/backends/sequel/hstore.rb +29 -0
- data/lib/mobility/{backend → backends}/sequel/hstore/query_methods.rb +4 -3
- data/lib/mobility/{backend → backends}/sequel/jsonb.rb +6 -6
- data/lib/mobility/{backend → backends}/sequel/jsonb/query_methods.rb +4 -3
- data/lib/mobility/{backend → backends}/sequel/key_value.rb +28 -39
- data/lib/mobility/{backend → backends}/sequel/key_value/query_methods.rb +4 -5
- data/lib/mobility/backends/sequel/pg_hash.rb +46 -0
- data/lib/mobility/{backend → backends}/sequel/postgres_query_methods.rb +1 -2
- data/lib/mobility/{backend → backends}/sequel/query_methods.rb +6 -4
- data/lib/mobility/{backend → backends}/sequel/serialized.rb +17 -38
- data/lib/mobility/backends/sequel/serialized/query_methods.rb +17 -0
- data/lib/mobility/{backend → backends}/sequel/table.rb +29 -60
- data/lib/mobility/{backend → backends}/sequel/table/query_methods.rb +5 -3
- data/lib/mobility/{backend → backends}/serialized.rb +27 -5
- data/lib/mobility/{backend → backends}/table.rb +69 -29
- data/lib/mobility/configuration.rb +40 -0
- data/lib/mobility/{orm.rb → loaded.rb} +0 -0
- data/lib/mobility/plugins.rb +35 -0
- data/lib/mobility/plugins/active_model.rb +6 -0
- data/lib/mobility/plugins/active_model/dirty.rb +81 -0
- data/lib/mobility/plugins/active_record.rb +6 -0
- data/lib/mobility/plugins/active_record/dirty.rb +59 -0
- data/lib/mobility/plugins/cache.rb +54 -0
- data/lib/mobility/plugins/cache/translation_cacher.rb +40 -0
- data/lib/mobility/plugins/default.rb +73 -0
- data/lib/mobility/plugins/dirty.rb +61 -0
- data/lib/mobility/{backend → plugins}/fallbacks.rb +36 -31
- data/lib/mobility/plugins/fallthrough_accessors.rb +66 -0
- data/lib/mobility/plugins/locale_accessors.rb +84 -0
- data/lib/mobility/{backend → plugins}/presence.rb +15 -6
- data/lib/mobility/plugins/sequel.rb +6 -0
- data/lib/mobility/plugins/sequel/dirty.rb +59 -0
- data/lib/mobility/sequel.rb +5 -14
- data/lib/mobility/sequel/backend_resetter.rb +4 -6
- data/lib/mobility/sequel/column_changes.rb +4 -4
- data/lib/mobility/sequel/model_translation.rb +1 -1
- data/lib/mobility/sequel/string_translation.rb +2 -0
- data/lib/mobility/sequel/text_translation.rb +2 -0
- data/lib/mobility/translates.rb +1 -5
- data/lib/mobility/util.rb +126 -0
- data/lib/mobility/version.rb +1 -1
- data/lib/mobility/wrapper.rb +1 -1
- data/lib/rails/generators/mobility/translations_generator.rb +7 -3
- metadata +85 -55
- metadata.gz.sig +0 -0
- data/lib/mobility/backend/active_model.rb +0 -7
- data/lib/mobility/backend/active_model/dirty.rb +0 -95
- data/lib/mobility/backend/active_record.rb +0 -29
- data/lib/mobility/backend/active_record/dirty.rb +0 -54
- data/lib/mobility/backend/active_record/hstore.rb +0 -29
- data/lib/mobility/backend/cache.rb +0 -117
- data/lib/mobility/backend/dirty.rb +0 -38
- data/lib/mobility/backend/key_value.rb +0 -85
- data/lib/mobility/backend/sequel.rb +0 -29
- data/lib/mobility/backend/sequel/column.rb +0 -39
- data/lib/mobility/backend/sequel/dirty.rb +0 -57
- data/lib/mobility/backend/sequel/hash_valued.rb +0 -51
- data/lib/mobility/backend/sequel/hstore.rb +0 -29
- data/lib/mobility/backend/sequel/serialized/query_methods.rb +0 -20
- data/lib/mobility/core_ext/object.rb +0 -30
- data/lib/mobility/core_ext/string.rb +0 -16
- data/lib/mobility/fallthrough_accessors.rb +0 -57
- data/lib/mobility/locale_accessors.rb +0 -55
metadata.gz.sig
ADDED
|
Binary file
|
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
module Mobility
|
|
2
|
-
module Backend
|
|
3
|
-
=begin
|
|
4
|
-
|
|
5
|
-
Dirty tracking for models which include the +ActiveModel::Dirty+ module.
|
|
6
|
-
|
|
7
|
-
Assuming we have an attribute +title+, this module will add support for the
|
|
8
|
-
following methods:
|
|
9
|
-
- +title_changed?+
|
|
10
|
-
- +title_change+
|
|
11
|
-
- +title_was+
|
|
12
|
-
- +title_will_change!+
|
|
13
|
-
- +title_previously_changed?+
|
|
14
|
-
- +title_previous_change+
|
|
15
|
-
- +restore_title!+
|
|
16
|
-
|
|
17
|
-
In addition, the private method +restore_attribute!+ will also restore the
|
|
18
|
-
value of the translated attribute if passed to it.
|
|
19
|
-
|
|
20
|
-
@see http://api.rubyonrails.org/classes/ActiveModel/Dirty.html Rails documentation for Active Model Dirty module
|
|
21
|
-
|
|
22
|
-
=end
|
|
23
|
-
module ActiveModel::Dirty
|
|
24
|
-
# @!group Backend Accessors
|
|
25
|
-
# @!macro backend_writer
|
|
26
|
-
# @param [Hash] options
|
|
27
|
-
def write(locale, value, **options)
|
|
28
|
-
locale_accessor = Mobility.normalize_locale_accessor(attribute, locale)
|
|
29
|
-
if model.changed_attributes.has_key?(locale_accessor) && model.changed_attributes[locale_accessor] == value
|
|
30
|
-
model.attributes_changed_by_setter.except!(locale_accessor)
|
|
31
|
-
elsif read(locale, options.merge(fallback: false)) != value
|
|
32
|
-
model.send(:attribute_will_change!, locale_accessor)
|
|
33
|
-
end
|
|
34
|
-
super
|
|
35
|
-
end
|
|
36
|
-
# @!endgroup
|
|
37
|
-
|
|
38
|
-
# @param [Class] backend_class Class of backend
|
|
39
|
-
def self.included(backend_class)
|
|
40
|
-
backend_class.extend(ClassMethods)
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
# Adds hook after {Backend::Setup#setup_model} to add dirty-tracking
|
|
44
|
-
# methods for translated attributes onto model class.
|
|
45
|
-
module ClassMethods
|
|
46
|
-
# (see Mobility::Backend::Setup#setup_model)
|
|
47
|
-
def setup_model(model_class, attributes, **options)
|
|
48
|
-
super
|
|
49
|
-
model_class.class_eval do
|
|
50
|
-
Mobility::Backend::ActiveModel::Dirty.method_suffixes.each do |suffix|
|
|
51
|
-
attributes.each do |attribute|
|
|
52
|
-
class_eval <<-EOM, __FILE__, __LINE__ + 1
|
|
53
|
-
def #{attribute}#{suffix}
|
|
54
|
-
attribute#{suffix}(Mobility.normalize_locale_accessor("#{attribute}"))
|
|
55
|
-
end
|
|
56
|
-
EOM
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
restore_methods = Module.new do
|
|
62
|
-
attributes.each do |attribute|
|
|
63
|
-
define_method "restore_#{attribute}!" do
|
|
64
|
-
locale_accessor = Mobility.normalize_locale_accessor(attribute)
|
|
65
|
-
if attribute_changed?(locale_accessor)
|
|
66
|
-
__send__("#{attribute}=", changed_attributes[locale_accessor])
|
|
67
|
-
end
|
|
68
|
-
end
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
define_method :restore_attribute! do |attr|
|
|
72
|
-
if attributes.include?(attr.to_s)
|
|
73
|
-
send("restore_#{attr}!")
|
|
74
|
-
else
|
|
75
|
-
super(attr)
|
|
76
|
-
end
|
|
77
|
-
end
|
|
78
|
-
private :restore_attribute!
|
|
79
|
-
end
|
|
80
|
-
model_class.include restore_methods
|
|
81
|
-
end
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
# Get method suffixes. Creating an object just to get the list of
|
|
85
|
-
# suffixes is not very efficient, but the most reliable way given that
|
|
86
|
-
# they change from Rails version to version.
|
|
87
|
-
def self.method_suffixes
|
|
88
|
-
@method_suffixes ||=
|
|
89
|
-
Class.new do
|
|
90
|
-
include ::ActiveModel::Dirty
|
|
91
|
-
end.attribute_method_matchers.map(&:suffix).select { |m| m =~ /\A_/ }
|
|
92
|
-
end
|
|
93
|
-
end
|
|
94
|
-
end
|
|
95
|
-
end
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
module Mobility
|
|
2
|
-
module Backend
|
|
3
|
-
module ActiveRecord
|
|
4
|
-
autoload :Column, 'mobility/backend/active_record/column'
|
|
5
|
-
autoload :Dirty, 'mobility/backend/active_record/dirty'
|
|
6
|
-
autoload :Hstore, 'mobility/backend/active_record/hstore'
|
|
7
|
-
autoload :Jsonb, 'mobility/backend/active_record/jsonb'
|
|
8
|
-
autoload :KeyValue, 'mobility/backend/active_record/key_value'
|
|
9
|
-
autoload :Serialized, 'mobility/backend/active_record/serialized'
|
|
10
|
-
autoload :QueryMethods, 'mobility/backend/active_record/query_methods'
|
|
11
|
-
autoload :Table, 'mobility/backend/active_record/table'
|
|
12
|
-
|
|
13
|
-
def setup_query_methods(query_methods)
|
|
14
|
-
setup do |attributes, options|
|
|
15
|
-
extend(Module.new do
|
|
16
|
-
define_method ::Mobility.query_method do
|
|
17
|
-
super().extending(query_methods.new(attributes, options))
|
|
18
|
-
end
|
|
19
|
-
end)
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def self.included(backend_class)
|
|
24
|
-
backend_class.include(Backend)
|
|
25
|
-
backend_class.extend(self)
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
end
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
module Mobility
|
|
2
|
-
module Backend
|
|
3
|
-
=begin
|
|
4
|
-
|
|
5
|
-
Dirty tracking for AR models. See {Mobility::Backend::ActiveModel::Dirty} for
|
|
6
|
-
details on usage.
|
|
7
|
-
|
|
8
|
-
=end
|
|
9
|
-
module ActiveRecord::Dirty
|
|
10
|
-
include ActiveModel::Dirty
|
|
11
|
-
|
|
12
|
-
# @param [Class] backend_class Class of backend
|
|
13
|
-
def self.included(backend_class)
|
|
14
|
-
backend_class.extend(ActiveModel::Dirty::ClassMethods)
|
|
15
|
-
backend_class.extend(ClassMethods)
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
# Adds hook after {Backend::Setup#setup_model} to patch AR so that it
|
|
19
|
-
# handles changes to translated attributes just like normal attributes.
|
|
20
|
-
module ClassMethods
|
|
21
|
-
# (see Mobility::Backend::Setup#setup_model)
|
|
22
|
-
def setup_model(model_class, attributes, **options)
|
|
23
|
-
super
|
|
24
|
-
|
|
25
|
-
method_name_regex = /\A(#{attributes.join('|'.freeze)})_([a-z]{2}(_[a-z]{2})?)(=?|\??)\z/.freeze
|
|
26
|
-
has_attribute = Module.new do
|
|
27
|
-
define_method :has_attribute? do |attr_name|
|
|
28
|
-
super(attr_name) || !!method_name_regex.match(attr_name)
|
|
29
|
-
end
|
|
30
|
-
end
|
|
31
|
-
model_class.extend has_attribute
|
|
32
|
-
|
|
33
|
-
changes_applied_method = ::ActiveRecord::VERSION::STRING < '5.1' ? :changes_applied : :changes_internally_applied
|
|
34
|
-
mod = Module.new do
|
|
35
|
-
define_method changes_applied_method do
|
|
36
|
-
@previously_changed = changes
|
|
37
|
-
super()
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
def clear_changes_information
|
|
41
|
-
@previously_changed = ActiveSupport::HashWithIndifferentAccess.new
|
|
42
|
-
super
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
def previous_changes
|
|
46
|
-
(@previously_changed ||= ActiveSupport::HashWithIndifferentAccess.new).merge(super)
|
|
47
|
-
end
|
|
48
|
-
end
|
|
49
|
-
model_class.include mod
|
|
50
|
-
end
|
|
51
|
-
end
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
end
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
require 'mobility/backend/active_record/hash_valued'
|
|
2
|
-
|
|
3
|
-
module Mobility
|
|
4
|
-
module Backend
|
|
5
|
-
=begin
|
|
6
|
-
|
|
7
|
-
Implements the {Mobility::Backend::Hstore} backend for ActiveRecord models.
|
|
8
|
-
|
|
9
|
-
@see Mobility::Backend::ActiveRecord::HashValued
|
|
10
|
-
|
|
11
|
-
=end
|
|
12
|
-
class ActiveRecord::Hstore < ActiveRecord::HashValued
|
|
13
|
-
require 'mobility/backend/active_record/hstore/query_methods'
|
|
14
|
-
|
|
15
|
-
# @!group Backend Accessors
|
|
16
|
-
# @!macro backend_reader
|
|
17
|
-
# @!method read(locale, **options)
|
|
18
|
-
|
|
19
|
-
# @!group Backend Accessors
|
|
20
|
-
# @!macro backend_writer
|
|
21
|
-
def write(locale, value, **_)
|
|
22
|
-
translations[locale] = value && value.to_s
|
|
23
|
-
end
|
|
24
|
-
# @!endgroup
|
|
25
|
-
|
|
26
|
-
setup_query_methods(QueryMethods)
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
end
|
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
module Mobility
|
|
2
|
-
module Backend
|
|
3
|
-
=begin
|
|
4
|
-
|
|
5
|
-
Caches values fetched from the backend so subsequent fetches can be performed
|
|
6
|
-
more quickly.
|
|
7
|
-
|
|
8
|
-
By default, the cache stores cached values in a simple hash, returned from the
|
|
9
|
-
{new_cache} method added to the including backend instance class. To use a
|
|
10
|
-
different cache class, simply define a +new_cache+ method in the backend and
|
|
11
|
-
return a new instance of the cache class (many backends do this, see
|
|
12
|
-
{Mobility::Backend::KeyValue} for one example.)
|
|
13
|
-
|
|
14
|
-
The cache is reset by the {clear_cache} method, which by default simply assigns
|
|
15
|
-
the result of {new_cache} to the +@cache+ instance variable. This behaviour can
|
|
16
|
-
also be customized by defining a +new_cache+ method on the backend class (see
|
|
17
|
-
{Mobility::Backend::ActiveRecord::Table#new_cache} for an example of a backend that does this).
|
|
18
|
-
|
|
19
|
-
The cache is reset when one of a set of events happens (saving, reloading,
|
|
20
|
-
etc.). See {BackendResetter} for details.
|
|
21
|
-
|
|
22
|
-
Values are added to the cache in two ways:
|
|
23
|
-
|
|
24
|
-
1. first read from backend
|
|
25
|
-
2. any write to backend
|
|
26
|
-
|
|
27
|
-
The latter can be customized by defining the {write_to_cache?} method, which by
|
|
28
|
-
default returns +false+. If set to +true+, then writes will only update the
|
|
29
|
-
cache and not hit the backend. This is a sensible setting in case the cache is
|
|
30
|
-
actually an object which directly stores the translation (see one of the
|
|
31
|
-
ORM-specific implementations of {Mobility::Backend::KeyValue} for examples of
|
|
32
|
-
this).
|
|
33
|
-
|
|
34
|
-
=end
|
|
35
|
-
module Cache
|
|
36
|
-
# @group Backend Accessors
|
|
37
|
-
# @!macro backend_reader
|
|
38
|
-
# @param [Hash] options
|
|
39
|
-
# @param [Boolean] cache
|
|
40
|
-
# *false* to disable cache.
|
|
41
|
-
def read(locale, **options)
|
|
42
|
-
return super if options.delete(:cache) == false
|
|
43
|
-
if write_to_cache? || cache.has_key?(locale)
|
|
44
|
-
cache[locale]
|
|
45
|
-
else
|
|
46
|
-
cache[locale] = super
|
|
47
|
-
end
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
# @!macro backend_writer
|
|
51
|
-
# @param [Hash] options
|
|
52
|
-
# @param [Boolean] cache
|
|
53
|
-
# *false* to disable cache.
|
|
54
|
-
def write(locale, value, **options)
|
|
55
|
-
return super if options.delete(:cache) == false
|
|
56
|
-
cache[locale] = write_to_cache? ? value : super
|
|
57
|
-
end
|
|
58
|
-
# @!endgroup
|
|
59
|
-
|
|
60
|
-
# Adds hook to {Backend::Setup#setup_model} to include instance of
|
|
61
|
-
# model-specific {BackendResetter} subclass when setting up
|
|
62
|
-
# model class, to trigger cache resetting at specific events (saving,
|
|
63
|
-
# reloading, etc.)
|
|
64
|
-
module Setup
|
|
65
|
-
# @param model_class Model class
|
|
66
|
-
# @param [Array<String>] attributes Backend attributes
|
|
67
|
-
def setup_model(model_class, attributes, **_)
|
|
68
|
-
super
|
|
69
|
-
model_class.include BackendResetter.for(model_class).new(attributes) { clear_cache }
|
|
70
|
-
end
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
# @!group Cache Methods
|
|
74
|
-
# @!parse
|
|
75
|
-
# def new_cache
|
|
76
|
-
# {}
|
|
77
|
-
# end
|
|
78
|
-
#
|
|
79
|
-
# @!parse
|
|
80
|
-
# def write_to_cache?
|
|
81
|
-
# false
|
|
82
|
-
# end
|
|
83
|
-
#
|
|
84
|
-
# @!parse
|
|
85
|
-
# def clear_cache
|
|
86
|
-
# @cache = new_cache
|
|
87
|
-
# end
|
|
88
|
-
# @!endgroup
|
|
89
|
-
|
|
90
|
-
# Includes cache methods to backend (unless they are already defined) and
|
|
91
|
-
# extends backend class with {Mobility::Cache::Setup} for backend resetting.
|
|
92
|
-
def self.included(backend_class)
|
|
93
|
-
backend_class.class_eval do
|
|
94
|
-
extend Setup
|
|
95
|
-
|
|
96
|
-
def new_cache
|
|
97
|
-
{}
|
|
98
|
-
end unless method_defined?(:new_cache)
|
|
99
|
-
|
|
100
|
-
def write_to_cache?
|
|
101
|
-
false
|
|
102
|
-
end unless method_defined?(:write_to_cache?)
|
|
103
|
-
|
|
104
|
-
def clear_cache
|
|
105
|
-
@cache = new_cache
|
|
106
|
-
end unless method_defined?(:clear_cache)
|
|
107
|
-
end
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
private
|
|
111
|
-
|
|
112
|
-
def cache
|
|
113
|
-
@cache ||= new_cache
|
|
114
|
-
end
|
|
115
|
-
end
|
|
116
|
-
end
|
|
117
|
-
end
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
module Mobility
|
|
2
|
-
module Backend
|
|
3
|
-
=begin
|
|
4
|
-
|
|
5
|
-
Dirty tracking for Mobility attributes. See class-specific implementations for
|
|
6
|
-
details.
|
|
7
|
-
|
|
8
|
-
@see Mobility::Backend::ActiveModel::Dirty
|
|
9
|
-
@see Mobility::Backend::Sequel::Dirty
|
|
10
|
-
|
|
11
|
-
@note Dirty tracking can have unexpected results when combined with fallbacks.
|
|
12
|
-
A change in the fallback locale value will not mark an attribute falling
|
|
13
|
-
through to that locale as changed, even though it may look like it has
|
|
14
|
-
changed. However, when the value for the current locale is changed from nil
|
|
15
|
-
or blank to a new value, the change will be recorded as a change from that
|
|
16
|
-
fallback value, rather than from the nil or blank value. The specs are the
|
|
17
|
-
most reliable source of information on the interaction between dirty tracking
|
|
18
|
-
and fallbacks.
|
|
19
|
-
|
|
20
|
-
=end
|
|
21
|
-
module Dirty
|
|
22
|
-
# @param model_class Class of model this backend is defined on.
|
|
23
|
-
# @return [Backend]
|
|
24
|
-
# @raise [ArgumentError] if model class does not support dirty tracking
|
|
25
|
-
def self.for(model_class)
|
|
26
|
-
model_class ||= Object
|
|
27
|
-
if Loaded::ActiveRecord && model_class.ancestors.include?(::ActiveModel::Dirty)
|
|
28
|
-
(model_class < ::ActiveRecord::Base) ?
|
|
29
|
-
Backend::ActiveRecord::Dirty : Backend::ActiveModel::Dirty
|
|
30
|
-
elsif Loaded::Sequel && model_class < ::Sequel::Model
|
|
31
|
-
Backend::Sequel::Dirty
|
|
32
|
-
else
|
|
33
|
-
raise ArgumentError, "#{model_class.to_s} does not support Dirty module."
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
|
-
end
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
module Mobility
|
|
2
|
-
module Backend
|
|
3
|
-
=begin
|
|
4
|
-
|
|
5
|
-
Stores attribute translation as attribute/value pair on a shared translations
|
|
6
|
-
table, using a polymorphic relationship between a translation class and models
|
|
7
|
-
using the backend. By default, two tables are assumed to be present supporting
|
|
8
|
-
string and text translations: a +mobility_text_translations+ table for text-valued translations and a
|
|
9
|
-
+mobility_string_translations+ table for string-valued translations (the only
|
|
10
|
-
difference being the column type of the +value+ column on the table).
|
|
11
|
-
|
|
12
|
-
==Backend Options
|
|
13
|
-
|
|
14
|
-
===+association_name+
|
|
15
|
-
|
|
16
|
-
Name of association on model. Defaults to +mobility_text_translations+ (if
|
|
17
|
-
+type+ is +:text+) or +mobility_string_translations+ (if +type+ is +:string+).
|
|
18
|
-
If specified, ensure name does not overlap with other methods on model or with
|
|
19
|
-
the association name used by other backends on model (otherwise one will
|
|
20
|
-
overwrite the other).
|
|
21
|
-
|
|
22
|
-
===+type+
|
|
23
|
-
|
|
24
|
-
Currently, either +:text+ or +:string+ is supported. Determines which class to
|
|
25
|
-
use for translations, which in turn determines which table to use to store
|
|
26
|
-
translations (by default +mobility_text_translations+ for text type,
|
|
27
|
-
+mobility_string_translations+ for string type).
|
|
28
|
-
|
|
29
|
-
===+class_name+
|
|
30
|
-
|
|
31
|
-
Class to use for translations when defining association. By default,
|
|
32
|
-
{Mobility::ActiveRecord::TextTranslation} or
|
|
33
|
-
{Mobility::ActiveRecord::StringTranslation} for ActiveRecord models (similar
|
|
34
|
-
for Sequel models). If string is passed in, it will be constantized to get the
|
|
35
|
-
class.
|
|
36
|
-
|
|
37
|
-
@see Mobility::Backend::ActiveRecord::KeyValue
|
|
38
|
-
@see Mobility::Backend::Sequel::KeyValue
|
|
39
|
-
|
|
40
|
-
=end
|
|
41
|
-
module KeyValue
|
|
42
|
-
include OrmDelegator
|
|
43
|
-
|
|
44
|
-
def self.included(backend)
|
|
45
|
-
backend.extend ClassMethods
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
module ClassMethods
|
|
49
|
-
# @!group Backend Configuration
|
|
50
|
-
# @option options [Symbol,String] type (:text) Column type to use
|
|
51
|
-
# @raise [ArgumentError] if type is not either :text or :string
|
|
52
|
-
def configure(options)
|
|
53
|
-
options[:type] = (options[:type] || :text).to_sym
|
|
54
|
-
raise ArgumentError, "type must be one of: [text, string]" unless [:text, :string].include?(options[:type])
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
# Simple cache to memoize translations as a hash so they can be fetched
|
|
59
|
-
# quickly.
|
|
60
|
-
class TranslationsCache
|
|
61
|
-
# @param backend Instance of KeyValue backend to cache
|
|
62
|
-
# @return [TranslationsCache]
|
|
63
|
-
def initialize(backend)
|
|
64
|
-
@cache = Hash.new { |hash, locale| hash[locale] = backend.translation_for(locale) }
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
# @param locale [Symbol] Locale to fetch
|
|
68
|
-
def [](locale)
|
|
69
|
-
@cache[locale].value
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
# @param locale [Symbol] Locale to set
|
|
73
|
-
# @param value [String] Value to set
|
|
74
|
-
def []=(locale, value)
|
|
75
|
-
@cache[locale].value = value
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
# @yield [locale, translation]
|
|
79
|
-
def each_translation &block
|
|
80
|
-
@cache.each_value &block
|
|
81
|
-
end
|
|
82
|
-
end
|
|
83
|
-
end
|
|
84
|
-
end
|
|
85
|
-
end
|