globalize3 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -58,6 +58,11 @@ end
58
58
 
59
59
  Note that the ActiveRecord model @Post@ must already exist and have a @translates@ directive listing the translated fields.
60
60
 
61
+ h2. Changes since Globalize2
62
+
63
+ * `translation_table_name` was renamed to `translations_table_name`
64
+ * `available_locales` has been removed. please use `translated_locales`
65
+
61
66
  h2. Migration from Globalize for Rails (version 1)
62
67
 
63
68
  See this script by Tomasz Stachewicz: http://gist.github.com/120867
@@ -4,11 +4,27 @@ module Globalize
4
4
  autoload :ActiveRecord, 'globalize/active_record'
5
5
 
6
6
  class << self
7
+ def locale
8
+ defined?(@@locale) && @@locale || I18n.locale
9
+ end
10
+
11
+ def locale=(locale)
12
+ @@locale = locale
13
+ end
14
+
15
+ def with_locale(locale, &block)
16
+ previous_locale = defined?(@@locale) && @@locale || nil
17
+ self.locale = locale
18
+ result = yield
19
+ self.locale = previous_locale
20
+ result
21
+ end
22
+
7
23
  def fallbacks?
8
24
  I18n.respond_to?(:fallbacks)
9
25
  end
10
26
 
11
- def fallbacks(locale)
27
+ def fallbacks(locale = self.locale)
12
28
  fallbacks? ? I18n.fallbacks[locale] : [locale.to_sym]
13
29
  end
14
30
  end
@@ -10,46 +10,6 @@ module Globalize
10
10
  autoload :ClassMethods, 'globalize/active_record/class_methods'
11
11
  autoload :InstanceMethods, 'globalize/active_record/instance_methods'
12
12
  autoload :Migration, 'globalize/active_record/migration'
13
-
14
- class << self
15
- def build_translation_class(target, options)
16
- options[:table_name] ||= "#{target.table_name.singularize}_translations"
17
-
18
- klass = target.const_defined?(:Translation) ?
19
- target.const_get(:Translation) :
20
- target.const_set(:Translation, Class.new(::ActiveRecord::Base))
21
-
22
- klass.class_eval do
23
- set_table_name(options[:table_name])
24
-
25
- belongs_to target.name.underscore.gsub('/', '_')
26
-
27
- class << self
28
- def by_locale(locale)
29
- where(:locale => locale.to_s)
30
- end
31
-
32
- def by_locales(locales)
33
- where(:locale => locales.map(&:to_s))
34
- end
35
-
36
- # TODO build is not defined here even when called through record.translations.find_or_initialize_by_locale(...)
37
- # def find_or_initialize_by_locale(locale)
38
- # by_locale(locale.to_s).first || build(:locale => locale.to_s)
39
- # end
40
- end
41
-
42
- def locale
43
- read_attribute(:locale).to_sym
44
- end
45
-
46
- def locale=(locale)
47
- write_attribute(:locale, locale.to_s)
48
- end
49
- end
50
-
51
- klass
52
- end
53
- end
13
+ autoload :Translation, 'globalize/active_record/translation'
54
14
  end
55
15
  end
@@ -1,43 +1,31 @@
1
1
  module Globalize
2
2
  module ActiveRecord
3
3
  module ActMacro
4
- def locale
5
- (defined?(@@locale) && @@locale)
6
- end
7
-
8
- def locale=(locale)
9
- @@locale = locale
10
- end
11
-
12
4
  def translates(*attr_names)
13
5
  return if translates?
14
- options = attr_names.extract_options!
15
6
 
16
- class_inheritable_accessor :translation_class, :translated_attribute_names
17
- class_inheritable_writer :required_attributes
18
-
19
- self.translation_class = ActiveRecord.build_translation_class(self, options)
20
- self.translated_attribute_names = attr_names.map(&:to_sym)
7
+ options = attr_names.extract_options!
8
+ options[:table_name] ||= "#{table_name.singularize}_translations"
21
9
 
22
10
  include InstanceMethods
23
11
  extend ClassMethods, Migration
24
12
 
13
+ class_inheritable_accessor :translated_attribute_names, :translation_options
14
+ class_inheritable_writer :required_attributes
15
+
16
+ self.translated_attribute_names = attr_names.map(&:to_sym)
17
+ self.translation_options = options
18
+
25
19
  after_save :save_translations!
