mobility 1.0.0.alpha → 1.0.1
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 +0 -0
- data/CHANGELOG.md +54 -1
- data/Gemfile +5 -16
- data/Gemfile.lock +30 -82
- data/README.md +24 -29
- data/lib/mobility.rb +67 -9
- data/lib/mobility/backend.rb +8 -10
- data/lib/mobility/backends.rb +1 -1
- data/lib/mobility/backends/active_record.rb +1 -1
- data/lib/mobility/backends/active_record/column.rb +1 -1
- data/lib/mobility/backends/active_record/container.rb +6 -9
- data/lib/mobility/backends/active_record/hstore.rb +4 -4
- data/lib/mobility/backends/active_record/json.rb +3 -3
- data/lib/mobility/backends/active_record/jsonb.rb +3 -3
- data/lib/mobility/backends/active_record/key_value.rb +27 -11
- data/lib/mobility/backends/active_record/serialized.rb +4 -0
- data/lib/mobility/backends/active_record/table.rb +12 -7
- data/lib/mobility/backends/container.rb +10 -2
- data/lib/mobility/backends/hash_valued.rb +4 -0
- data/lib/mobility/backends/jsonb.rb +1 -1
- data/lib/mobility/backends/key_value.rb +12 -15
- data/lib/mobility/backends/sequel.rb +34 -2
- data/lib/mobility/backends/sequel/container.rb +8 -8
- data/lib/mobility/backends/sequel/hstore.rb +1 -1
- data/lib/mobility/backends/sequel/json.rb +1 -0
- data/lib/mobility/backends/sequel/key_value.rb +79 -12
- data/lib/mobility/backends/sequel/pg_hash.rb +6 -6
- data/lib/mobility/backends/sequel/serialized.rb +4 -0
- data/lib/mobility/backends/sequel/table.rb +18 -8
- data/lib/mobility/backends/table.rb +29 -29
- data/lib/mobility/pluggable.rb +21 -1
- data/lib/mobility/plugin.rb +2 -2
- data/lib/mobility/plugins.rb +2 -0
- data/lib/mobility/plugins/active_model/dirty.rb +11 -5
- data/lib/mobility/plugins/active_record.rb +3 -0
- data/lib/mobility/plugins/active_record/backend.rb +2 -0
- data/lib/mobility/plugins/active_record/query.rb +7 -7
- data/lib/mobility/plugins/active_record/uniqueness_validation.rb +5 -1
- data/lib/mobility/plugins/arel.rb +125 -0
- data/lib/mobility/plugins/arel/nodes.rb +15 -0
- data/lib/mobility/plugins/arel/nodes/pg_ops.rb +134 -0
- data/lib/mobility/plugins/attribute_methods.rb +1 -0
- data/lib/mobility/plugins/attributes.rb +17 -15
- data/lib/mobility/plugins/backend.rb +45 -22
- data/lib/mobility/plugins/cache.rb +12 -5
- data/lib/mobility/plugins/default.rb +1 -1
- data/lib/mobility/plugins/fallbacks.rb +4 -4
- data/lib/mobility/plugins/fallthrough_accessors.rb +5 -6
- data/lib/mobility/plugins/locale_accessors.rb +2 -5
- data/lib/mobility/plugins/presence.rb +1 -1
- data/lib/mobility/plugins/reader.rb +2 -2
- data/lib/mobility/plugins/sequel/dirty.rb +2 -2
- data/lib/mobility/plugins/writer.rb +1 -1
- data/lib/mobility/version.rb +2 -2
- data/lib/rails/generators/mobility/templates/create_string_translations.rb +0 -1
- data/lib/rails/generators/mobility/templates/create_text_translations.rb +0 -1
- data/lib/rails/generators/mobility/templates/initializer.rb +11 -3
- metadata +14 -20
- metadata.gz.sig +0 -0
- data/lib/mobility/active_record/model_translation.rb +0 -14
- data/lib/mobility/active_record/string_translation.rb +0 -10
- data/lib/mobility/active_record/text_translation.rb +0 -10
- data/lib/mobility/active_record/translation.rb +0 -14
- data/lib/mobility/arel.rb +0 -49
- data/lib/mobility/arel/nodes.rb +0 -13
- data/lib/mobility/arel/nodes/pg_ops.rb +0 -132
- data/lib/mobility/arel/visitor.rb +0 -61
- data/lib/mobility/sequel/column_changes.rb +0 -28
- data/lib/mobility/sequel/hash_initializer.rb +0 -21
- data/lib/mobility/sequel/model_translation.rb +0 -20
- data/lib/mobility/sequel/sql.rb +0 -16
- data/lib/mobility/sequel/string_translation.rb +0 -10
- data/lib/mobility/sequel/text_translation.rb +0 -10
- data/lib/mobility/sequel/translation.rb +0 -53
metadata.gz.sig
CHANGED
Binary file
|
@@ -1,14 +0,0 @@
|
|
1
|
-
module Mobility
|
2
|
-
module ActiveRecord
|
3
|
-
=begin
|
4
|
-
|
5
|
-
Subclassed dynamically to generate translation class in
|
6
|
-
{Backends::ActiveRecord::Table} backend.
|
7
|
-
|
8
|
-
=end
|
9
|
-
class ModelTranslation < ::ActiveRecord::Base
|
10
|
-
self.abstract_class = true
|
11
|
-
validates :locale, presence: true
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
@@ -1,14 +0,0 @@
|
|
1
|
-
module Mobility
|
2
|
-
module ActiveRecord
|
3
|
-
# @abstract Subclass and set +table_name+ to implement for a particular column type.
|
4
|
-
class Translation < ::ActiveRecord::Base
|
5
|
-
self.abstract_class = true
|
6
|
-
|
7
|
-
belongs_to :translatable, polymorphic: true, touch: true
|
8
|
-
|
9
|
-
validates :key, presence: true, uniqueness: { scope: [:translatable_id, :translatable_type, :locale], case_sensitive: true }
|
10
|
-
validates :translatable, presence: true
|
11
|
-
validates :locale, presence: true
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
data/lib/mobility/arel.rb
DELETED
@@ -1,49 +0,0 @@
|
|
1
|
-
# frozen-string-literal: true
|
2
|
-
require "mobility/arel/nodes"
|
3
|
-
require "mobility/arel/visitor"
|
4
|
-
|
5
|
-
module Mobility
|
6
|
-
module Arel
|
7
|
-
module MobilityExpressions
|
8
|
-
include ::Arel::Expressions
|
9
|
-
|
10
|
-
# @note This is necessary in order to ensure that when a translated
|
11
|
-
# attribute is selected with an alias using +AS+, the resulting
|
12
|
-
# expression can still be counted without blowing up.
|
13
|
-
#
|
14
|
-
# Extending +::Arel::Expressions+ is necessary to convince ActiveRecord
|
15
|
-
# that this node should not be stringified, which otherwise would
|
16
|
-
# result in garbage SQL.
|
17
|
-
#
|
18
|
-
# @see https://github.com/rails/rails/blob/847342c25c61acaea988430dc3ab66a82e3ed486/activerecord/lib/active_record/relation/calculations.rb#L261
|
19
|
-
def as(*)
|
20
|
-
super
|
21
|
-
.extend(::Arel::Expressions)
|
22
|
-
.extend(Countable)
|
23
|
-
end
|
24
|
-
|
25
|
-
module Countable
|
26
|
-
# @note This allows expressions with selected translated attributes to
|
27
|
-
# be counted.
|
28
|
-
def count(*args)
|
29
|
-
left.count(*args)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
class Attribute < ::Arel::Attributes::Attribute
|
35
|
-
include MobilityExpressions
|
36
|
-
|
37
|
-
attr_reader :backend_class
|
38
|
-
attr_reader :locale
|
39
|
-
attr_reader :attribute_name
|
40
|
-
|
41
|
-
def initialize(relation, column_name, locale, backend_class, attribute_name: nil)
|
42
|
-
@backend_class = backend_class
|
43
|
-
@locale = locale
|
44
|
-
@attribute_name = attribute_name || column_name
|
45
|
-
super(relation, column_name)
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
data/lib/mobility/arel/nodes.rb
DELETED
@@ -1,13 +0,0 @@
|
|
1
|
-
# frozen-string-literal: true
|
2
|
-
module Mobility
|
3
|
-
module Arel
|
4
|
-
module Nodes
|
5
|
-
class Binary < ::Arel::Nodes::Binary; end
|
6
|
-
class Grouping < ::Arel::Nodes::Grouping; end
|
7
|
-
|
8
|
-
::Arel::Visitors::ToSql.class_eval do
|
9
|
-
alias :visit_Mobility_Arel_Nodes_Grouping :visit_Arel_Nodes_Grouping
|
10
|
-
end
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
@@ -1,132 +0,0 @@
|
|
1
|
-
# frozen-string-literal: true
|
2
|
-
require "mobility/arel"
|
3
|
-
|
4
|
-
module Mobility
|
5
|
-
module Arel
|
6
|
-
module Nodes
|
7
|
-
%w[
|
8
|
-
JsonDashArrow
|
9
|
-
JsonDashDoubleArrow
|
10
|
-
JsonbDashArrow
|
11
|
-
JsonbDashDoubleArrow
|
12
|
-
JsonbQuestion
|
13
|
-
HstoreDashArrow
|
14
|
-
HstoreQuestion
|
15
|
-
].each do |name|
|
16
|
-
const_set name, (Class.new(Binary) do
|
17
|
-
include ::Arel::Predications
|
18
|
-
include ::Arel::OrderPredications
|
19
|
-
include ::Arel::AliasPredication
|
20
|
-
include ::Mobility::Arel::MobilityExpressions
|
21
|
-
|
22
|
-
def lower
|
23
|
-
super self
|
24
|
-
end
|
25
|
-
end)
|
26
|
-
end
|
27
|
-
|
28
|
-
# Needed for AR 4.2, can be removed when support is deprecated
|
29
|
-
if ::ActiveRecord::VERSION::STRING < '5.0'
|
30
|
-
[JsonbDashDoubleArrow, HstoreDashArrow].each do |klass|
|
31
|
-
klass.class_eval do
|
32
|
-
def quoted_node other
|
33
|
-
other && super
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
class Jsonb < JsonbDashDoubleArrow
|
40
|
-
def to_dash_arrow
|
41
|
-
JsonbDashArrow.new left, right
|
42
|
-
end
|
43
|
-
|
44
|
-
def to_question
|
45
|
-
JsonbQuestion.new left, right
|
46
|
-
end
|
47
|
-
|
48
|
-
def eq other
|
49
|
-
case other
|
50
|
-
when NilClass
|
51
|
-
to_question.not
|
52
|
-
when Integer, Array, ::Hash
|
53
|
-
to_dash_arrow.eq other.to_json
|
54
|
-
when Jsonb
|
55
|
-
to_dash_arrow.eq other.to_dash_arrow
|
56
|
-
when JsonbDashArrow
|
57
|
-
to_dash_arrow.eq other
|
58
|
-
else
|
59
|
-
super
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
class Hstore < HstoreDashArrow
|
65
|
-
def to_question
|
66
|
-
HstoreQuestion.new left, right
|
67
|
-
end
|
68
|
-
|
69
|
-
def eq other
|
70
|
-
other.nil? ? to_question.not : super
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
class Json < JsonDashDoubleArrow; end
|
75
|
-
|
76
|
-
class JsonContainer < Json
|
77
|
-
def initialize column, locale, attr
|
78
|
-
super(Arel::Nodes::JsonDashArrow.new(column, locale), attr)
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
class JsonbContainer < Jsonb
|
83
|
-
def initialize column, locale, attr
|
84
|
-
@column, @locale = column, locale
|
85
|
-
super(JsonbDashArrow.new(column, locale), attr)
|
86
|
-
end
|
87
|
-
|
88
|
-
def eq other
|
89
|
-
other.nil? ? super.or(JsonbQuestion.new(@column, @locale).not) : super
|
90
|
-
end
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
module Visitors
|
95
|
-
def visit_Mobility_Arel_Nodes_JsonDashArrow o, a
|
96
|
-
json_infix o, a, '->'
|
97
|
-
end
|
98
|
-
|
99
|
-
def visit_Mobility_Arel_Nodes_JsonDashDoubleArrow o, a
|
100
|
-
json_infix o, a, '->>'
|
101
|
-
end
|
102
|
-
|
103
|
-
def visit_Mobility_Arel_Nodes_JsonbDashArrow o, a
|
104
|
-
json_infix o, a, '->'
|
105
|
-
end
|
106
|
-
|
107
|
-
def visit_Mobility_Arel_Nodes_JsonbDashDoubleArrow o, a
|
108
|
-
json_infix o, a, '->>'
|
109
|
-
end
|
110
|
-
|
111
|
-
def visit_Mobility_Arel_Nodes_JsonbQuestion o, a
|
112
|
-
json_infix o, a, '?'
|
113
|
-
end
|
114
|
-
|
115
|
-
def visit_Mobility_Arel_Nodes_HstoreDashArrow o, a
|
116
|
-
json_infix o, a, '->'
|
117
|
-
end
|
118
|
-
|
119
|
-
def visit_Mobility_Arel_Nodes_HstoreQuestion o, a
|
120
|
-
json_infix o, a, '?'
|
121
|
-
end
|
122
|
-
|
123
|
-
private
|
124
|
-
|
125
|
-
def json_infix o, a, opr
|
126
|
-
visit(Nodes::Grouping.new(::Arel::Nodes::InfixOperation.new(opr, o.left, o.right)), a)
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
::Arel::Visitors::PostgreSQL.include Visitors
|
131
|
-
end
|
132
|
-
end
|
@@ -1,61 +0,0 @@
|
|
1
|
-
# frozen-string-literal: true
|
2
|
-
module Mobility
|
3
|
-
module Arel
|
4
|
-
class Visitor < ::Arel::Visitors::Visitor
|
5
|
-
INNER_JOIN = ::Arel::Nodes::InnerJoin
|
6
|
-
OUTER_JOIN = ::Arel::Nodes::OuterJoin
|
7
|
-
|
8
|
-
attr_reader :backend_class, :locale
|
9
|
-
|
10
|
-
def initialize(backend_class, locale)
|
11
|
-
super()
|
12
|
-
@backend_class, @locale = backend_class, locale
|
13
|
-
end
|
14
|
-
|
15
|
-
private
|
16
|
-
|
17
|
-
def visit(*args)
|
18
|
-
super
|
19
|
-
rescue TypeError
|
20
|
-
visit_default(*args)
|
21
|
-
end
|
22
|
-
|
23
|
-
def visit_collection(_objects)
|
24
|
-
raise NotImplementedError
|
25
|
-
end
|
26
|
-
alias :visit_Array :visit_collection
|
27
|
-
|
28
|
-
def visit_Arel_Nodes_Unary(object)
|
29
|
-
visit(object.expr)
|
30
|
-
end
|
31
|
-
|
32
|
-
def visit_Arel_Nodes_Binary(object)
|
33
|
-
visit_collection([object.left, object.right])
|
34
|
-
end
|
35
|
-
|
36
|
-
def visit_Arel_Nodes_Function(object)
|
37
|
-
visit_collection(object.expressions)
|
38
|
-
end
|
39
|
-
|
40
|
-
def visit_Arel_Nodes_Case(object)
|
41
|
-
visit_collection([object.case, object.conditions, object.default])
|
42
|
-
end
|
43
|
-
|
44
|
-
def visit_Arel_Nodes_And(object)
|
45
|
-
visit_Array(object.children)
|
46
|
-
end
|
47
|
-
|
48
|
-
def visit_Arel_Nodes_Node(object)
|
49
|
-
visit_default(object)
|
50
|
-
end
|
51
|
-
|
52
|
-
def visit_Arel_Attributes_Attribute(object)
|
53
|
-
visit_default(object)
|
54
|
-
end
|
55
|
-
|
56
|
-
def visit_default(_object)
|
57
|
-
nil
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
@@ -1,28 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Mobility
|
4
|
-
module Sequel
|
5
|
-
=begin
|
6
|
-
|
7
|
-
Internal class used to force Sequel model to notice changes when mobility
|
8
|
-
setter method is called.
|
9
|
-
|
10
|
-
=end
|
11
|
-
class ColumnChanges < Module
|
12
|
-
# @param [Array<String>] attributes Backend attributes
|
13
|
-
def initialize(attributes, column_affix: "%s")
|
14
|
-
attributes.each do |attribute|
|
15
|
-
define_method "#{attribute}=" do |value, **options|
|
16
|
-
if !options[:super] && send(attribute) != value
|
17
|
-
locale = options[:locale] || Mobility.locale
|
18
|
-
column = (column_affix % attribute).to_sym
|
19
|
-
attribute_with_locale = :"#{attribute}_#{Mobility.normalize_locale(locale)}"
|
20
|
-
@changed_columns = changed_columns | [column, attribute.to_sym, attribute_with_locale]
|
21
|
-
end
|
22
|
-
super(value, **options)
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
@@ -1,21 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Mobility
|
4
|
-
module Sequel
|
5
|
-
=begin
|
6
|
-
|
7
|
-
Internal class used to initialize column value(s) by default to a hash.
|
8
|
-
|
9
|
-
=end
|
10
|
-
class HashInitializer < Module
|
11
|
-
def initialize(*columns)
|
12
|
-
class_eval <<-EOM, __FILE__, __LINE__ + 1
|
13
|
-
def initialize_set(values)
|
14
|
-
#{columns.map { |c| "self[:#{c}] = {}" }.join(';')}
|
15
|
-
super
|
16
|
-
end
|
17
|
-
EOM
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
@@ -1,20 +0,0 @@
|
|
1
|
-
module Mobility
|
2
|
-
module Sequel
|
3
|
-
=begin
|
4
|
-
|
5
|
-
Module included in translation class dynamically generated by
|
6
|
-
{Backends::Sequel::Table} backend.
|
7
|
-
|
8
|
-
=end
|
9
|
-
module ModelTranslation
|
10
|
-
def self.included(base)
|
11
|
-
base.plugin :validation_helpers
|
12
|
-
end
|
13
|
-
|
14
|
-
def validate
|
15
|
-
super
|
16
|
-
validates_presence [:locale]
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
data/lib/mobility/sequel/sql.rb
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
module Mobility
|
2
|
-
module Sequel
|
3
|
-
module SQL
|
4
|
-
class QualifiedIdentifier < ::Sequel::SQL::QualifiedIdentifier
|
5
|
-
attr_reader :backend_class, :locale, :attribute_name
|
6
|
-
|
7
|
-
def initialize(table, column, locale, backend_class, attribute_name: nil)
|
8
|
-
@backend_class = backend_class
|
9
|
-
@locale = locale
|
10
|
-
@attribute_name = attribute_name || column
|
11
|
-
super(table, column)
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
@@ -1,53 +0,0 @@
|
|
1
|
-
module Mobility
|
2
|
-
module Sequel
|
3
|
-
module Translation
|
4
|
-
def self.included(base)
|
5
|
-
base.class_eval do
|
6
|
-
plugin :validation_helpers
|
7
|
-
|
8
|
-
# Paraphased from sequel_polymorphic gem
|
9
|
-
#
|
10
|
-
model = underscore(self.to_s)
|
11
|
-
plural_model = pluralize(model)
|
12
|
-
many_to_one :translatable,
|
13
|
-
reciprocal: plural_model.to_sym,
|
14
|
-
reciprocal_type: :many_to_one,
|
15
|
-
setter: (proc do |able_instance|
|
16
|
-
self[:translatable_id] = (able_instance.pk if able_instance)
|
17
|
-
self[:translatable_type] = (able_instance.class.name if able_instance)
|
18
|
-
end),
|
19
|
-
dataset: (proc do
|
20
|
-
translatable_type = send :translatable_type
|
21
|
-
translatable_id = send :translatable_id
|
22
|
-
return if translatable_type.nil? || translatable_id.nil?
|
23
|
-
klass = self.class.send(:constantize, translatable_type)
|
24
|
-
klass.where(klass.primary_key => translatable_id)
|
25
|
-
end),
|
26
|
-
eager_loader: (proc do |eo|
|
27
|
-
id_map = {}
|
28
|
-
eo[:rows].each do |model|
|
29
|
-
model_able_type = model.send :translatable_type
|
30
|
-
model_able_id = model.send :translatable_id
|
31
|
-
model.associations[:translatable] = nil
|
32
|
-
((id_map[model_able_type] ||= {})[model_able_id] ||= []) << model if !model_able_type.nil? && !model_able_id.nil?
|
33
|
-
end
|
34
|
-
id_map.each do |klass_name, id_map|
|
35
|
-
klass = constantize(camelize(klass_name))
|
36
|
-
klass.where(klass.primary_key=>id_map.keys).all do |related_obj|
|
37
|
-
id_map[related_obj.pk].each do |model|
|
38
|
-
model.associations[:translatable] = related_obj
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end)
|
43
|
-
|
44
|
-
def validate
|
45
|
-
super
|
46
|
-
validates_presence [:locale, :key, :translatable_id, :translatable_type]
|
47
|
-
validates_unique [:locale, :key, :translatable_id, :translatable_type]
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|