globalize-rails5 5.1.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 +7 -0
- data/CHANGELOG.md +111 -0
- data/CONTRIBUTING.md +37 -0
- data/Gemfile +26 -0
- data/LICENSE +22 -0
- data/README.md +430 -0
- data/Rakefile +55 -0
- data/lib/globalize.rb +90 -0
- data/lib/globalize/active_record.rb +14 -0
- data/lib/globalize/active_record/act_macro.rb +111 -0
- data/lib/globalize/active_record/adapter.rb +99 -0
- data/lib/globalize/active_record/adapter_dirty.rb +54 -0
- data/lib/globalize/active_record/attributes.rb +26 -0
- data/lib/globalize/active_record/class_methods.rb +124 -0
- data/lib/globalize/active_record/exceptions.rb +13 -0
- data/lib/globalize/active_record/instance_methods.rb +218 -0
- data/lib/globalize/active_record/migration.rb +210 -0
- data/lib/globalize/active_record/query_methods.rb +98 -0
- data/lib/globalize/active_record/translation.rb +45 -0
- data/lib/globalize/interpolation.rb +28 -0
- data/lib/globalize/version.rb +3 -0
- data/lib/i18n/missing_translations_log_handler.rb +41 -0
- data/lib/i18n/missing_translations_raise_handler.rb +25 -0
- data/lib/patches/active_record/persistence.rb +17 -0
- data/lib/patches/active_record/query_method.rb +3 -0
- data/lib/patches/active_record/rails4/query_method.rb +35 -0
- data/lib/patches/active_record/rails4/uniqueness_validator.rb +42 -0
- data/lib/patches/active_record/rails5/uniqueness_validator.rb +47 -0
- data/lib/patches/active_record/relation.rb +12 -0
- data/lib/patches/active_record/serialization.rb +21 -0
- data/lib/patches/active_record/uniqueness_validator.rb +5 -0
- data/lib/patches/active_record/xml_attribute_serializer.rb +23 -0
- metadata +204 -0
@@ -0,0 +1,124 @@
|
|
1
|
+
module Globalize
|
2
|
+
module ActiveRecord
|
3
|
+
module ClassMethods
|
4
|
+
delegate :translated_locales, :set_translations_table_name, :to => :translation_class
|
5
|
+
|
6
|
+
if ::ActiveRecord::VERSION::STRING < "5.0.0"
|
7
|
+
def columns_hash
|
8
|
+
super.except(*translated_attribute_names.map(&:to_s))
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def with_locales(*locales)
|
13
|
+
all.merge translation_class.with_locales(*locales)
|
14
|
+
end
|
15
|
+
|
16
|
+
def with_translations(*locales)
|
17
|
+
locales = translated_locales if locales.empty?
|
18
|
+
preload(:translations).joins(:translations).readonly(false).with_locales(locales).tap do |query|
|
19
|
+
query.distinct! unless locales.flatten.one?
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def with_required_attributes
|
24
|
+
warn 'with_required_attributes is deprecated and will be removed in the next release of Globalize.'
|
25
|
+
required_translated_attributes.inject(all) do |scope, name|
|
26
|
+
scope.where("#{translated_column_name(name)} IS NOT NULL")
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def with_translated_attribute(name, value, locales = Globalize.fallbacks)
|
31
|
+
with_translations.where(
|
32
|
+
translated_column_name(name) => value,
|
33
|
+
translated_column_name(:locale) => Array(locales).map(&:to_s)
|
34
|
+
)
|
35
|
+
end
|
36
|
+
|
37
|
+
def translated?(name)
|
38
|
+
translated_attribute_names.include?(name.to_sym)
|
39
|
+
end
|
40
|
+
|
41
|
+
def required_attributes
|
42
|
+
warn 'required_attributes is deprecated and will be removed in the next release of Globalize.'
|
43
|
+
validators.map { |v| v.attributes if v.is_a?(ActiveModel::Validations::PresenceValidator) }.flatten
|
44
|
+
end
|
45
|
+
|
46
|
+
def required_translated_attributes
|
47
|
+
warn 'required_translated_attributes is deprecated and will be removed in the next release of Globalize.'
|
48
|
+
translated_attribute_names & required_attributes
|
49
|
+
end
|
50
|
+
|
51
|
+
def translation_class
|
52
|
+
@translation_class ||= begin
|
53
|
+
if self.const_defined?(:Translation, false)
|
54
|
+
klass = self.const_get(:Translation, false)
|
55
|
+
else
|
56
|
+
klass = self.const_set(:Translation, Class.new(Globalize::ActiveRecord::Translation))
|
57
|
+
end
|
58
|
+
|
59
|
+
klass.belongs_to :globalized_model, :class_name => self.name, :foreign_key => translation_options[:foreign_key], inverse_of: :translations
|
60
|
+
klass
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def translations_table_name
|
65
|
+
translation_class.table_name
|
66
|
+
end
|
67
|
+
|
68
|
+
def translated_column_name(name)
|
69
|
+
"#{translation_class.table_name}.#{name}"
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
# Override the default relation method in order to return a subclass
|
75
|
+
# of ActiveRecord::Relation with custom finder methods for translated
|
76
|
+
# attributes.
|
77
|
+
def relation
|
78
|
+
super.extending!(QueryMethods)
|
79
|
+
end
|
80
|
+
|
81
|
+
protected
|
82
|
+
|
83
|
+
def define_translated_attr_reader(name)
|
84
|
+
define_method(name) do |*args|
|
85
|
+
Globalize::Interpolation.interpolate(name, self, args)
|
86
|
+
end
|
87
|
+
alias_method :"#{name}_before_type_cast", name
|
88
|
+
end
|
89
|
+
|
90
|
+
def define_translated_attr_writer(name)
|
91
|
+
define_method(:"#{name}=") do |value|
|
92
|
+
write_attribute(name, value)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def define_translated_attr_accessor(name)
|
97
|
+
define_translated_attr_reader(name)
|
98
|
+
define_translated_attr_writer(name)
|
99
|
+
end
|
100
|
+
|
101
|
+
def define_translations_reader(name)
|
102
|
+
define_method(:"#{name}_translations") do
|
103
|
+
hash = translated_attribute_by_locale(name)
|
104
|
+
globalize.stash.keys.each_with_object(hash) do |locale, result|
|
105
|
+
result[locale] = globalize.fetch_stash(locale, name) if globalize.stash_contains?(locale, name)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def define_translations_writer(name)
|
111
|
+
define_method(:"#{name}_translations=") do |value|
|
112
|
+
value.each do |(locale, _value)|
|
113
|
+
write_attribute name, _value, :locale => locale
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def define_translations_accessor(name)
|
119
|
+
define_translations_reader(name)
|
120
|
+
define_translations_writer(name)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
@@ -0,0 +1,218 @@
|
|
1
|
+
module Globalize
|
2
|
+
module ActiveRecord
|
3
|
+
module InstanceMethods
|
4
|
+
delegate :translated_locales, :to => :translations
|
5
|
+
|
6
|
+
def globalize
|
7
|
+
@globalize ||= Adapter.new(self)
|
8
|
+
end
|
9
|
+
|
10
|
+
def attributes
|
11
|
+
super.merge(translated_attributes)
|
12
|
+
end
|
13
|
+
|
14
|
+
def attributes=(new_attributes, *options)
|
15
|
+
super unless new_attributes.respond_to?(:stringify_keys) && new_attributes.present?
|
16
|
+
attributes = new_attributes.stringify_keys
|
17
|
+
with_given_locale(attributes) { super(attributes.except("locale"), *options) }
|
18
|
+
end
|
19
|
+
|
20
|
+
def assign_attributes(new_attributes, *options)
|
21
|
+
super unless new_attributes.respond_to?(:stringify_keys) && new_attributes.present?
|
22
|
+
attributes = new_attributes.stringify_keys
|
23
|
+
with_given_locale(attributes) { super(attributes.except("locale"), *options) }
|
24
|
+
end
|
25
|
+
|
26
|
+
def write_attribute(name, value, *args, &block)
|
27
|
+
return super(name, value, *args, &block) unless translated?(name)
|
28
|
+
|
29
|
+
options = {:locale => Globalize.locale}.merge(args.first || {})
|
30
|
+
|
31
|
+
globalize.write(options[:locale], name, value)
|
32
|
+
end
|
33
|
+
|
34
|
+
def [](attr_name)
|
35
|
+
if translated?(attr_name)
|
36
|
+
read_attribute(attr_name)
|
37
|
+
else
|
38
|
+
read_attribute(attr_name) { |n| missing_attribute(n, caller) }
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def read_attribute(name, options = {}, &block)
|
43
|
+
options = {:translated => true, :locale => nil}.merge(options)
|
44
|
+
return super(name, &block) unless options[:translated]
|
45
|
+
|
46
|
+
if translated?(name)
|
47
|
+
if !(value = globalize.fetch(options[:locale] || Globalize.locale, name)).nil?
|
48
|
+
value
|
49
|
+
else
|
50
|
+
super(name, &block)
|
51
|
+
end
|
52
|
+
else
|
53
|
+
super(name, &block)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def attribute_names
|
58
|
+
translated_attribute_names.map(&:to_s) + super
|
59
|
+
end
|
60
|
+
|
61
|
+
delegate :translated?, :to => :class
|
62
|
+
|
63
|
+
def translated_attributes
|
64
|
+
translated_attribute_names.inject({}) do |attributes, name|
|
65
|
+
attributes.merge(name.to_s => send(name))
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# This method is basically the method built into Rails
|
70
|
+
# but we have to pass {:translated => false}
|
71
|
+
def untranslated_attributes
|
72
|
+
attribute_names.inject({}) do |attrs, name|
|
73
|
+
attrs[name] = read_attribute(name, {:translated => false}); attrs
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def set_translations(options)
|
78
|
+
options.keys.each do |locale|
|
79
|
+
translation = translation_for(locale) ||
|
80
|
+
translations.build(:locale => locale.to_s)
|
81
|
+
|
82
|
+
options[locale].each do |key, value|
|
83
|
+
translation.send :"#{key}=", value
|
84
|
+
translation.globalized_model.send :"#{key}=", value
|
85
|
+
end
|
86
|
+
translation.save if persisted?
|
87
|
+
end
|
88
|
+
globalize.reset
|
89
|
+
end
|
90
|
+
|
91
|
+
def reload(options = nil)
|
92
|
+
translation_caches.clear
|
93
|
+
translated_attribute_names.each { |name| @attributes.reset(name.to_s) }
|
94
|
+
globalize.reset
|
95
|
+
super(options)
|
96
|
+
end
|
97
|
+
|
98
|
+
def initialize_dup(other)
|
99
|
+
@globalize = nil
|
100
|
+
@translation_caches = nil
|
101
|
+
super
|
102
|
+
other.each_locale_and_translated_attribute do |locale, name|
|
103
|
+
globalize.write(locale, name, other.globalize.fetch(locale, name) )
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def translation
|
108
|
+
translation_for(::Globalize.locale)
|
109
|
+
end
|
110
|
+
|
111
|
+
def translation_for(locale, build_if_missing = true)
|
112
|
+
unless translation_caches[locale]
|
113
|
+
# Fetch translations from database as those in the translation collection may be incomplete
|
114
|
+
_translation = translations.detect{|t| t.locale.to_s == locale.to_s}
|
115
|
+
_translation ||= translations.with_locale(locale).first unless translations.loaded?
|
116
|
+
_translation ||= translations.build(:locale => locale) if build_if_missing
|
117
|
+
translation_caches[locale] = _translation if _translation
|
118
|
+
end
|
119
|
+
translation_caches[locale]
|
120
|
+
end
|
121
|
+
|
122
|
+
def translation_caches
|
123
|
+
@translation_caches ||= {}
|
124
|
+
end
|
125
|
+
|
126
|
+
def translations_by_locale
|
127
|
+
translations.each_with_object(HashWithIndifferentAccess.new) do |t, hash|
|
128
|
+
hash[t.locale] = block_given? ? yield(t) : t
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def translated_attribute_by_locale(name)
|
133
|
+
translations_by_locale(&:"#{name}")
|
134
|
+
end
|
135
|
+
|
136
|
+
# Get available locales from translations association, without a separate distinct query
|
137
|
+
def available_locales
|
138
|
+
translations.map(&:locale).uniq
|
139
|
+
end
|
140
|
+
|
141
|
+
def globalize_fallbacks(locale)
|
142
|
+
Globalize.fallbacks(locale)
|
143
|
+
end
|
144
|
+
|
145
|
+
def save(*)
|
146
|
+
result = Globalize.with_locale(translation.locale || I18n.default_locale) do
|
147
|
+
without_fallbacks do
|
148
|
+
super
|
149
|
+
end
|
150
|
+
end
|
151
|
+
if result
|
152
|
+
globalize.clear_dirty
|
153
|
+
end
|
154
|
+
|
155
|
+
result
|
156
|
+
end
|
157
|
+
|
158
|
+
def column_for_attribute name
|
159
|
+
return super if translated_attribute_names.exclude?(name)
|
160
|
+
|
161
|
+
globalize.send(:column_for_attribute, name)
|
162
|
+
end
|
163
|
+
|
164
|
+
def cache_key
|
165
|
+
[super, translation.cache_key].join("/")
|
166
|
+
end
|
167
|
+
|
168
|
+
def changed?
|
169
|
+
changed_attributes.present? || translations.any?(&:changed?)
|
170
|
+
end
|
171
|
+
|
172
|
+
# need to access instance variable directly since changed_attributes
|
173
|
+
# is frozen as of Rails 4.2
|
174
|
+
def original_changed_attributes
|
175
|
+
@changed_attributes
|
176
|
+
end
|
177
|
+
|
178
|
+
protected
|
179
|
+
|
180
|
+
def each_locale_and_translated_attribute
|
181
|
+
used_locales.each do |locale|
|
182
|
+
translated_attribute_names.each do |name|
|
183
|
+
yield locale, name
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
def used_locales
|
189
|
+
locales = globalize.stash.keys.concat(globalize.stash.keys).concat(translations.translated_locales)
|
190
|
+
locales.uniq!
|
191
|
+
locales
|
192
|
+
end
|
193
|
+
|
194
|
+
def save_translations!
|
195
|
+
globalize.save_translations!
|
196
|
+
translation_caches.clear
|
197
|
+
end
|
198
|
+
|
199
|
+
def with_given_locale(_attributes, &block)
|
200
|
+
attributes = _attributes.stringify_keys
|
201
|
+
|
202
|
+
if locale = attributes.try(:delete, "locale")
|
203
|
+
Globalize.with_locale(locale, &block)
|
204
|
+
else
|
205
|
+
yield
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
def without_fallbacks
|
210
|
+
before = self.fallbacks_for_empty_translations
|
211
|
+
self.fallbacks_for_empty_translations = false
|
212
|
+
yield
|
213
|
+
ensure
|
214
|
+
self.fallbacks_for_empty_translations = before
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
@@ -0,0 +1,210 @@
|
|
1
|
+
require 'digest/sha1'
|
2
|
+
|
3
|
+
module Globalize
|
4
|
+
module ActiveRecord
|
5
|
+
module Migration
|
6
|
+
def globalize_migrator
|
7
|
+
@globalize_migrator ||= Migrator.new(self)
|
8
|
+
end
|
9
|
+
|
10
|
+
delegate :create_translation_table!, :add_translation_fields!,
|
11
|
+
:drop_translation_table!, :translation_index_name,
|
12
|
+
:translation_locale_index_name, :to => :globalize_migrator
|
13
|
+
|
14
|
+
class Migrator
|
15
|
+
include Globalize::ActiveRecord::Exceptions
|
16
|
+
|
17
|
+
attr_reader :model
|
18
|
+
delegate :translated_attribute_names, :connection, :table_name,
|
19
|
+
:table_name_prefix, :translations_table_name, :columns, :to => :model
|
20
|
+
|
21
|
+
def initialize(model)
|
22
|
+
@model = model
|
23
|
+
end
|
24
|
+
|
25
|
+
def fields
|
26
|
+
@fields ||= complete_translated_fields
|
27
|
+
end
|
28
|
+
|
29
|
+
def create_translation_table!(fields = {}, options = {})
|
30
|
+
extra = options.keys - [:migrate_data, :remove_source_columns, :unique_index]
|
31
|
+
if extra.any?
|
32
|
+
raise ArgumentError, "Unknown migration #{'option'.pluralize(extra.size)}: #{extra}"
|
33
|
+
end
|
34
|
+
@fields = fields
|
35
|
+
# If we have fields we only want to create the translation table with those fields
|
36
|
+
complete_translated_fields if fields.blank?
|
37
|
+
validate_translated_fields
|
38
|
+
|
39
|
+
create_translation_table
|
40
|
+
add_translation_fields!(fields, options)
|
41
|
+
create_translations_index(options)
|
42
|
+
clear_schema_cache!
|
43
|
+
end
|
44
|
+
|
45
|
+
def add_translation_fields!(fields, options = {})
|
46
|
+
@fields = fields
|
47
|
+
validate_translated_fields
|
48
|
+
add_translation_fields
|
49
|
+
clear_schema_cache!
|
50
|
+
move_data_to_translation_table if options[:migrate_data]
|
51
|
+
remove_source_columns if options[:remove_source_columns]
|
52
|
+
clear_schema_cache!
|
53
|
+
end
|
54
|
+
|
55
|
+
def remove_source_columns
|
56
|
+
connection.remove_columns(table_name, *fields.keys)
|
57
|
+
end
|
58
|
+
|
59
|
+
def drop_translation_table!(options = {})
|
60
|
+
move_data_to_model_table if options[:migrate_data]
|
61
|
+
drop_translations_index
|
62
|
+
drop_translation_table
|
63
|
+
clear_schema_cache!
|
64
|
+
end
|
65
|
+
|
66
|
+
# This adds all the current translated attributes of the model
|
67
|
+
# It's a problem because in early migrations would add all the translated attributes
|
68
|
+
def complete_translated_fields
|
69
|
+
translated_attribute_names.each do |name|
|
70
|
+
@fields[name] ||= column_type(name)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def create_translation_table
|
75
|
+
connection.create_table(translations_table_name) do |t|
|
76
|
+
t.references table_name.sub(/^#{table_name_prefix}/, '').singularize, :null => false, :index => false, :type => column_type(model.primary_key).to_sym
|
77
|
+
t.string :locale, :null => false
|
78
|
+
t.timestamps :null => false
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def add_translation_fields
|
83
|
+
connection.change_table(translations_table_name) do |t|
|
84
|
+
fields.each do |name, options|
|
85
|
+
if options.is_a? Hash
|
86
|
+
t.column name, options.delete(:type), options
|
87
|
+
else
|
88
|
+
t.column name, options
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def create_translations_index(options)
|
95
|
+
foreign_key = "#{table_name.sub(/^#{table_name_prefix}/, "").singularize}_id".to_sym
|
96
|
+
connection.add_index(
|
97
|
+
translations_table_name,
|
98
|
+
foreign_key,
|
99
|
+
:name => translation_index_name
|
100
|
+
)
|
101
|
+
# index for select('DISTINCT locale') call in translation.rb
|
102
|
+
connection.add_index(
|
103
|
+
translations_table_name,
|
104
|
+
:locale,
|
105
|
+
:name => translation_locale_index_name
|
106
|
+
)
|
107
|
+
|
108
|
+
if options[:unique_index]
|
109
|
+
connection.add_index(
|
110
|
+
translations_table_name,
|
111
|
+
[foreign_key, :locale],
|
112
|
+
:name => translation_unique_index_name,
|
113
|
+
unique: true
|
114
|
+
)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def drop_translation_table
|
119
|
+
connection.drop_table(translations_table_name)
|
120
|
+
end
|
121
|
+
|
122
|
+
def drop_translations_index
|
123
|
+
if connection.indexes(translations_table_name).map(&:name).include?(translation_index_name)
|
124
|
+
connection.remove_index(translations_table_name, :name => translation_index_name)
|
125
|
+
end
|
126
|
+
if connection.indexes(translations_table_name).map(&:name).include?(translation_locale_index_name)
|
127
|
+
connection.remove_index(translations_table_name, :name => translation_locale_index_name)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def move_data_to_translation_table
|
132
|
+
model.find_each do |record|
|
133
|
+
translation = record.translation_for(I18n.locale) || record.translations.build(:locale => I18n.locale)
|
134
|
+
fields.each do |attribute_name, attribute_type|
|
135
|
+
translation[attribute_name] = record.read_attribute(attribute_name, {:translated => false})
|
136
|
+
end
|
137
|
+
translation.save!
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def move_data_to_model_table
|
142
|
+
add_missing_columns
|
143
|
+
|
144
|
+
# Find all of the translated attributes for all records in the model.
|
145
|
+
all_translated_attributes = model.all.collect{|m| m.attributes}
|
146
|
+
all_translated_attributes.each do |translated_record|
|
147
|
+
# Create a hash containing the translated column names and their values.
|
148
|
+
translated_attribute_names.inject(fields_to_update={}) do |f, name|
|
149
|
+
f.update({name.to_sym => translated_record[name.to_s]})
|
150
|
+
end
|
151
|
+
|
152
|
+
# Now, update the actual model's record with the hash.
|
153
|
+
model.where(model.primary_key.to_sym => translated_record[model.primary_key]).update_all(fields_to_update)
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
def validate_translated_fields
|
158
|
+
fields.each do |name, options|
|
159
|
+
raise BadFieldName.new(name) unless valid_field_name?(name)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def column_type(name)
|
164
|
+
columns.detect { |c| c.name == name.to_s }.try(:type)
|
165
|
+
end
|
166
|
+
|
167
|
+
def valid_field_name?(name)
|
168
|
+
translated_attribute_names.include?(name)
|
169
|
+
end
|
170
|
+
|
171
|
+
def translation_index_name
|
172
|
+
truncate_index_name "index_#{translations_table_name}_on_#{table_name.singularize}_id"
|
173
|
+
end
|
174
|
+
|
175
|
+
def translation_locale_index_name
|
176
|
+
truncate_index_name "index_#{translations_table_name}_on_locale"
|
177
|
+
end
|
178
|
+
|
179
|
+
def translation_unique_index_name
|
180
|
+
truncate_index_name "index_#{translations_table_name}_on_#{table_name.singularize}_id_and_locale"
|
181
|
+
end
|
182
|
+
|
183
|
+
def clear_schema_cache!
|
184
|
+
connection.schema_cache.clear! if connection.respond_to? :schema_cache
|
185
|
+
model::Translation.reset_column_information
|
186
|
+
model.reset_column_information
|
187
|
+
end
|
188
|
+
|
189
|
+
private
|
190
|
+
|
191
|
+
def truncate_index_name(index_name)
|
192
|
+
if index_name.size < connection.index_name_length
|
193
|
+
index_name
|
194
|
+
else
|
195
|
+
"index_#{Digest::SHA1.hexdigest(index_name)}"[0, connection.index_name_length]
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
def add_missing_columns
|
200
|
+
clear_schema_cache!
|
201
|
+
translated_attribute_names.map(&:to_s).each do |attribute|
|
202
|
+
unless model.column_names.include?(attribute)
|
203
|
+
connection.add_column(table_name, attribute, model::Translation.columns_hash[attribute].type)
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|