20
+
26
21
  has_many :translations, :class_name => translation_class.name,
27
22
  :foreign_key => class_name.foreign_key,
28
- :dependent => :delete_all
29
-
30
- scope :with_translations, lambda { |locale|
31
- conditions = required_attributes.map do |attribute|
32
- "#{quoted_translation_table_name}.#{attribute} IS NOT NULL"
33
- end
34
- conditions << "#{quoted_translation_table_name}.locale = ?"
35
- { :include => :translations, :conditions => [conditions.join(' AND '), locale] }
36
- }
23
+ :dependent => :delete_all,
24
+ :extend => HasManyExtensions
37
25
 
38
26
  attr_names.each { |attr_name| translated_attr_accessor(attr_name) }
39
27
  end
40
-
28
+
41
29
  def class_name
42
30
  class_name = table_name[table_name_prefix.length..-(table_name_suffix.length + 1)].camelize
43
31
  pluralize_table_names ? class_name.singularize : class_name
@@ -47,5 +35,11 @@ module Globalize
47
35
  included_modules.include?(InstanceMethods)
48
36
  end
49
37
  end
38
+
39
+ module HasManyExtensions
40
+ def find_or_initialize_by_locale(locale)
41
+ with_locale(locale.to_s).first || build(:locale => locale.to_s)
42
+ end
43
+ end
50
44
  end
51
45
  end
@@ -24,9 +24,7 @@ module Globalize
24
24
 
25
25
  def save_translations!
26
26
  stash.each do |locale, attrs|
27
- # TODO use find_or_initialize_by_locale
28
- translation = record.translations.by_locale(locale.to_s).first
29
- translation ||= record.translations.build(:locale => locale.to_s)
27
+ translation = record.translations.find_or_initialize_by_locale(locale.to_s)
30
28
  attrs.each { |attr_name, value| translation[attr_name] = value }
31
29
  translation.save!
32
30
  end
@@ -35,7 +33,6 @@ module Globalize
35
33
 
36
34
  def reset
37
35
  cache.clear
38
- # stash.clear
39
36
  end
40
37
 
41
38
  protected
@@ -43,13 +40,13 @@ module Globalize
43
40
  def fetch_translation(locale)
44
41
  locale = locale.to_sym
45
42
  record.translations.loaded? ? record.translations.detect { |t| t.locale == locale } :
46
- record.translations.by_locale(locale)
43
+ record.translations.with_locales(locale)
47
44
  end
48
45
 
49
46
  def fetch_translations(locale)
50
47
  # only query if not already included with :include => translations
51
48
  record.translations.loaded? ? record.translations :
52
- record.translations.by_locales(Globalize.fallbacks(locale))
49
+ record.translations.with_locales(Globalize.fallbacks(locale))
53
50
  end
54
51
 
55
52
  def fetch_attribute(locale, attr_name)
@@ -1,5 +1,6 @@
1
1
  # Helper class for storing values per locale. Used by Globalize::Adapter
2
2
  # to stash and cache attribute values.
3
+
3
4
  module Globalize
4
5
  module ActiveRecord
5
6
  class Attributes < Hash
@@ -1,27 +1,54 @@
1
1
  module Globalize
2
2
  module ActiveRecord
3
3
  module ClassMethods
4
- delegate :set_translation_table_name, :to => :translation_class
4
+ delegate :translated_locales, :set_translations_table_name, :to => :translation_class
5
5
 
6
- def with_locale(locale)
7
- previous_locale, self.locale = self.locale, locale
8
- result = yield
9
- self.locale = previous_locale
10
- result
6
+ def with_locales(*locales)
7
+ scoped & translation_class.with_locales(*locales)
11
8
  end
12
9
 
13
- def translation_table_name
14
- translation_class.table_name
10
+ def with_translations(*locales)
11
+ locales = translated_locales if locales.empty?
12
+ includes(:translations).with_locales(locales).with_required_attributes
15
13
  end
16
14
 
17
- def quoted_translation_table_name
18
- translation_class.quoted_table_name
15
+ def with_required_attributes
16
+ required_translated_attributes.inject(scoped) do |scope, name|
17
+ scope.where("#{translated_column_name(name)} IS NOT NULL")
18
+ end
19
+ end
20
+
21
+ def with_translated_attribute(name, value, locales = nil)
22
+ locales ||= Globalize.fallbacks
23
+ with_translations.where(
24
+ translated_column_name(name) => value,
25
+ translated_column_name(:locale) => locales.map(&:to_s)
26
+ )
19
27
  end
