mobility 0.1.20 → 0.2.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 +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
@@ -1,29 +0,0 @@
|
|
1
|
-
module Mobility
|
2
|
-
module Backend
|
3
|
-
module Sequel
|
4
|
-
autoload :Column, 'mobility/backend/sequel/column'
|
5
|
-
autoload :Dirty, 'mobility/backend/sequel/dirty'
|
6
|
-
autoload :Hstore, 'mobility/backend/sequel/hstore'
|
7
|
-
autoload :Jsonb, 'mobility/backend/sequel/jsonb'
|
8
|
-
autoload :KeyValue, 'mobility/backend/sequel/key_value'
|
9
|
-
autoload :Serialized, 'mobility/backend/sequel/serialized'
|
10
|
-
autoload :Table, 'mobility/backend/sequel/table'
|
11
|
-
autoload :QueryMethods, 'mobility/backend/sequel/query_methods'
|
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().with_extend(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,39 +0,0 @@
|
|
1
|
-
module Mobility
|
2
|
-
module Backend
|
3
|
-
=begin
|
4
|
-
|
5
|
-
Implements the {Mobility::Backend::Column} backend for Sequel models.
|
6
|
-
|
7
|
-
@note This backend disables the +locale_accessors+ option, which would
|
8
|
-
otherwise interfere with column methods.
|
9
|
-
=end
|
10
|
-
class Sequel::Column
|
11
|
-
include Sequel
|
12
|
-
include Column
|
13
|
-
|
14
|
-
require 'mobility/backend/sequel/column/query_methods'
|
15
|
-
|
16
|
-
# @!group Backend Accessors
|
17
|
-
# @!macro backend_reader
|
18
|
-
def read(locale, **_)
|
19
|
-
column = column(locale)
|
20
|
-
model.send(column) if model.columns.include?(column)
|
21
|
-
end
|
22
|
-
|
23
|
-
# @!group Backend Accessors
|
24
|
-
# @!macro backend_writer
|
25
|
-
def write(locale, value, **_)
|
26
|
-
column = column(locale)
|
27
|
-
model.send("#{column}=", value) if model.columns.include?(column)
|
28
|
-
end
|
29
|
-
|
30
|
-
# @!group Backend Configuration
|
31
|
-
def self.configure(options)
|
32
|
-
options[:locale_accessors] = false
|
33
|
-
end
|
34
|
-
# @!endgroup
|
35
|
-
|
36
|
-
setup_query_methods(QueryMethods)
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
@@ -1,57 +0,0 @@
|
|
1
|
-
module Mobility
|
2
|
-
module Backend
|
3
|
-
=begin
|
4
|
-
|
5
|
-
Dirty tracking for Sequel models which use the +Sequel::Plugins::Dirty+ plugin.
|
6
|
-
Automatically includes dirty plugin in model class when enabled.
|
7
|
-
|
8
|
-
@see http://sequel.jeremyevans.net/rdoc-plugins/index.html Sequel dirty plugin
|
9
|
-
|
10
|
-
=end
|
11
|
-
module Sequel::Dirty
|
12
|
-
# @!group Backend Accessors
|
13
|
-
# @!macro backend_writer
|
14
|
-
# @param [Hash] options
|
15
|
-
def write(locale, value, **options)
|
16
|
-
locale_accessor = Mobility.normalize_locale_accessor(attribute, locale).to_sym
|
17
|
-
if model.column_changes.has_key?(locale_accessor) && model.initial_values[locale_accessor] == value
|
18
|
-
super
|
19
|
-
[model.changed_columns, model.initial_values].each { |h| h.delete(locale_accessor) }
|
20
|
-
elsif read(locale, options.merge(fallback: false)) != value
|
21
|
-
model.will_change_column(locale_accessor)
|
22
|
-
super
|
23
|
-
end
|
24
|
-
end
|
25
|
-
# @!endgroup
|
26
|
-
|
27
|
-
# @param [Class] backend_class Class of backend
|
28
|
-
def self.included(backend_class)
|
29
|
-
backend_class.extend(ClassMethods)
|
30
|
-
end
|
31
|
-
|
32
|
-
# Adds hook after {Backend::Setup#setup_model} to add dirty-tracking
|
33
|
-
# methods for translated attributes onto model class.
|
34
|
-
module ClassMethods
|
35
|
-
# (see Mobility::Backend::Setup#setup_model)
|
36
|
-
def setup_model(model_class, attributes, **options)
|
37
|
-
super
|
38
|
-
model_class.plugin :dirty
|
39
|
-
model_class.class_eval do
|
40
|
-
mod = Module.new do
|
41
|
-
%w[initial_value column_change column_changed? reset_column].each do |method_name|
|
42
|
-
define_method method_name do |column|
|
43
|
-
if attributes.map(&:to_sym).include?(column)
|
44
|
-
super(Mobility.normalize_locale_accessor(column).to_sym)
|
45
|
-
else
|
46
|
-
super(column)
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
|
-
include mod
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
@@ -1,51 +0,0 @@
|
|
1
|
-
module Mobility
|
2
|
-
module Backend
|
3
|
-
=begin
|
4
|
-
|
5
|
-
Internal class used by Sequel backends that store values as a hash.
|
6
|
-
|
7
|
-
=end
|
8
|
-
class Sequel::HashValued
|
9
|
-
include Sequel
|
10
|
-
|
11
|
-
# @!macro backend_reader
|
12
|
-
def read(locale, **_)
|
13
|
-
translations[locale.to_s]
|
14
|
-
end
|
15
|
-
|
16
|
-
# @!macro backend_writer
|
17
|
-
def write(locale, value, **_)
|
18
|
-
translations[locale.to_s] = value
|
19
|
-
end
|
20
|
-
|
21
|
-
# @!group Cache Methods
|
22
|
-
def translations
|
23
|
-
model.send("#{attribute}_before_mobility")
|
24
|
-
end
|
25
|
-
alias_method :new_cache, :translations
|
26
|
-
|
27
|
-
# @return [Boolean]
|
28
|
-
def write_to_cache?
|
29
|
-
true
|
30
|
-
end
|
31
|
-
# @!endgroup
|
32
|
-
|
33
|
-
setup do |attributes, options|
|
34
|
-
method_overrides = Module.new do
|
35
|
-
define_method :initialize_set do |values|
|
36
|
-
attributes.each { |attribute| send(:"#{attribute}_before_mobility=", {}) }
|
37
|
-
super(values)
|
38
|
-
end
|
39
|
-
define_method :before_validation do
|
40
|
-
attributes.each do |attribute|
|
41
|
-
send("#{attribute}_before_mobility").delete_if { |_, v| v.blank? }
|
42
|
-
end
|
43
|
-
super()
|
44
|
-
end
|
45
|
-
end
|
46
|
-
include method_overrides
|
47
|
-
include Mobility::Sequel::ColumnChanges.new(attributes)
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
@@ -1,29 +0,0 @@
|
|
1
|
-
require 'mobility/backend/sequel/hash_valued'
|
2
|
-
|
3
|
-
module Mobility
|
4
|
-
module Backend
|
5
|
-
=begin
|
6
|
-
|
7
|
-
Implements the {Mobility::Backend::Hstore} backend for Sequel models.
|
8
|
-
|
9
|
-
@see Mobility::Backend::Sequel::HashValued
|
10
|
-
|
11
|
-
=end
|
12
|
-
class Sequel::Hstore < Sequel::HashValued
|
13
|
-
require 'mobility/backend/sequel/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.to_s] = value && value.to_s
|
23
|
-
end
|
24
|
-
# @!endgroup
|
25
|
-
|
26
|
-
setup_query_methods(QueryMethods)
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
@@ -1,20 +0,0 @@
|
|
1
|
-
module Mobility
|
2
|
-
module Backend
|
3
|
-
class Sequel::Serialized::QueryMethods < Sequel::QueryMethods
|
4
|
-
def initialize(attributes, **)
|
5
|
-
super
|
6
|
-
attributes_extractor = @attributes_extractor
|
7
|
-
cond_checker = @cond_checker = lambda do |cond|
|
8
|
-
if i18n_keys = attributes_extractor.call(cond)
|
9
|
-
raise ArgumentError,
|
10
|
-
"You cannot query on mobility attributes translated with the Serialized backend (#{i18n_keys.join(", ")})."
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
define_method :where do |*cond, &block|
|
15
|
-
cond_checker.call(cond.first) || super(*cond, &block)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
@@ -1,30 +0,0 @@
|
|
1
|
-
=begin
|
2
|
-
|
3
|
-
Add +blank?+, +present?+ and +presence+ methods to +Object+ class if
|
4
|
-
activesupport cannot be loaded.
|
5
|
-
|
6
|
-
=end
|
7
|
-
class Object
|
8
|
-
def blank?
|
9
|
-
respond_to?(:empty?) ? !!empty? : !self
|
10
|
-
end
|
11
|
-
|
12
|
-
def present?
|
13
|
-
!blank?
|
14
|
-
end
|
15
|
-
|
16
|
-
def presence
|
17
|
-
self if present?
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
=begin
|
22
|
-
|
23
|
-
Add +blank?+ method to +NilClass+ in case activesupport cannot be loaded.
|
24
|
-
|
25
|
-
=end
|
26
|
-
class NilClass
|
27
|
-
def blank?
|
28
|
-
true
|
29
|
-
end
|
30
|
-
end
|
@@ -1,16 +0,0 @@
|
|
1
|
-
=begin
|
2
|
-
|
3
|
-
Add String methods +camelize+ and +present?+ to +String+ if activesupport
|
4
|
-
cannot be loaded.
|
5
|
-
|
6
|
-
=end
|
7
|
-
class String
|
8
|
-
# paraphrased from activesupport
|
9
|
-
def camelize
|
10
|
-
sub(/^[a-z\d]*/) { $&.capitalize }.gsub(/(?:_|(\/))([a-z\d]*)/) { "#{$1}#{$2.capitalize}" }.gsub('/', '::')
|
11
|
-
end
|
12
|
-
|
13
|
-
def present?
|
14
|
-
!blank?
|
15
|
-
end
|
16
|
-
end
|
@@ -1,57 +0,0 @@
|
|
1
|
-
# frozen-string-literal: true
|
2
|
-
|
3
|
-
module Mobility
|
4
|
-
=begin
|
5
|
-
|
6
|
-
Defines +method_missing+ and +respond_to_missing?+ methods for a set of
|
7
|
-
attributes such that a method call using a locale accessor, like:
|
8
|
-
|
9
|
-
article.title_pt_br
|
10
|
-
|
11
|
-
will return the value of +article.title+ with the locale set to +pt-BR+ around
|
12
|
-
the method call. The class is called "FallthroughAccessors" because when
|
13
|
-
included in a model class, locale-specific methods will be available even if
|
14
|
-
not explicitly defined with the +locale_accessors+ option.
|
15
|
-
|
16
|
-
This is a less efficient (but more open-ended) implementation of locale
|
17
|
-
accessors, for use in cases where the locales to be used are not known when the
|
18
|
-
model class is generated.
|
19
|
-
|
20
|
-
@example Using fallthrough locales on a plain old ruby class
|
21
|
-
class Post
|
22
|
-
def title
|
23
|
-
"title in #{Mobility.locale}"
|
24
|
-
end
|
25
|
-
include Mobility::FallthroughAccessors.new("title")
|
26
|
-
end
|
27
|
-
|
28
|
-
Mobility.locale = :en
|
29
|
-
post = Post.new
|
30
|
-
post.title
|
31
|
-
#=> "title in en"
|
32
|
-
post.title_fr
|
33
|
-
#=> "title in fr"
|
34
|
-
|
35
|
-
=end
|
36
|
-
class FallthroughAccessors < Module
|
37
|
-
# @param [String] One or more attributes
|
38
|
-
def initialize(*attributes)
|
39
|
-
method_name_regex = /\A(#{attributes.join('|'.freeze)})_([a-z]{2}(_[a-z]{2})?)(=?|\??)\z/.freeze
|
40
|
-
|
41
|
-
define_method :method_missing do |method_name, *arguments, &block|
|
42
|
-
if method_name =~ method_name_regex
|
43
|
-
attribute = $1.to_sym
|
44
|
-
locale, suffix = $2.split('_'.freeze)
|
45
|
-
locale = "#{locale}-#{suffix.upcase}".freeze if suffix
|
46
|
-
Mobility.with_locale(locale) { public_send("#{attribute}#{$4}".freeze, *arguments) }
|
47
|
-
else
|
48
|
-
super(method_name, *arguments, &block)
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
define_method :respond_to_missing? do |method_name, include_private = false|
|
53
|
-
(method_name =~ method_name_regex) || super(method_name, include_private)
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
@@ -1,55 +0,0 @@
|
|
1
|
-
# frozen-string-literal: true
|
2
|
-
|
3
|
-
module Mobility
|
4
|
-
=begin
|
5
|
-
|
6
|
-
Defines methods for a set of locales to access translated attributes in those
|
7
|
-
locales directly with a method call, using a suffix including the locale:
|
8
|
-
|
9
|
-
article.title_pt_br
|
10
|
-
|
11
|
-
If no locales are passed as an option to the initializer,
|
12
|
-
+I18n.available_locales+ will be used by default.
|
13
|
-
|
14
|
-
@example
|
15
|
-
class Post
|
16
|
-
def title
|
17
|
-
"title in #{Mobility.locale}"
|
18
|
-
end
|
19
|
-
include Mobility::LocaleAccessors.new("title", locales: [:en, :fr])
|
20
|
-
end
|
21
|
-
|
22
|
-
Mobility.locale = :en
|
23
|
-
post = Post.new
|
24
|
-
post.title
|
25
|
-
#=> "title in en"
|
26
|
-
post.title_fr
|
27
|
-
#=> "title in fr"
|
28
|
-
|
29
|
-
=end
|
30
|
-
class LocaleAccessors < Module
|
31
|
-
# @param [String] One or more attributes
|
32
|
-
# @param [Array<Symbol>] Locales
|
33
|
-
def initialize(*attributes, locales: I18n.available_locales)
|
34
|
-
warning_message = "locale passed as option to locale accessor will be ignored".freeze
|
35
|
-
|
36
|
-
attributes.each do |attribute|
|
37
|
-
locales.each do |locale|
|
38
|
-
normalized_locale = Mobility.normalize_locale(locale)
|
39
|
-
define_method "#{attribute}_#{normalized_locale}" do |**options|
|
40
|
-
warn warning_message if options.delete(:locale)
|
41
|
-
Mobility.with_locale(locale) { send(attribute, options) }
|
42
|
-
end
|
43
|
-
define_method "#{attribute}_#{normalized_locale}?" do |**options|
|
44
|
-
warn warning_message if options.delete(:locale)
|
45
|
-
Mobility.with_locale(locale) { send("#{attribute}?", options) }
|
46
|
-
end
|
47
|
-
define_method "#{attribute}_#{normalized_locale}=" do |value, **options|
|
48
|
-
warn warning_message if options.delete(:locale)
|
49
|
-
Mobility.with_locale(locale) { send("#{attribute}=", value, options) }
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|