mobility 0.6.0 → 0.7.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 +5 -5
- checksums.yaml.gz.sig +3 -2
- data.tar.gz.sig +0 -0
- data/CHANGELOG.md +39 -1
- data/Gemfile.lock +65 -10
- data/README.md +63 -27
- data/lib/mobility.rb +16 -31
- data/lib/mobility/active_record.rb +2 -12
- data/lib/mobility/active_record/uniqueness_validator.rb +9 -8
- data/lib/mobility/arel.rb +20 -0
- data/lib/mobility/arel/nodes.rb +16 -0
- data/lib/mobility/arel/nodes/pg_ops.rb +136 -0
- data/lib/mobility/arel/visitor.rb +61 -0
- data/lib/mobility/attributes.rb +82 -19
- data/lib/mobility/backend.rb +53 -8
- data/lib/mobility/backend_resetter.rb +2 -1
- data/lib/mobility/backends/active_record.rb +31 -11
- data/lib/mobility/backends/active_record/column.rb +7 -3
- data/lib/mobility/backends/active_record/container.rb +23 -21
- data/lib/mobility/backends/active_record/hstore.rb +11 -6
- data/lib/mobility/backends/active_record/json.rb +22 -16
- data/lib/mobility/backends/active_record/jsonb.rb +22 -16
- data/lib/mobility/backends/active_record/key_value.rb +123 -15
- data/lib/mobility/backends/active_record/pg_hash.rb +1 -2
- data/lib/mobility/backends/active_record/serialized.rb +7 -6
- data/lib/mobility/backends/active_record/table.rb +145 -24
- data/lib/mobility/backends/hash_valued.rb +15 -10
- data/lib/mobility/backends/key_value.rb +12 -12
- data/lib/mobility/backends/sequel/container.rb +3 -9
- data/lib/mobility/backends/sequel/hstore.rb +2 -2
- data/lib/mobility/backends/sequel/json.rb +15 -15
- data/lib/mobility/backends/sequel/jsonb.rb +14 -14
- data/lib/mobility/backends/sequel/key_value.rb +0 -11
- data/lib/mobility/backends/sequel/pg_hash.rb +2 -3
- data/lib/mobility/backends/sequel/pg_query_methods.rb +1 -1
- data/lib/mobility/backends/sequel/query_methods.rb +3 -3
- data/lib/mobility/backends/sequel/serialized.rb +2 -2
- data/lib/mobility/backends/sequel/table.rb +10 -11
- data/lib/mobility/backends/table.rb +17 -8
- data/lib/mobility/configuration.rb +4 -1
- data/lib/mobility/interface.rb +0 -0
- data/lib/mobility/plugins.rb +1 -0
- data/lib/mobility/plugins/active_record/query.rb +192 -0
- data/lib/mobility/plugins/cache.rb +1 -2
- data/lib/mobility/plugins/default.rb +28 -14
- data/lib/mobility/plugins/fallbacks.rb +1 -1
- data/lib/mobility/plugins/locale_accessors.rb +13 -9
- data/lib/mobility/plugins/presence.rb +15 -7
- data/lib/mobility/plugins/query.rb +28 -0
- data/lib/mobility/translates.rb +9 -9
- data/lib/mobility/version.rb +1 -1
- data/lib/rails/generators/mobility/templates/initializer.rb +1 -0
- metadata +10 -15
- metadata.gz.sig +0 -0
- data/lib/mobility/accumulator.rb +0 -33
- data/lib/mobility/adapter.rb +0 -20
- data/lib/mobility/backends/active_record/column/query_methods.rb +0 -42
- data/lib/mobility/backends/active_record/container/json_query_methods.rb +0 -36
- data/lib/mobility/backends/active_record/container/jsonb_query_methods.rb +0 -33
- data/lib/mobility/backends/active_record/hstore/query_methods.rb +0 -25
- data/lib/mobility/backends/active_record/json/query_methods.rb +0 -30
- data/lib/mobility/backends/active_record/jsonb/query_methods.rb +0 -26
- data/lib/mobility/backends/active_record/key_value/query_methods.rb +0 -76
- data/lib/mobility/backends/active_record/pg_query_methods.rb +0 -154
- data/lib/mobility/backends/active_record/serialized/query_methods.rb +0 -34
- data/lib/mobility/backends/active_record/table/query_methods.rb +0 -105
@@ -1,25 +0,0 @@
|
|
1
|
-
require 'mobility/backends/active_record/pg_query_methods'
|
2
|
-
require 'mobility/backends/active_record/query_methods'
|
3
|
-
|
4
|
-
module Mobility
|
5
|
-
module Backends
|
6
|
-
module ActiveRecord
|
7
|
-
class Hstore::QueryMethods < QueryMethods
|
8
|
-
include PgQueryMethods
|
9
|
-
|
10
|
-
def matches(key, locale)
|
11
|
-
build_infix(:'->', arel_table[column_name(key)], build_quoted(locale))
|
12
|
-
end
|
13
|
-
|
14
|
-
def exists(key, locale)
|
15
|
-
build_infix(:'?', arel_table[column_name(key)], build_quoted(locale))
|
16
|
-
end
|
17
|
-
|
18
|
-
def quote(value)
|
19
|
-
build_quoted(value)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
Hstore.private_constant :QueryMethods
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
@@ -1,30 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
require 'mobility/backends/active_record/pg_query_methods'
|
3
|
-
require "mobility/backends/active_record/query_methods"
|
4
|
-
|
5
|
-
module Mobility
|
6
|
-
module Backends
|
7
|
-
module ActiveRecord
|
8
|
-
class Json::QueryMethods < QueryMethods
|
9
|
-
include PgQueryMethods
|
10
|
-
|
11
|
-
def matches(key, locale)
|
12
|
-
build_infix(:'->>', arel_table[column_name(key)], build_quoted(locale))
|
13
|
-
end
|
14
|
-
|
15
|
-
def exists(key, locale)
|
16
|
-
absent(key, locale).not
|
17
|
-
end
|
18
|
-
|
19
|
-
def absent(key, locale)
|
20
|
-
matches(key, locale).eq(nil)
|
21
|
-
end
|
22
|
-
|
23
|
-
def quote(value)
|
24
|
-
value.to_s
|
25
|
-
end
|
26
|
-
end
|
27
|
-
Json.private_constant :QueryMethods
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
@@ -1,26 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
require 'mobility/backends/active_record/pg_query_methods'
|
3
|
-
require "mobility/backends/active_record/query_methods"
|
4
|
-
|
5
|
-
module Mobility
|
6
|
-
module Backends
|
7
|
-
module ActiveRecord
|
8
|
-
class Jsonb::QueryMethods < QueryMethods
|
9
|
-
include PgQueryMethods
|
10
|
-
|
11
|
-
def matches(key, locale)
|
12
|
-
build_infix(:'->', arel_table[column_name(key)], build_quoted(locale))
|
13
|
-
end
|
14
|
-
|
15
|
-
def exists(key, locale)
|
16
|
-
build_infix(:'?', arel_table[column_name(key)], build_quoted(locale))
|
17
|
-
end
|
18
|
-
|
19
|
-
def quote(value)
|
20
|
-
build_quoted(value.to_json)
|
21
|
-
end
|
22
|
-
end
|
23
|
-
Jsonb.private_constant :QueryMethods
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
@@ -1,76 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
require "mobility/backends/active_record/query_methods"
|
3
|
-
|
4
|
-
module Mobility
|
5
|
-
module Backends
|
6
|
-
module ActiveRecord
|
7
|
-
class KeyValue::QueryMethods < QueryMethods
|
8
|
-
def initialize(attributes, association_name: nil, class_name: nil, **)
|
9
|
-
super
|
10
|
-
@association_name = association_name
|
11
|
-
|
12
|
-
define_join_method(association_name, class_name)
|
13
|
-
define_query_methods(association_name)
|
14
|
-
end
|
15
|
-
|
16
|
-
def extended(relation)
|
17
|
-
super
|
18
|
-
association_name = @association_name
|
19
|
-
q = self
|
20
|
-
|
21
|
-
mod = Module.new do
|
22
|
-
define_method :not do |opts, *rest|
|
23
|
-
if i18n_keys = q.extract_attributes(opts)
|
24
|
-
opts = opts.with_indifferent_access
|
25
|
-
i18n_keys.each do |attr|
|
26
|
-
opts["#{attr}_#{association_name}"] = { value: q.collapse(opts.delete(attr)) }
|
27
|
-
end
|
28
|
-
super(opts, *rest).send(:"join_#{association_name}", *i18n_keys)
|
29
|
-
else
|
30
|
-
super(opts, *rest)
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
relation.mobility_where_chain.include(mod)
|
35
|
-
end
|
36
|
-
|
37
|
-
private
|
38
|
-
|
39
|
-
def define_join_method(association_name, translation_class)
|
40
|
-
define_method :"join_#{association_name}" do |*attributes, **options|
|
41
|
-
attributes.inject(self) do |relation, attribute|
|
42
|
-
t = translation_class.arel_table.alias("#{attribute}_#{association_name}")
|
43
|
-
m = arel_table
|
44
|
-
join_type = options[:outer_join] ? Arel::Nodes::OuterJoin : Arel::Nodes::InnerJoin
|
45
|
-
relation.joins(m.join(t, join_type).
|
46
|
-
on(t[:key].eq(attribute).
|
47
|
-
and(t[:locale].eq(Mobility.locale).
|
48
|
-
and(t[:translatable_type].eq(base_class.name).
|
49
|
-
and(t[:translatable_id].eq(m[:id]))))).join_sources)
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
def define_query_methods(association_name)
|
55
|
-
q = self
|
56
|
-
|
57
|
-
define_method :where! do |opts, *rest|
|
58
|
-
if i18n_keys = q.extract_attributes(opts)
|
59
|
-
opts = opts.with_indifferent_access
|
60
|
-
i18n_nulls = i18n_keys.reject { |key| opts[key] && [*opts[key]].all? }
|
61
|
-
i18n_keys.each do |attr|
|
62
|
-
opts["#{attr}_#{association_name}"] = { value: q.collapse(opts.delete(attr)) }
|
63
|
-
end
|
64
|
-
super(opts, *rest).
|
65
|
-
send("join_#{association_name}", *(i18n_keys - i18n_nulls)).
|
66
|
-
send("join_#{association_name}", *i18n_nulls, outer_join: true)
|
67
|
-
else
|
68
|
-
super(opts, *rest)
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
73
|
-
KeyValue.private_constant :QueryMethods
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
@@ -1,154 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Mobility
|
4
|
-
module Backends
|
5
|
-
module ActiveRecord
|
6
|
-
=begin
|
7
|
-
|
8
|
-
Internal module builder defining query methods for Postgres backends. Including
|
9
|
-
class must define the following methods:
|
10
|
-
|
11
|
-
- a method +matches+ which takes an attribute, and a locale to match, and
|
12
|
-
returns an Arel node which is used to check that the attribute has the
|
13
|
-
specified value in the specified locale
|
14
|
-
- a method +exists+ which takes an attribute and a locale and
|
15
|
-
returns an Arel node checking that a value exists for the attribute in the
|
16
|
-
specified locale
|
17
|
-
- a method +quote+ which quotes the value to be matched
|
18
|
-
- an optional method +absent+ which takes an attribute and a locale and returns
|
19
|
-
an Arel node checking that the value for the attribute does not exist in the
|
20
|
-
specified locale. Defaults to +exists(key, locale).not+.
|
21
|
-
|
22
|
-
This module avoids a lot of duplication between hstore/json/jsonb/container
|
23
|
-
backend querying code.
|
24
|
-
|
25
|
-
@see Mobility::Backends::ActiveRecord::Json::QueryMethods
|
26
|
-
@see Mobility::Backends::ActiveRecord::Jsonb::QueryMethods
|
27
|
-
@see Mobility::Backends::ActiveRecord::Hstore::QueryMethods
|
28
|
-
@see Mobility::Backends::ActiveRecord::Container::JsonQueryMethods
|
29
|
-
@see Mobility::Backends::ActiveRecord::Container::JsonbQueryMethods
|
30
|
-
|
31
|
-
=end
|
32
|
-
module PgQueryMethods
|
33
|
-
attr_reader :arel_table, :column_affix
|
34
|
-
|
35
|
-
def initialize(attributes, options)
|
36
|
-
super
|
37
|
-
@arel_table = options[:model_class].arel_table
|
38
|
-
@column_affix = "#{options[:column_prefix]}%s#{options[:column_suffix]}"
|
39
|
-
|
40
|
-
q = self
|
41
|
-
|
42
|
-
define_method :where! do |opts, *rest|
|
43
|
-
if i18n_keys = q.extract_attributes(opts)
|
44
|
-
opts = opts.with_indifferent_access
|
45
|
-
query = q.create_query!(opts, i18n_keys)
|
46
|
-
|
47
|
-
opts.empty? ? super(query) : super(opts, *rest).where(query)
|
48
|
-
else
|
49
|
-
super(opts, *rest)
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
def extended(relation)
|
55
|
-
super
|
56
|
-
q = self
|
57
|
-
|
58
|
-
mod = Module.new do
|
59
|
-
define_method :not do |opts, *rest|
|
60
|
-
if i18n_keys = q.extract_attributes(opts)
|
61
|
-
opts = opts.with_indifferent_access
|
62
|
-
query = q.create_query!(opts, i18n_keys, inverse: true)
|
63
|
-
|
64
|
-
super(opts, *rest).where(query)
|
65
|
-
else
|
66
|
-
super(opts, *rest)
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
relation.mobility_where_chain.include(mod)
|
71
|
-
end
|
72
|
-
|
73
|
-
# Create +where+ query for specified key and value
|
74
|
-
#
|
75
|
-
# @note This is a destructive operation, it will modify +opts+.
|
76
|
-
# @param [Hash] opts Hash of attribute/value pairs
|
77
|
-
# @param [Array] keys Translated attribute names
|
78
|
-
# @option [Boolean] inverse (false) If true, create a +not+ query
|
79
|
-
# instead of a +where+ query
|
80
|
-
# @return [Arel::Node] Arel node to pass to +where+
|
81
|
-
def create_query!(opts, keys, inverse: false)
|
82
|
-
keys.map { |key|
|
83
|
-
values = Array.wrap(opts.delete(key)).uniq
|
84
|
-
send(inverse ? :not_query : :where_query, key, values, Mobility.locale)
|
85
|
-
}.inject(&:and)
|
86
|
-
end
|
87
|
-
|
88
|
-
def matches(_key, _locale)
|
89
|
-
raise NotImplementedError
|
90
|
-
end
|
91
|
-
|
92
|
-
def exists(_key, _locale)
|
93
|
-
raise NotImplementedError
|
94
|
-
end
|
95
|
-
|
96
|
-
def quote(_value)
|
97
|
-
raise NotImplementedError
|
98
|
-
end
|
99
|
-
|
100
|
-
def absent(key, locale)
|
101
|
-
exists(key, locale).not
|
102
|
-
end
|
103
|
-
|
104
|
-
private
|
105
|
-
|
106
|
-
def build_infix(*args)
|
107
|
-
arel_table.grouping(Arel::Nodes::InfixOperation.new(*args))
|
108
|
-
end
|
109
|
-
|
110
|
-
def build_quoted(value)
|
111
|
-
Arel::Nodes.build_quoted(value.to_s)
|
112
|
-
end
|
113
|
-
|
114
|
-
def column_name(attribute)
|
115
|
-
column_affix % attribute
|
116
|
-
end
|
117
|
-
|
118
|
-
# Create +where+ query for specified key and values
|
119
|
-
#
|
120
|
-
# @param [String] key Translated attribute name
|
121
|
-
# @param [Array] values Values to match
|
122
|
-
# @param [Symbol] locale Locale to query for
|
123
|
-
# @return [Arel::Node] Arel node to pass to +where+
|
124
|
-
def where_query(key, values, locale)
|
125
|
-
nils, vals = values.partition(&:nil?)
|
126
|
-
|
127
|
-
return absent(key, locale) if vals.empty?
|
128
|
-
|
129
|
-
node = matches(key, locale)
|
130
|
-
vals = vals.map(&method(:quote))
|
131
|
-
|
132
|
-
query = vals.size == 1 ? node.eq(vals.first) : node.in(vals)
|
133
|
-
query = query.or(absent(key, locale)) unless nils.empty?
|
134
|
-
query
|
135
|
-
end
|
136
|
-
|
137
|
-
# Create +not+ query for specified key and values
|
138
|
-
#
|
139
|
-
# @param [String] key Translated attribute name
|
140
|
-
# @param [Array] values Values to match
|
141
|
-
# @param [Symbol] locale Locale to query for
|
142
|
-
# @return [Arel::Node] Arel node to pass to +where+
|
143
|
-
def not_query(key, values, locale)
|
144
|
-
vals = values.map(&method(:quote))
|
145
|
-
node = matches(key, locale)
|
146
|
-
|
147
|
-
query = vals.size == 1 ? node.eq(vals.first) : node.in(vals)
|
148
|
-
query.not.and(exists(key, locale))
|
149
|
-
end
|
150
|
-
end
|
151
|
-
private_constant :PgQueryMethods
|
152
|
-
end
|
153
|
-
end
|
154
|
-
end
|
@@ -1,34 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
require "mobility/backends/active_record/query_methods"
|
3
|
-
|
4
|
-
module Mobility
|
5
|
-
module Backends
|
6
|
-
module ActiveRecord
|
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 |opts, *rest|
|
15
|
-
q.check_opts(opts) || super(opts, *rest)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
def extended(relation)
|
20
|
-
super
|
21
|
-
q = self
|
22
|
-
|
23
|
-
mod = Module.new do
|
24
|
-
define_method :not do |opts, *rest|
|
25
|
-
q.check_opts(opts) || super(opts, *rest)
|
26
|
-
end
|
27
|
-
end
|
28
|
-
relation.mobility_where_chain.include(mod)
|
29
|
-
end
|
30
|
-
end
|
31
|
-
Serialized.private_constant :QueryMethods
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
@@ -1,105 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
require "mobility/backends/active_record/query_methods"
|
3
|
-
|
4
|
-
module Mobility
|
5
|
-
module Backends
|
6
|
-
module ActiveRecord
|
7
|
-
class Table::QueryMethods < QueryMethods
|
8
|
-
def initialize(attributes, association_name: nil, model_class: nil, subclass_name: nil, **options)
|
9
|
-
super
|
10
|
-
|
11
|
-
@association_name = association_name
|
12
|
-
@translation_class = translation_class = model_class.const_get(subclass_name)
|
13
|
-
|
14
|
-
define_join_method(association_name, translation_class, **options)
|
15
|
-
define_query_methods(association_name, translation_class, **options)
|
16
|
-
end
|
17
|
-
|
18
|
-
def extended(relation)
|
19
|
-
super
|
20
|
-
association_name = @association_name
|
21
|
-
translation_class = @translation_class
|
22
|
-
q = self
|
23
|
-
|
24
|
-
mod = Module.new do
|
25
|
-
define_method :not do |opts, *rest|
|
26
|
-
if i18n_keys = q.extract_attributes(opts)
|
27
|
-
opts = opts.with_indifferent_access
|
28
|
-
i18n_keys.each do |attr|
|
29
|
-
opts["#{translation_class.table_name}.#{attr}"] = q.collapse opts.delete(attr)
|
30
|
-
end
|
31
|
-
super(opts, *rest).send("join_#{association_name}")
|
32
|
-
else
|
33
|
-
super(opts, *rest)
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
relation.mobility_where_chain.include(mod)
|
38
|
-
end
|
39
|
-
|
40
|
-
private
|
41
|
-
|
42
|
-
def define_join_method(association_name, translation_class, foreign_key: nil, table_name: nil, **)
|
43
|
-
define_method :"join_#{association_name}" do |**options|
|
44
|
-
if join = joins_values.find { |v| (Arel::Nodes::Join === v) && (v.left.name == table_name.to_s) }
|
45
|
-
return self if (options[:outer_join] || Arel::Nodes::InnerJoin === join)
|
46
|
-
self.joins_values = joins_values - [join]
|
47
|
-
end
|
48
|
-
t = translation_class.arel_table
|
49
|
-
m = arel_table
|
50
|
-
join_type = options[:outer_join] ? Arel::Nodes::OuterJoin : Arel::Nodes::InnerJoin
|
51
|
-
joins(m.join(t, join_type).
|
52
|
-
on(t[foreign_key].eq(m[:id]).
|
53
|
-
and(t[:locale].eq(Mobility.locale))).join_sources)
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
def define_query_methods(association_name, translation_class, **)
|
58
|
-
q = self
|
59
|
-
|
60
|
-
# Note that Mobility will try to use inner/outer joins appropriate to the query,
|
61
|
-
# so for example:
|
62
|
-
#
|
63
|
-
# Article.where(title: nil, content: nil) #=> OUTER JOIN (all nils)
|
64
|
-
# Article.where(title: "foo", content: nil) #=> INNER JOIN (one non-nil)
|
65
|
-
#
|
66
|
-
# In the first case, if we are in (say) the "en" locale, then we should match articles
|
67
|
-
# that have *no* article_translations with English locales (since no translation is
|
68
|
-
# equivalent to a nil value). If we used an inner join in the first case, an article
|
69
|
-
# with no English translations would be filtered out, so we use an outer join.
|
70
|
-
#
|
71
|
-
# When deciding whether to use an outer or inner join, array-valued
|
72
|
-
# conditions are treated as nil if they have any values.
|
73
|
-
#
|
74
|
-
# Article.where(title: nil, content: ["foo", nil]) #=> OUTER JOIN (all nil or array with nil)
|
75
|
-
# Article.where(title: "foo", content: ["foo", nil]) #=> INNER JOIN (one non-nil)
|
76
|
-
# Article.where(title: ["foo", "bar"], content: ["foo", nil]) #=> INNER JOIN (one non-nil array)
|
77
|
-
#
|
78
|
-
# The logic also applies when a query has more than one where clause.
|
79
|
-
#
|
80
|
-
# Article.where(title: nil).where(content: nil) #=> OUTER JOIN (all nils)
|
81
|
-
# Article.where(title: nil).where(content: "foo") #=> INNER JOIN (one non-nil)
|
82
|
-
# Article.where(title: "foo").where(content: nil) #=> INNER JOIN (one non-nil)
|
83
|
-
#
|
84
|
-
define_method :where! do |opts, *rest|
|
85
|
-
if i18n_keys = q.extract_attributes(opts)
|
86
|
-
opts = opts.with_indifferent_access
|
87
|
-
options = {
|
88
|
-
# We only need an OUTER JOIN if every value is either nil, or an
|
89
|
-
# array with at least one nil value.
|
90
|
-
outer_join: opts.values_at(*i18n_keys).compact.all? { |v| ![*v].all? }
|
91
|
-
}
|
92
|
-
i18n_keys.each do |attr|
|
93
|
-
opts["#{translation_class.table_name}.#{attr}"] = q.collapse opts.delete(attr)
|
94
|
-
end
|
95
|
-
super(opts, *rest).send("join_#{association_name}", options)
|
96
|
-
else
|
97
|
-
super(opts, *rest)
|
98
|
-
end
|
99
|
-
end
|
100
|
-
end
|
101
|
-
end
|
102
|
-
Table.private_constant :QueryMethods
|
103
|
-
end
|
104
|
-
end
|
105
|
-
end
|