20
28
 
21
29
  def required_attributes
22
- @required_attributes ||= reflect_on_all_validations.select do |validation|
23
- validation.macro == :validates_presence_of && translated_attribute_names.include?(validation.name)
24
- end.map(&:name)
30
+ validators.map { |v| v.attributes if v.is_a?(ActiveModel::Validations::PresenceValidator) }.flatten
31
+ end
32
+
33
+ def required_translated_attributes
34
+ translated_attribute_names & required_attributes
35
+ end
36
+
37
+ def translation_class
38
+ klass = const_get(:Translation) rescue const_set(:Translation, Class.new(Translation))
39
+ if klass.table_name == 'translations'
40
+ klass.set_table_name(translation_options[:table_name])
41
+ klass.belongs_to name.underscore.gsub('/', '_')
42
+ end
43
+ klass
44
+ end
45
+
46
+ def translations_table_name
47
+ translation_class.table_name
48
+ end
49
+
50
+ def translated_column_name(name)
51
+ "#{translation_class.table_name}.#{name}"
25
52
  end
26
53
 
27
54
  def respond_to?(method, *args, &block)
@@ -29,8 +56,9 @@ module Globalize
29
56
  end
30
57
 
31
58
  def method_missing(method, *args)
32
- if method.to_s =~ /^find_by_(\w+)$/ && translated_attribute_names.include?($1.to_sym)
33
- find_first_by_translated_attr_and_locales($1, args.first)
59
+ if method.to_s =~ /^find_(first_|)by_(\w+)$/ && translated_attribute_names.include?($2.to_sym)
60
+ result = with_translated_attribute($2, args.first)
61
+ $1 == 'first_' ? result.first : result
34
62
  else
35
63
  super
36
64
  end
@@ -38,30 +66,15 @@ module Globalize
38
66
 
39
67
  protected
40
68
 
41
- def find_first_by_translated_attr_and_locales(name, value)
42
- query = "#{translated_attr_name(name)} = ? AND #{translated_attr_name('locale')} IN (?)"
43
- locales = Globalize.fallbacks(locale || I18n.locale).map(&:to_s)
44
- find(
45
- :first,
46
- :joins => :translations,
47
- :conditions => [query, value, locales],
48
- :readonly => false
49
- )
50
- end
51
-
52
69
  def translated_attr_accessor(name)
