globalize3 0.0.1 → 0.0.2

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.
@@ -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