mobility 0.7.6 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) 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 +14 -3
  5. data/Gemfile.lock +57 -0
  6. data/README.md +15 -4
  7. data/lib/mobility.rb +17 -1
  8. data/lib/mobility/active_record/uniqueness_validator.rb +1 -1
  9. data/lib/mobility/arel/nodes.rb +0 -3
  10. data/lib/mobility/arel/nodes/pg_ops.rb +0 -4
  11. data/lib/mobility/attributes.rb +42 -25
  12. data/lib/mobility/backends/active_record.rb +2 -2
  13. data/lib/mobility/backends/active_record/column.rb +2 -2
  14. data/lib/mobility/backends/active_record/key_value.rb +6 -9
  15. data/lib/mobility/backends/active_record/table.rb +6 -7
  16. data/lib/mobility/backends/column.rb +2 -2
  17. data/lib/mobility/backends/key_value.rb +5 -0
  18. data/lib/mobility/backends/sequel.rb +24 -11
  19. data/lib/mobility/backends/sequel/column.rb +4 -3
  20. data/lib/mobility/backends/sequel/container.rb +21 -12
  21. data/lib/mobility/backends/sequel/hstore.rb +11 -3
  22. data/lib/mobility/backends/sequel/json.rb +11 -3
  23. data/lib/mobility/backends/sequel/jsonb.rb +35 -3
  24. data/lib/mobility/backends/sequel/key_value.rb +97 -17
  25. data/lib/mobility/backends/sequel/serialized.rb +5 -4
  26. data/lib/mobility/backends/sequel/table.rb +95 -26
  27. data/lib/mobility/backends/table.rb +4 -0
  28. data/lib/mobility/configuration.rb +1 -1
  29. data/lib/mobility/plugins/active_record/query.rb +52 -26
  30. data/lib/mobility/plugins/locale_accessors.rb +3 -2
  31. data/lib/mobility/plugins/query.rb +3 -0
  32. data/lib/mobility/plugins/sequel/query.rb +140 -0
  33. data/lib/mobility/sequel.rb +0 -14
  34. data/lib/mobility/sequel/sql.rb +16 -0
  35. data/lib/mobility/version.rb +1 -1
  36. data/lib/rails/generators/mobility/templates/column_translations.rb +1 -1
  37. data/lib/rails/generators/mobility/templates/initializer.rb +3 -2
  38. data/lib/rails/generators/mobility/translations_generator.rb +1 -1
  39. metadata +27 -46
  40. metadata.gz.sig +1 -1
  41. data/lib/mobility/backends/active_record/query_methods.rb +0 -50
  42. data/lib/mobility/backends/sequel/column/query_methods.rb +0 -29
  43. data/lib/mobility/backends/sequel/container/json_query_methods.rb +0 -41
  44. data/lib/mobility/backends/sequel/container/jsonb_query_methods.rb +0 -41
  45. data/lib/mobility/backends/sequel/hstore/query_methods.rb +0 -34
  46. data/lib/mobility/backends/sequel/json/query_methods.rb +0 -34
  47. data/lib/mobility/backends/sequel/jsonb/query_methods.rb +0 -34
  48. data/lib/mobility/backends/sequel/key_value/query_methods.rb +0 -58
  49. data/lib/mobility/backends/sequel/pg_query_methods.rb +0 -114
  50. data/lib/mobility/backends/sequel/query_methods.rb +0 -36
  51. data/lib/mobility/backends/sequel/serialized/query_methods.rb +0 -22
  52. data/lib/mobility/backends/sequel/table/query_methods.rb +0 -58
