(Not documented)
# File vendor/plugins/ubiquo_i18n/lib/ubiquo_i18n/extensions/active_record.rb, line 466
466: def self.extended(klass)
467: # Ensure that the needed variables are inherited
468: @@translatable_inheritable_instance_variables.each do |inheritable|
469: unless eval("@#{inheritable}").nil?
470: klass.instance_variable_set("@#{inheritable}", eval("@#{inheritable}").dup)
471: end
472: end
473:
474: # Aliases the find and count methods to apply the locale filter
475: klass.class_eval do
476: class << self
477: alias_method_chain :find, :locale_filter
478: alias_method_chain :count, :locale_filter
479: VALID_FIND_OPTIONS << :locale_scoped << :locale_list
480: end
481: end
482:
483: # Accept the :translation_shared option when defining associations
484: ASSOCIATION_TYPES.each do |type|
485: klass.send("valid_keys_for_#{type}_association") << :translation_shared
486: end
487: end
Used by third parties to add fields that should always be independent between different languages
# File vendor/plugins/ubiquo_i18n/lib/ubiquo_i18n/extensions/active_record.rb, line 445
445: def add_translatable_attributes(*args)
446: @global_translatable_attributes += args
447: end
Used by third parties to add scopes for translations updates of common fields It accepts two formats for condition:
# File vendor/plugins/ubiquo_i18n/lib/ubiquo_i18n/extensions/active_record.rb, line 458
458: def add_translatable_scope(condition)
459: @translatable_scopes << condition
460: end
Applies the locale filter if needed, then performs the normal count method
# File vendor/plugins/ubiquo_i18n/lib/ubiquo_i18n/extensions/active_record.rb, line 429
429: def count_with_locale_filter(*args)
430: if self.is_translatable?
431: options = args.extract_options!
432: apply_locale_filter!(options)
433: count_without_locale_filter(args.first || :all, options)
434: else
435: count_without_locale_filter(*args)
436: end
437: end
Applies the locale filter if needed, then performs the normal find method
# File vendor/plugins/ubiquo_i18n/lib/ubiquo_i18n/extensions/active_record.rb, line 418
418: def find_with_locale_filter(*args)
419: if self.is_translatable?
420: options = args.extract_options!
421: apply_locale_filter!(options)
422: find_without_locale_filter(args.first, options)
423: else
424: find_without_locale_filter(*args)
425: end
426: end
(Not documented)
# File vendor/plugins/ubiquo_i18n/lib/ubiquo_i18n/extensions/active_record.rb, line 489
489: def inherited(klass)
490: super
491: @@translatable_inheritable_instance_variables.each do |inheritable|
492: unless eval("@#{inheritable}").nil?
493: klass.instance_variable_set("@#{inheritable}", eval("@#{inheritable}").dup)
494: end
495: end
496: end
Returns the value for the var_name instance variable, or if this is nil, follow the superclass chain to ask the value
# File vendor/plugins/ubiquo_i18n/lib/ubiquo_i18n/extensions/active_record.rb, line 322
322: def instance_variable_inherited_get(var_name, method_name = nil)
323: method_name ||= var_name
324: value = instance_variable_get("@#{var_name}")
325: if value.nil? && !@really_translatable_class
326: self.superclass.respond_to?(method_name) && self.superclass.send(method_name)
327: else
328: value
329: end
330: end
Sets the value for the var_name instance variable, or if this is nil, follow the superclass chain to set the value
# File vendor/plugins/ubiquo_i18n/lib/ubiquo_i18n/extensions/active_record.rb, line 334
334: def instance_variable_inherited_set(value, var_name, method_name = nil)
335: method_name ||= var_name
336: if !@really_translatable_class
337: self.superclass.respond_to?(method_name) && self.superclass.send(method_name, value)
338: else
339: instance_variable_set("@#{var_name}", value)
340: end
341: end
Returns true if the class is marked as translatable
# File vendor/plugins/ubiquo_i18n/lib/ubiquo_i18n/extensions/active_record.rb, line 344
344: def is_translatable?
345: instance_variable_inherited_get("translatable", "is_translatable?")
346: end
Returns true if this class is currently translating relations
# File vendor/plugins/ubiquo_i18n/lib/ubiquo_i18n/extensions/active_record.rb, line 359
359: def is_translating_relations
360: instance_variable_inherited_get("is_translating_relations")
361: end
Sets the value of the is_translating_relations flag
# File vendor/plugins/ubiquo_i18n/lib/ubiquo_i18n/extensions/active_record.rb, line 364
364: def is_translating_relations=(value)
365: instance_variable_inherited_set(value, "is_translating_relations", "is_translating_relations=")
366: end
Returns the class that really calls the translatable method
# File vendor/plugins/ubiquo_i18n/lib/ubiquo_i18n/extensions/active_record.rb, line 354
354: def really_translatable_class
355: instance_variable_inherited_get("really_translatable_class")
356: end
Returns true if the translatable propagation has been set to stop
# File vendor/plugins/ubiquo_i18n/lib/ubiquo_i18n/extensions/active_record.rb, line 381
381: def stop_translatable_propagation
382: instance_variable_inherited_get("stop_translatable_propagation")
383: end
Setter for the stop_translatable_propagation_flag
# File vendor/plugins/ubiquo_i18n/lib/ubiquo_i18n/extensions/active_record.rb, line 386
386: def stop_translatable_propagation=(value)
387: instance_variable_inherited_set(value, "stop_translatable_propagation", "stop_translatable_propagation=")
388: end
Class method for ActiveRecord that states which attributes are translatable and therefore when updated will be only updated for the current locale.
EXAMPLE:
translatable :title, :description
possible options:
:timestamps => set to false to avoid translatable (i.e. independent per translation) timestamps
# File vendor/plugins/ubiquo_i18n/lib/ubiquo_i18n/extensions/active_record.rb, line 22
22: def translatable(*attrs)
23: # inherit translatable attributes
24: @translatable_attributes = self.translatable_attributes || []
25:
26: @really_translatable_class = self
27: @translatable = true
28:
29: # extract and parse options
30: options = attrs.extract_options!
31: # add attrs from this class
32: @translatable_attributes += attrs
33:
34: # timestamps are independent per translation unless set
35: @translatable_attributes += [:created_at, :updated_at] unless options[:timestamps] == false
36:
37: # try to generate the attribute setter
38: self.new.send(:locale=, :generate) rescue nil
39: if instance_methods.include?('locale=') && !instance_methods.include?('locale_with_duality=')
40: # give the proper behaviour to the locale setter
41: define_method('locale_with_duality=') do |locale|
42: locale = case locale
43: when String
44: locale
45: else
46: locale.iso_code if locale.respond_to?(:iso_code)
47: end
48: send(:locale_without_duality=, locale)
49: end
50:
51: alias_method_chain :locale=, :duality
52:
53: end
54:
55: unless instance_methods.include?("in_locale")
56: define_method('in_locale') do |*locales|
57: self.class.locale(*locales).first(:conditions => {:content_id => self.content_id})
58: end
59: end
60:
61: # Checks if the instance has a locale in the given a locales list
62: # The last parameter can be an options hash
63: # :skip_any => if true, ignore items with the :any locale.
64: # else, these items always return true
65: define_method('in_locale?') do |*asked_locales|
66: options = asked_locales.extract_options!
67: options.reverse_merge!({
68: :skip_any => false
69: })
70: asked_locales.map(&:to_s).include?(self.locale) ||
71: (!options[:skip_any] && self.locale == 'any')
72: end
73:
74: # usage:
75: # find all content in any locale: Model.locale(:all)
76: # find spanish content: Model.locale('es')
77: # find spanish or english content. If spanish and english exists, gets the spanish version. Model.locale('es', 'en')
78: # find all content in spanish or any other locale if spanish dosn't exist: Model.locale('es', :all)
79: # find all content in any locale: Model.locale(:all)
80: #
81: named_scope :locale, lambda{|*locales|
82: if locales.delete(:ALL)
83: locales << :all
84: ActiveSupport::Deprecation.warn('Use :all instead of :ALL in locale()', caller(5))
85: end
86:
87: {:locale_scoped => true, :locale_list => locales}
88: }
89:
90: # usage:
91: # find all items of one content: Model.content(1).first
92: # find all items of some contents: Model.content(1,2,3)
93: named_scope :content, lambda{|*content_ids|
94: {:conditions => {:content_id => content_ids}}
95: }
96:
97: # usage:
98: # find all translations of a given content: Model.translations(content)
99: # will use the defined scopes to discriminate what are translations
100: # remember it won't return 'content' itself
101: named_scope :translations, lambda{|content|
102: scoped_conditions = []
103: @translatable_scopes.each do |scope|
104: scoped_conditions << (String === scope ? scope : scope.call(content))
105: end
106: translation_condition = "#{self.table_name}.content_id = ? AND #{self.table_name}.locale != ?"
107: unless scoped_conditions.blank?
108: translation_condition += ' AND ' + scoped_conditions.join(' AND ')
109: end
110: {:conditions => [translation_condition, content.content_id, content.locale]}
111: }
112:
113: # Apply these named scopes to any possible already loaded subclass
114: subclasses.each do |klass|
115: klass.scopes.merge! scopes.slice(:locale, :translations, :content)
116: end
117:
118: # Instance method to find translations
119: define_method('translations') do
120: self.class.translations(self)
121: end
122:
123: # Returns an array containing self and its translations
124: define_method('with_translations') do
125: [self] + translations
126: end
127:
128: # Creates a new instance of the translatable class, using the common
129: # values from an instance sharing the same content_id
130: # Returns a new independent instance if content_id is nil or not found
131: # Options can be one of these:
132: # :copy_all => if true, will copy all the attributes from the original, even the translatable ones
133: def translate(content_id, locale, options = {})
134: original = find_by_content_id(content_id)
135: new_translation = original ? original.translate(locale, options) : new
136: new_translation.locale = locale
137: new_translation
138: end
139:
140: # Creates (saving) a new translation of self, with the common values filled in
141: define_method('translate') do |*attrs|
142: locale = attrs.first
143: options = attrs.extract_options!
144: options[:copy_all] = options[:copy_all].nil? ? true : options[:copy_all]
145:
146: new_translation = self.class.new
147: new_translation.locale = locale
148:
149: # copy of attributes
150: clonable_attributes = options[:copy_all] ? :attributes_except_unique_for_translation : :untranslatable_attributes
151: self.send(clonable_attributes).each_pair do |attr, value|
152: new_translation.send("#{attr}=", value)
153: end
154:
155: # copy of relations
156: new_translation.copy_translatable_shared_relations_from self
157: new_translation
158: end
159:
160:
161: # Looks for defined shared relations and performs a chain-update on them
162: define_method('copy_translatable_shared_relations_from') do |model|
163: # here a clean environment is needed, but save Locale.current
164: @current_locale, Locale.current = Locale.current, nil if Locale.current
165: self.class.is_translating_relations = true
166: begin
167: # act on reflections where translatable == false
168: self.class.reflections.select do |name, reflection|
169: reflection.options[:translation_shared] == true
170: end.each do |association_id, reflection_values|
171: association_values = model.send(association_id)
172: record = [association_values].flatten.first
173:
174: if record && record.class.is_translatable?
175:
176: all_relationship_contents = []
177: [association_values].flatten.each do |related_element|
178: existing_translation = related_element.translations.locale(locale).first
179: if existing_translation
180: all_relationship_contents << existing_translation
181: else
182: all_relationship_contents << related_element
183: end
184: end
185:
186: elsif record
187:
188: if reflection_values.macro == :belongs_to
189: # we simply copy the attribute value
190: all_relationship_contents = [association_values]
191: else
192: raise "This behaviour is not supported by ubiquo_i18n. Either use a has_many :through to a translatable model or mark the #{record.class} model as translatable"
193: end
194:
195: else
196: next
197: end
198:
199: all_relationship_contents = all_relationship_contents.first unless association_values.is_a?(Array)
200: self.send(association_id.to_s + '=', all_relationship_contents)
201: if reflection_values.macro == :belongs_to && !new_record?
202: # belongs_to is not autosaved by rails when the association is not new
203: save
204: end
205: end
206: ensure
207: self.class.is_translating_relations = false
208: Locale.current = @current_locale
209: end
210: end
211:
212: define_method 'destroy_content' do
213: self.translations.each(&:destroy)
214: self.destroy
215: end
216:
217: end
Returns a list of translatable attributes for this class
# File vendor/plugins/ubiquo_i18n/lib/ubiquo_i18n/extensions/active_record.rb, line 349
349: def translatable_attributes
350: instance_variable_inherited_get("translatable_attributes")
351: end
Creates a new instance of the translatable class, using the common values from an instance sharing the same content_id Returns a new independent instance if content_id is nil or not found Options can be one of these:
:copy_all => if true, will copy all the attributes from the original, even the translatable ones
# File vendor/plugins/ubiquo_i18n/lib/ubiquo_i18n/extensions/active_record.rb, line 133
133: def translate(content_id, locale, options = {})
134: original = find_by_content_id(content_id)
135: new_translation = original ? original.translate(locale, options) : new
136: new_translation.locale = locale
137: new_translation
138: end
Wrapper for translating relations preventing cyclical chain updates
# File vendor/plugins/ubiquo_i18n/lib/ubiquo_i18n/extensions/active_record.rb, line 369
369: def translating_relations
370: unless is_translating_relations
371: self.is_translating_relations = true
372: begin
373: yield
374: ensure
375: self.is_translating_relations = false
376: end
377: end
378: end
Disabled; run with $DEBUG to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.