]> git.openstreetmap.org Git - rails.git/blob - vendor/plugins/globalize2/lib/globalize/model/active_record/translated.rb
Allow the "remember me" label to wrap when showing OpenID URL field
[rails.git] / vendor / plugins / globalize2 / lib / globalize / model / active_record / translated.rb
1 module Globalize
2   module Model
3   
4     class MigrationError < StandardError; end
5     class UntranslatedMigrationField < MigrationError; end
6     class MigrationMissingTranslatedField < MigrationError; end
7     class BadMigrationFieldType < MigrationError; end
8   
9     module ActiveRecord
10       module Translated
11         def self.included(base)
12           base.extend ActMethods
13         end
14
15         module ActMethods
16           def translates(*attr_names)
17             options = attr_names.extract_options!
18             options[:translated_attributes] = attr_names
19
20             # Only set up once per class
21             unless included_modules.include? InstanceMethods
22               class_inheritable_accessor :globalize_options, :globalize_proxy
23               
24               include InstanceMethods
25               extend  ClassMethods
26               
27               self.globalize_proxy = Globalize::Model::ActiveRecord.create_proxy_class(self)
28               has_many(
29                 :globalize_translations,
30                 :class_name   => globalize_proxy.name,
31                 :extend       => Extensions,
32                 :dependent    => :delete_all,
33                 :foreign_key  => class_name.foreign_key
34               )
35
36               after_save :update_globalize_record              
37             end
38
39             self.globalize_options = options
40             Globalize::Model::ActiveRecord.define_accessors(self, attr_names)
41             
42             # Import any callbacks that have been defined by extensions to Globalize2
43             # and run them.
44             extend Callbacks
45             Callbacks.instance_methods.each {|cb| send cb }
46           end
47
48           def locale=(locale)
49             @@locale = locale
50           end
51           
52           def locale
53             (defined?(@@locale) && @@locale) || I18n.locale
54           end          
55         end
56
57         # Dummy Callbacks module. Extensions to Globalize2 can insert methods into here
58         # and they'll be called at the end of the translates class method.
59         module Callbacks
60         end
61         
62         # Extension to the has_many :globalize_translations association
63         module Extensions
64           def by_locales(locales)
65             find :all, :conditions => { :locale => locales.map(&:to_s) }
66           end
67         end
68         
69         module ClassMethods          
70           def method_missing(method, *args)
71             if method.to_s =~ /^find_by_(\w+)$/ && globalize_options[:translated_attributes].include?($1.to_sym)
72               find(:first, :joins => :globalize_translations,
73                    :conditions => [ "#{i18n_attr($1)} = ? AND #{i18n_attr('locale')} IN (?)",
74                                    args.first,I18n.fallbacks[I18n.locale].map{|tag| tag.to_s}])
75             else
76               super
77             end
78           end
79                     
80           def create_translation_table!(fields)
81             translated_fields = self.globalize_options[:translated_attributes]
82             translated_fields.each do |f|
83               raise MigrationMissingTranslatedField, "Missing translated field #{f}" unless fields[f]
84             end
85             fields.each do |name, type|
86               unless translated_fields.member? name 
87                 raise UntranslatedMigrationField, "Can't migrate untranslated field: #{name}"
88               end              
89               unless [ :string, :text ].member? type
90                 raise BadMigrationFieldType, "Bad field type for #{name}, should be :string or :text"
91               end 
92             end
93             translation_table_name = self.name.underscore + '_translations'
94             self.connection.create_table(translation_table_name) do |t|
95               t.references self.table_name.singularize
96               t.string :locale
97               fields.each do |name, type|
98                 t.column name, type
99               end
100               t.timestamps              
101             end
102           end
103
104           def drop_translation_table!
105             translation_table_name = self.name.underscore + '_translations'
106             self.connection.drop_table translation_table_name
107           end
108           
109           private
110           
111           def i18n_attr(attribute_name)
112             self.base_class.name.underscore + "_translations.#{attribute_name}"
113           end          
114         end
115         
116         module InstanceMethods
117           def reload(options = nil)
118             globalize.clear
119             
120             # clear all globalized attributes
121             # TODO what's the best way to handle this?
122             self.class.globalize_options[:translated_attributes].each do |attr|
123               @attributes.delete attr.to_s
124             end
125             
126             super options
127           end
128           
129           def globalize
130             @globalize ||= Adapter.new self
131           end
132           
133           def update_globalize_record
134             globalize.update_translations!
135           end
136           
137           def translated_locales
138             globalize_translations.scoped(:select => 'DISTINCT locale').map {|gt| gt.locale.to_sym }
139           end
140           
141           def set_translations options
142             options.keys.each do |key|
143
144               translation = globalize_translations.find_by_locale(key.to_s) ||
145                 globalize_translations.build(:locale => key.to_s)
146               translation.update_attributes!(options[key])
147             end
148           end
149           
150         end
151       end
152     end
153   end
154 end