53
- define_method "#{name}=", lambda { |value|
54
- globalize.write(self.class.locale || I18n.locale, name, value)
70
+ define_method :"#{name}=", lambda { |value|
71
+ globalize.write(Globalize.locale, name, value)
55
72
  self[name] = value
56
73
  }
57
74
  define_method name, lambda { |*args|
58
- globalize.fetch(args.first || self.class.locale || I18n.locale, name)
75
+ globalize.fetch(args.first || Globalize.locale, name)
59
76
  }
60
- alias_method "#{name}_before_type_cast", name
61
- end
62
-
63
- def translated_attr_name(name)
64
- "#{translation_class.table_name}.#{name}"
77
+ alias_method :"#{name}_before_type_cast", name
65
78
  end
66
79
  end
67
80
  end
@@ -1,21 +1,19 @@
1
1
  module Globalize
2
2
  module ActiveRecord
3
3
  module InstanceMethods
4
+ delegate :translated_locales, :to => :translations
5
+
4
6
  def globalize
5
7
  @globalize ||= Adapter.new self
6
8
  end
7
9
 
8
10
  def attributes
9
- self.attribute_names.inject({}) do |attrs, name|
10
- attrs[name] = read_attribute(name) ||
11
- (globalize.fetch(I18n.locale, name) rescue nil)
12
- attrs
13
- end
11
+ super.merge(translated_attributes)
14
12
  end
15
13
 
16
14
  def attributes=(attributes, *args)
17
- if attributes.respond_to?(:delete) && locale = attributes.delete(:locale)
18
- self.class.with_locale(locale) { super }
15
+ if locale = attributes.try(:delete, :locale)
16
+ Globalize.with_locale(locale) { super }
19
17
  else
20
18
  super
21
19
  end
@@ -24,18 +22,10 @@ module Globalize
24
22
  def attribute_names
25
23
  translated_attribute_names.map(&:to_s) + super
26
24
  end
27
-
28
- def available_locales
29
- translations.select('DISTINCT locale').map(&:locale)
30
- end
31
-
32
- def translated_locales
33
- translations.map(&:locale)
34
- end
35
-
25
+
36
26
  def translated_attributes
37
27
  translated_attribute_names.inject({}) do |attributes, name|
38
- attributes.merge(name => send(name))
28
+ attributes.merge(name.to_s => send(name))
39
29
  end
40
30
  end
41
31
 
@@ -12,7 +12,7 @@ module Globalize
12
12
  end
13
13
  end
14
14
 
15
- self.connection.create_table(translation_table_name) do |t|
15
+ self.connection.create_table(translations_table_name) do |t|
16
16
  t.references table_name.sub(/^#{table_name_prefix}/, "").singularize
17
17
  t.string :locale
18
18
  fields.each do |name, type|
@@ -22,7 +22,7 @@ module Globalize
22
22
  end
23
23
 
24
24
  self.connection.add_index(
25
- translation_table_name,
25
+ translations_table_name,
26
26
  "#{table_name.sub(/^#{table_name_prefix}/, "").singularize}_id",
27
27
  :name => translation_index_name
28
28
  )
@@ -31,13 +31,13 @@ module Globalize
31
31
  def translation_index_name
32
32
  require 'digest/sha1'
33
33
  # FIXME what's the max size of an index name?
34
- index_name = "index_#{translation_table_name}_on_#{self.table_name.singularize}_id"
34
+ index_name = "index_#{translations_table_name}_on_#{self.table_name.singularize}_id"
35
35
  index_name.size < 50 ? index_name : "index_#{Digest::SHA1.hexdigest(index_name)}"
36
36
  end
37
37
 
38
38
  def drop_translation_table!
39
- self.connection.remove_index(translation_table_name, :name => translation_index_name) rescue nil
40
- self.connection.drop_table(translation_table_name)
39
+ self.connection.remove_index(translations_table_name, :name => translation_index_name) rescue nil
40
+ self.connection.drop_table(translations_table_name)
41
41
  end
42
42
  end
43
43
  end
@@ -0,0 +1,24 @@
1
+ module Globalize
2
+ module ActiveRecord
3
+ class Translation < ::ActiveRecord::Base
4
+ class << self
5
+ def with_locales(*locales)
6
+ where(:locale => locales.flatten.map(&:to_s))
7
+ end
8
+ alias with_locale with_locales
9
+
10
+ def translated_locales
11
+ select('DISTINCT locale').map(&:locale)
12
+ end
13
+ end
14
+
15
+ def locale
16
+ read_attribute(:locale).to_sym
17
+ end
18
+
19
+ def locale=(locale)
20
+ write_attribute(:locale, locale.to_s)
21
+ end
22
+ end
23
+ end
24
+ end
@@ -1,3 +1,3 @@
1
1
  module Globalize
2
- VERSION = '0.0.1'
2
+ VERSION = '0.0.2'
3
3
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: globalize3
3
3
  version: !ruby/object:Gem::Version
4
- hash: 29
4
+ hash: 27
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 1
10
- version: 0.0.1
9
+ - 2
10
+ version: 0.0.2
11
11
  platform: ruby
12
12
  authors:
13
13
  - Sven Fuchs
@@ -18,7 +18,7 @@ autorequire:
18
18
  bindir: bin
19
19
  cert_chain: []
20
20
 
21
- date: 2010-07-30 00:00:00 +02:00
21
+ date: 2010-07-31 00:00:00 +02:00
22
22
  default_executable:
23
23
  dependencies:
24
24
  - !ruby/object:Gem::Dependency
@@ -53,6 +53,7 @@ files:
53
53
  - lib/globalize/active_record/class_methods.rb
54
54
  - lib/globalize/active_record/instance_methods.rb
55
55
  - lib/globalize/active_record/migration.rb
56
+ - lib/globalize/active_record/translation.rb
56
57
  - lib/globalize/active_record.rb
57
58
  - lib/globalize/version.rb
58
59
  - lib/globalize.rb