@@ -1,34 +0,0 @@
1
- # frozen_string_literal: true
2
- require "mobility/backends/sequel/pg_query_methods"
3
- require "mobility/backends/sequel/query_methods"
4
-
5
- Sequel.extension :pg_json, :pg_json_ops
6
-
7
- module Mobility
8
- module Backends
9
- module Sequel
10
- class Jsonb::QueryMethods < QueryMethods
11
- include PgQueryMethods
12
-
13
- def matches(key, locale)
14
- build_op(key)[locale]
15
- end
16
-
17
- def exists(key, locale)
18
- build_op(key).has_key?(locale)
19
- end
20
-
21
- def quote(value)
22
- value && value.to_json
23
- end
24
-
25
- private
26
-
27
- def build_op(key)
28
- ::Sequel.pg_jsonb_op(column_name(key))
29
- end
30
- end
31
- Jsonb.private_constant :QueryMethods
32
- end
33
- end
34
- end
@@ -1,58 +0,0 @@
1
- # frozen_string_literal: true
2
- require "mobility/backends/sequel/query_methods"
3
-
4
- module Mobility
5
- module Backends
6
- module Sequel
7
- class KeyValue::QueryMethods < QueryMethods
8
- def initialize(attributes, association_name: nil, class_name: nil, **)
9
- super
10
-
11
- define_join_method(association_name, class_name)
12
- define_query_methods(association_name)
13
- end
14
-
15
- private
16
-
17
- def define_join_method(association_name, translation_class)
18
- define_method :"join_#{association_name}" do |*attributes, **options|
19
- attributes.inject(self) do |relation, attribute|
20
- join_type = options[:outer_join] ? :left_outer : :inner
21
- relation.join_table(join_type,
22
- translation_class.table_name,
23
- {
24
- key: attribute.to_s,
25
- locale: Mobility.locale.to_s,
26
- translatable_type: model.name,
27
- translatable_id: ::Sequel[:"#{model.table_name}"][:id]
28
- },
29
- table_alias: "#{attribute}_#{association_name}")
30
- end
31
- end
32
- end
33
-
34
- def define_query_methods(association_name)
35
- q = self
36
-
37
- %w[exclude or where].each do |method_name|
38
- define_method method_name do |*conds, &block|
39
- if i18n_keys = q.extract_attributes(conds.first)
40
- cond = conds.first.dup
41
- i18n_nulls = i18n_keys.select { |key| cond[key].nil? }
42
- i18n_keys.each do |attr|
43
- cond[::Sequel[:"#{attr}_#{association_name}"][:value]] = q.collapse cond.delete(attr)
44
- end
45
- super(cond, &block).
46
- send("join_#{association_name}", *(i18n_keys - i18n_nulls), outer_join: method_name == "or").
47
- send("join_#{association_name}", *i18n_nulls, outer_join: true)
48
- else
49
- super(*conds, &block)
50
- end
51
- end
52
- end
53
- end
54
- end
55
- KeyValue.private_constant :QueryMethods
56
- end
57
- end
58
- end
@@ -1,114 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Mobility
4
- module Backends
5
- module Sequel
6
- =begin
7
-
8
- Internal module builder defining query methods for Postgres backends. Including
9
- class must define three methods:
10
-
11
- - a method +matches+ which takes a key (column name) and a locale to match and
12
- returns an SQL expression checking that the column has the specified value
13
- in the specified locale
14
- - a method +exists+ which takes a key (column name) and locale, and returns
15
- an SQL expression which checks that the column has a value in the locale
16
- - a method +quote+ which quotes the value to be matched
17
-
18
- (The +matches+/+exists+/+quote+ methods are implemented slightly differently
19
- for hstore/json/jsonb/container backends.)
20
-
21
- @see Mobility::Backends::Sequel::Json::QueryMethods
22
- @see Mobility::Backends::Sequel::Jsonb::QueryMethods
23
- @see Mobility::Backends::Sequel::Hstore::QueryMethods
24
- @see Mobility::Backends::Sequel::Container::JsonQueryMethods
25
- @see Mobility::Backends::Sequel::Container::JsonbQueryMethods
26
-
27
- =end
28
- module PgQueryMethods
29
- attr_reader :column_affix
30
-
31
- def initialize(attributes, options)
32
- super
33
- @column_affix = options[:column_affix]
34
- define_query_methods
35
- end
36
-
37
- # Create query for conditions and translated keys
38
- # @note This is a destructive action, it will alter +cond+.
39
- #
40
- # @param [Hash] cond Hash of attribute/value pairs
41
- # @param [Array] keys Translated attribute names
42
- # @param [Boolean] invert Invert query, true for +exclude+, false otherwise
43
- # @return [Sequel::SQL::Expression] Query expression
44
- def create_query!(cond, keys, invert = false)
45
- keys.map { |key|
46
- values = cond.delete(key)
47
- values = values.is_a?(Array) ? values.uniq: [values]
48
- create_query_op(key, values, invert)
49
- }.inject(invert ? :| : :&)
50
- end
51
-
52
- def matches(_key, _locale)
53
- raise NotImplementedError
54
- end
55
-
56
- def exists(_key, _locale)
57
- raise NotImplementedError
58
- end
59
-
60
- def quote(_value)
61
- raise NotImplementedError
62
- end
63
-
64
- private
65
-
66
- def define_query_methods
67
- %w[exclude or where].each do |method_name|
68
- define_query_method(method_name)
69
- end
70
- end
71
-
72
- def define_query_method(method_name)
73
- q = self
74
-
75
- define_method method_name do |*cond, &block|
76
- if i18n_keys = q.extract_attributes(cond.first)
77
- cond = cond.first
78
-
79
- query = q.create_query!(cond, i18n_keys, method_name == "exclude")
80
- if method_name == "or"
81
- query = ::Sequel.&(cond, query) unless cond.empty?
82
- super(query, &block)
83
- else
84
- super(cond, &block).where(query)
85
- end
86
- else
87
- super(*cond, &block)
88
- end
89
- end
90
- end
91
-
92
- def create_query_op(key, values, invert)
93
- locale = Mobility.locale.to_s
94
- values = values.map(&method(:quote))
95
- values = values.first if values.size == 1
96
-
97
- match = matches(key, locale) =~ values
98
-
99
- if invert
100
- exists(key, locale) & ~match
101
- else
102
- values.nil? ? ~exists(key, locale) : match
103
- end
104
- end
105
-
106
-
107
- def column_name(attribute)
108
- (column_affix % attribute).to_sym
109
- end
110
- end
111
- private_constant :PgQueryMethods
112
- end
113
- end
114
- end
@@ -1,36 +0,0 @@
1
- # frozen_string_literal: true
2
- require "mobility/util"
3
-
4
- module Mobility
5
- module Backends
6
- module Sequel
7
- =begin
8
-
9
- Defines query method overrides to handle translated attributes for Sequel
10
- models. For details see backend-specific subclasses.
11
-
12
- =end
13
- class QueryMethods < Module
14
- # @param [Array<String>] attributes Translated attributes
15
- def initialize(attributes, _)
16
- @attributes = attributes.map(&:to_sym)
17
-
18
- @attributes.each do |attribute|
19
- define_method :"first_by_#{attribute}" do |value|
20
- where(attribute => value).select_all(model.table_name).first
21
- end
22
- end
23
- end
24
-
25
- def extract_attributes(cond)
26
- cond.is_a?(Hash) && Util.presence(cond.keys & @attributes)
27
- end
28
-
29
- def collapse(value)
30
- value.is_a?(Array) ? value.uniq : value
31
- end
32
- end
33
- private_constant :QueryMethods
34
- end
35
- end
36
- end
@@ -1,22 +0,0 @@
1
- # frozen_string_literal: true
2
- require "mobility/backends/sequel/query_methods"
3
-
4
- module Mobility
5
- module Backends
6
- module Sequel
7
- class Serialized::QueryMethods < QueryMethods
8
- include Backends::Serialized
9
-
10
- def initialize(attributes, _)
11
- super
12
- q = self
13
-
14
- define_method :where do |*cond, &block|
15
- q.check_opts(cond.first) || super(*cond, &block)
16
- end
17
- end
18
- end
19
- Serialized.private_constant :QueryMethods
20
- end
21
- end
22
- end
@@ -1,58 +0,0 @@
1
- # frozen_string_literal: true
2
- require "mobility/backends/sequel/query_methods"
3
-
4
- module Mobility
5
- module Backends
6
- module Sequel
7
- class Table::QueryMethods < QueryMethods
8
- def initialize(attributes, association_name: nil, model_class: nil, subclass_name: nil, **options)
9
- super
10
- translation_class = model_class.const_get(subclass_name)
11
-
12
- define_join_method(association_name, translation_class, **options)
13
- define_query_methods(association_name, translation_class, **options)
14
- end
15
-
16
- def define_join_method(association_name, translation_class, table_name: nil, foreign_key: nil, **)
17
- define_method :"join_#{association_name}" do |**options|
18
- if joins = @opts[:join]
19
- # Return self if we've already joined this table
20
- return self if joins.any? { |clause| clause.table_expr == table_name }
21
- end
22
-
23
- join_type = options[:outer_join] ? :left_outer : :inner
24
- join_table(join_type,
25
- translation_class.table_name,
26
- {
27
- locale: Mobility.locale.to_s,
28
- foreign_key => ::Sequel[model.table_name][:id]
29
- })
30
- end
31
- end
32
-
33
- def define_query_methods(association_name, translation_class, **)
34
- q = self
35
-
36
- # See note in AR Table QueryMethods class about limitations of
37
- # query methods on translated attributes when searching on nil values.
38
- #
39
- %w[exclude or where].each do |method_name|
40
- define_method method_name do |*conds, &block|
41
- if i18n_keys = q.extract_attributes(conds.first)
42
- cond = conds.first.dup
43
- outer_join = method_name == "or" || i18n_keys.all? { |key| cond[key].nil? }
44
- i18n_keys.each do |attr|
45
- cond[::Sequel[translation_class.table_name][attr]] = q.collapse cond.delete(attr)
46
- end
47
- super(cond, &block).send("join_#{association_name}", outer_join: outer_join)
48
- else
49
- super(*conds, &block)
50
- end
51
- end
52
- end
53
- end
54
- end
55
- Table.private_constant :QueryMethods
56
- end
57
- end
58
- end