summaryrefslogtreecommitdiff
path: root/vendor/plugins/globalize2/lib/globalize/model
diff options
context:
space:
mode:
authorhukl <contact@smyck.org>2010-01-14 22:21:43 +0100
committerhukl <contact@smyck.org>2010-01-14 22:21:43 +0100
commit57d1382013c85a7b11ac8ce5e683f6006b12b328 (patch)
tree19646c4fa5952fa1cf0a2c874952affa346373f1 /vendor/plugins/globalize2/lib/globalize/model
parent1b86bf5f2e35d1820bfa32d979bcc2d9ff9a9a8e (diff)
Updated globalize2 to latest version. Modified existing code accoringly
Diffstat (limited to 'vendor/plugins/globalize2/lib/globalize/model')
-rw-r--r--vendor/plugins/globalize2/lib/globalize/model/active_record.rb45
-rw-r--r--vendor/plugins/globalize2/lib/globalize/model/active_record/adapter.rb96
-rw-r--r--vendor/plugins/globalize2/lib/globalize/model/active_record/translated.rb164
3 files changed, 0 insertions, 305 deletions
diff --git a/vendor/plugins/globalize2/lib/globalize/model/active_record.rb b/vendor/plugins/globalize2/lib/globalize/model/active_record.rb
deleted file mode 100644
index 9218054c..00000000
--- a/vendor/plugins/globalize2/lib/globalize/model/active_record.rb
+++ /dev/null
@@ -1,45 +0,0 @@
1require 'globalize/translation'
2require 'globalize/locale/fallbacks'
3require 'globalize/model/active_record/adapter'
4require 'globalize/model/active_record/translated'
5
6module Globalize
7 module Model
8 module ActiveRecord
9 class << self
10 def create_proxy_class(klass)
11 module_names = klass.name.split('::')
12 klass_name = module_names.pop
13 target = module_names.empty? ? Object : module_names.join('::').constantize
14
15 target.const_set "#{klass_name}Translation", Class.new(::ActiveRecord::Base) {
16 belongs_to "#{klass.name.underscore.gsub('/', '_')}".intern
17
18 def locale
19 read_attribute(:locale).to_sym
20 end
21
22 def locale=(locale)
23 write_attribute(:locale, locale.to_s)
24 end
25 }
26 end
27
28 def define_accessors(klass, attr_names)
29 attr_names.each do |attr_name|
30 klass.send :define_method, attr_name, lambda {
31 globalize.fetch self.class.locale, attr_name
32 }
33 klass.send :define_method, "#{attr_name}_before_type_cast", lambda {
34 globalize.fetch self.class.locale, attr_name
35 }
36 klass.send :define_method, "#{attr_name}=", lambda {|val|
37 globalize.stash self.class.locale, attr_name, val
38 self[attr_name] = val
39 }
40 end
41 end
42 end
43 end
44 end
45end \ No newline at end of file
diff --git a/vendor/plugins/globalize2/lib/globalize/model/active_record/adapter.rb b/vendor/plugins/globalize2/lib/globalize/model/active_record/adapter.rb
deleted file mode 100644
index 93355b87..00000000
--- a/vendor/plugins/globalize2/lib/globalize/model/active_record/adapter.rb
+++ /dev/null
@@ -1,96 +0,0 @@
1module Globalize
2 module Model
3 class AttributeStash < Hash
4 def contains?(locale, attr_name)
5 locale = locale.to_sym
6 self[locale] ||= {}
7 self[locale].has_key? attr_name
8 end
9
10 def read(locale, attr_name)
11 locale = locale.to_sym
12 self[locale] ||= {}
13 self[locale][attr_name]
14 end
15
16 def write(locale, attr_name, value)
17 locale = locale.to_sym
18 self[locale] ||= {}
19 self[locale][attr_name] = value
20 end
21 end
22
23 class Adapter
24 def initialize(record)
25 @record = record
26
27 # TODO what exactly are the roles of cache and stash
28 @cache = AttributeStash.new
29 @stash = AttributeStash.new
30 end
31
32 def fetch(locale, attr_name)
33 # locale = I18n.locale
34 is_cached = @cache.contains?(locale, attr_name)
35 is_cached ? @cache.read(locale, attr_name) : begin
36 value = fetch_attribute locale, attr_name
37 @cache.write locale, attr_name, value if value && value.locale == locale
38 value
39 end
40 end
41
42 def stash(locale, attr_name, value)
43 @stash.write locale, attr_name, value
44 @cache.write locale, attr_name, value
45 end
46
47 def update_translations!
48 @stash.each do |locale, attrs|
49 translation = @record.globalize_translations.find_or_initialize_by_locale(locale.to_s)
50 attrs.each{|attr_name, value| translation[attr_name] = value }
51 translation.save!
52 end
53 @stash.clear
54 end
55
56 # Clears the cache
57 def clear
58 @cache.clear
59 @stash.clear
60 end
61
62 private
63
64 def fetch_attribute(locale, attr_name)
65 fallbacks = I18n.fallbacks[locale].map{|tag| tag.to_s}.map(&:to_sym)
66
67 # If the translations were included with
68 # :include => globalize_translations
69 # there is no need to query them again.
70 unless @record.globalize_translations.loaded?
71 translations = @record.globalize_translations.by_locales(fallbacks)
72 else
73 translations = @record.globalize_translations
74 end
75 result, requested_locale = nil, locale
76
77 # Walk through the fallbacks, starting with the current locale itself, and moving
78 # to the next best choice, until we find a match.
79 # Check the @globalize_set_translations cache first to see if we've just changed the
80 # attribute and not saved yet.
81 fallbacks.each do |fallback|
82 # TODO should we be checking stash or just cache?
83 result = @stash.read(fallback, attr_name) || begin
84 translation = translations.detect {|tr| tr.locale == fallback }
85 translation && translation.send(attr_name)
86 end
87 if result
88 locale = fallback
89 break
90 end
91 end
92 result && Translation::Attribute.new(result, :locale => locale, :requested_locale => requested_locale)
93 end
94 end
95 end
96end
diff --git a/vendor/plugins/globalize2/lib/globalize/model/active_record/translated.rb b/vendor/plugins/globalize2/lib/globalize/model/active_record/translated.rb
deleted file mode 100644
index 4f75c8ae..00000000
--- a/vendor/plugins/globalize2/lib/globalize/model/active_record/translated.rb
+++ /dev/null
@@ -1,164 +0,0 @@
1require 'digest/sha1'
2
3module Globalize
4 module Model
5 class MigrationError < StandardError; 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 { |callback| send(callback) }
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
86 fields.each do |name, type|
87 if translated_fields.include?(name) && ![:string, :text].include?(type)
88 raise BadMigrationFieldType, "Bad field type for #{name}, should be :string or :text"
89 end
90 end
91
92 self.connection.create_table(translation_table_name) do |t|
93 t.references self.table_name.singularize
94 t.string :locale
95 fields.each do |name, type|
96 t.column name, type
97 end
98 t.timestamps
99 end
100
101 self.connection.add_index(translation_table_name, "#{self.table_name.singularize}_id", :name => translation_index_name)
102 end
103
104 def translation_table_name
105 self.name.underscore.gsub('/', '_') + '_translations'
106 end
107
108 def translation_index_name
109 # FIXME what's the max size of an index name?
110 index_name = "index_#{translation_table_name}_on_#{self.table_name.singularize}_id"
111 index_name.size < 50 ? index_name : "index_#{Digest::SHA1.hexdigest(index_name)}"
112 end
113
114 def drop_translation_table!
115 self.connection.remove_index(translation_table_name, :name => translation_index_name)
116 self.connection.drop_table translation_table_name
117 end
118
119 private
120
121 def i18n_attr(attribute_name)
122 self.base_class.name.underscore.gsub('/', '_') + "_translations.#{attribute_name}"
123 end
124 end
125
126 module InstanceMethods
127 def reload(options = nil)
128 globalize.clear
129
130 # clear all globalized attributes
131 # TODO what's the best way to handle this?
132 self.class.globalize_options[:translated_attributes].each do |attr|
133 @attributes.delete(attr.to_s)
134 end
135
136 super(options)
137 end
138
139 def globalize
140 @globalize ||= Adapter.new self
141 end
142
143 def update_globalize_record
144 globalize.update_translations!
145 end
146
147 def translated_locales
148 globalize_translations.scoped(:select => 'DISTINCT locale').map do |translation|
149 translation.locale.to_sym
150 end
151 end
152
153 def set_translations options
154 options.keys.each do |key|
155 translation = globalize_translations.find_by_locale(key.to_s) ||
156 globalize_translations.build(:locale => key.to_s)
157 translation.update_attributes!(options[key])
158 end
159 end
160 end
161 end
162 end
163 end
164end \ No newline at end of file