single_table_globalize3 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +1 -1
- data/Gemfile.lock +1 -12
- data/lib/generators/single_table_globalize3/migration_generator.rb +12 -0
- data/lib/generators/{globalize3 → single_table_globalize3}/templates/migration.rb +0 -0
- data/lib/i18n/missing_translations_log_handler.rb +1 -1
- data/lib/i18n/missing_translations_raise_handler.rb +1 -1
- data/lib/patches/active_record/uniqueness_validator.rb +2 -2
- data/lib/{globalize → single_table_globalize3}/active_record/act_macro.rb +9 -27
- data/lib/{globalize → single_table_globalize3}/active_record/adapter.rb +13 -12
- data/lib/single_table_globalize3/active_record/attribute_read_write.rb +75 -0
- data/lib/{globalize → single_table_globalize3}/active_record/attributes.rb +2 -2
- data/lib/{globalize → single_table_globalize3}/active_record/class_methods.rb +3 -61
- data/lib/{globalize → single_table_globalize3}/active_record/exceptions.rb +4 -4
- data/lib/{globalize → single_table_globalize3}/active_record/instance_methods.rb +6 -73
- data/lib/{globalize → single_table_globalize3}/active_record/translation.rb +7 -1
- data/lib/single_table_globalize3/active_record/with_translations.rb +59 -0
- data/lib/single_table_globalize3/active_record.rb +14 -0
- data/lib/single_table_globalize3/version.rb +1 -1
- data/lib/single_table_globalize3.rb +73 -1
- metadata +16 -16
- data/lib/generators/globalize3/migration_generator.rb +0 -14
- data/lib/globalize/active_record.rb +0 -12
- data/lib/globalize.rb +0 -74
- data/lib/patches/active_record/query_method.rb +0 -35
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 26717252049728b19cb768820301e55d01b6d0d9
|
4
|
+
data.tar.gz: ddd3692c29e5a96c960150c36209df54ee1c0286
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b73332cb50bfe6a2d706a6ad4450fb471c64dc102264a2310171e12f1ee78d43dfaf59ed8fe8bc14ebddc26cbbcbea5e711b4638057c38168a06266bc90d4745
|
7
|
+
data.tar.gz: 238fbd2b8c9bb11dec4c5cc3a58a8d529f734171f896d86f1109dd66d38248b31ba36c196b35d6567253ac55d49aec26dcd1ba276245f285dfc6fa906fe33475
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
single_table_globalize3 (0.
|
4
|
+
single_table_globalize3 (0.0.1)
|
5
5
|
activemodel (>= 3.0.0)
|
6
6
|
activerecord (>= 3.0.0)
|
7
7
|
|
@@ -21,26 +21,17 @@ GEM
|
|
21
21
|
multi_json (~> 1.0)
|
22
22
|
arel (3.0.2)
|
23
23
|
builder (3.0.4)
|
24
|
-
coderay (1.0.8)
|
25
24
|
database_cleaner (0.6.7)
|
26
25
|
i18n (0.6.1)
|
27
26
|
json (1.7.7)
|
28
27
|
metaclass (0.0.1)
|
29
|
-
method_source (0.8.1)
|
30
28
|
mocha (0.13.2)
|
31
29
|
metaclass (~> 0.0.1)
|
32
30
|
multi_json (1.6.1)
|
33
31
|
pathname_local (0.0.2)
|
34
|
-
pry (0.9.12)
|
35
|
-
coderay (~> 1.0.5)
|
36
|
-
method_source (~> 0.8)
|
37
|
-
slop (~> 3.4)
|
38
|
-
pry-nav (0.2.3)
|
39
|
-
pry (~> 0.9.10)
|
40
32
|
rake (10.0.3)
|
41
33
|
rdoc (3.12.1)
|
42
34
|
json (~> 1.4)
|
43
|
-
slop (3.4.3)
|
44
35
|
sqlite3 (1.3.7)
|
45
36
|
test_declarative (0.0.5)
|
46
37
|
tzinfo (0.3.35)
|
@@ -52,8 +43,6 @@ DEPENDENCIES
|
|
52
43
|
database_cleaner (~> 0.6.0)
|
53
44
|
mocha
|
54
45
|
pathname_local
|
55
|
-
pry
|
56
|
-
pry-nav
|
57
46
|
rake
|
58
47
|
rdoc
|
59
48
|
single_table_globalize3!
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'rails/generators/active_record'
|
2
|
+
|
3
|
+
module SingleTableGlobalize3
|
4
|
+
class MigrationGenerator < ::ActiveRecord::Generators::Base
|
5
|
+
source_root File.expand_path("../templates", __FILE__)
|
6
|
+
argument :name, :type => :string, :default => "application"
|
7
|
+
|
8
|
+
def copy_devise_migration
|
9
|
+
migration_template "migration.rb", "db/migrate/create_globalize_translations"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
File without changes
|
@@ -5,7 +5,7 @@
|
|
5
5
|
#
|
6
6
|
# E.g.
|
7
7
|
#
|
8
|
-
# require '
|
8
|
+
# require 'single_table_globalize3/i18n/missing_translations_log_handler'
|
9
9
|
# I18n.missing_translations_logger = RAILS_DEFAULT_LOGGER
|
10
10
|
# I18n.exception_handler = :missing_translations_log_handler
|
11
11
|
#
|
@@ -9,7 +9,7 @@ ActiveRecord::Validations::UniquenessValidator.class_eval do
|
|
9
9
|
table = finder_class.arel_table
|
10
10
|
|
11
11
|
relation = build_relation(finder_class, table, 'attribute_name', attribute).
|
12
|
-
and(table[:locale].eq(
|
12
|
+
and(table[:locale].eq(SingleTableGlobalize3.locale)).
|
13
13
|
and(table[:value].eq(value)).
|
14
14
|
and(table[:translatable_type].eq(klass.name))
|
15
15
|
relation = relation.and(table[klass.reflect_on_association(:translations).foreign_key].not_eq(record.send(:id))) if record.persisted?
|
@@ -35,7 +35,7 @@ ActiveRecord::Validations::UniquenessValidator.class_eval do
|
|
35
35
|
sql, params = mount_sql_and_params(finder_class, table_name, 'value', value)
|
36
36
|
|
37
37
|
relation = table.where(sql, *params).
|
38
|
-
where(:locale =>
|
38
|
+
where(:locale => SingleTableGlobalize3.locale).
|
39
39
|
where(:attribute_name => attribute).
|
40
40
|
where(:translatable_type => klass.name)
|
41
41
|
|
@@ -1,4 +1,4 @@
|
|
1
|
-
module
|
1
|
+
module SingleTableGlobalize3
|
2
2
|
module ActiveRecord
|
3
3
|
module ActMacro
|
4
4
|
def translates(*attr_names)
|
@@ -9,31 +9,13 @@ module Globalize
|
|
9
9
|
attr_names = attr_names.map(&:to_sym)
|
10
10
|
attr_names -= translated_attribute_names if defined?(translated_attribute_names)
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
12
|
+
attr_names.each do |attr_name|
|
13
|
+
# Create accessors for the attribute.
|
14
|
+
translated_attr_accessor(attr_name)
|
15
|
+
translations_accessor(attr_name)
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
serializer = self.serialized_attributes[attr_name.to_s]
|
20
|
-
if serializer.present?
|
21
|
-
if defined?(::ActiveRecord::Coders::YAMLColumn) &&
|
22
|
-
serializer.is_a?(::ActiveRecord::Coders::YAMLColumn)
|
23
|
-
|
24
|
-
serializer = serializer.object_class
|
25
|
-
end
|
26
|
-
|
27
|
-
translation_class.send :serialize, attr_name, serializer
|
28
|
-
end
|
29
|
-
|
30
|
-
# Create accessors for the attribute.
|
31
|
-
translated_attr_accessor(attr_name)
|
32
|
-
translations_accessor(attr_name)
|
33
|
-
|
34
|
-
# Add attribute to the list.
|
35
|
-
self.translated_attribute_names << attr_name
|
36
|
-
end
|
17
|
+
# Add attribute to the list.
|
18
|
+
self.translated_attribute_names << attr_name
|
37
19
|
end
|
38
20
|
end
|
39
21
|
|
@@ -58,8 +40,8 @@ module Globalize
|
|
58
40
|
|
59
41
|
after_create :save_translations!
|
60
42
|
after_update :save_translations!
|
61
|
-
|
62
|
-
|
43
|
+
# if attr_accessible is explicitly defined in the class, add locale to it
|
44
|
+
attr_accessible :locale if self.accessible_attributes.to_a.present?
|
63
45
|
end
|
64
46
|
end
|
65
47
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
module
|
1
|
+
module SingleTableGlobalize3
|
2
2
|
module ActiveRecord
|
3
3
|
class Adapter
|
4
4
|
# The cache caches attributes that already were looked up for read access.
|
@@ -14,9 +14,17 @@ module Globalize
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def fetch_stash(locale, name)
|
17
|
-
|
18
|
-
|
19
|
-
|
17
|
+
stash.read(locale, name)
|
18
|
+
end
|
19
|
+
|
20
|
+
def fetch_locales(name)
|
21
|
+
stash.keys.inject({}) do |result, locale|
|
22
|
+
if stash_contains?(locale, name)
|
23
|
+
result.update(locale => fetch_stash(locale, name))
|
24
|
+
else
|
25
|
+
result
|
26
|
+
end
|
27
|
+
end
|
20
28
|
end
|
21
29
|
|
22
30
|
def stash_contains?(locale, name)
|
@@ -41,17 +49,10 @@ module Globalize
|
|
41
49
|
end
|
42
50
|
|
43
51
|
def save_translations!
|
44
|
-
existing_translations = {}
|
45
|
-
record.translations.each do |t|
|
46
|
-
locale_str = t.locale.to_s
|
47
|
-
existing_translations[locale_str] ||= {}
|
48
|
-
existing_translations[locale_str][t.attribute_name] = t
|
49
|
-
end
|
50
|
-
|
51
52
|
stash.each do |locale, attrs|
|
52
53
|
locale_str = locale.to_s
|
53
54
|
attrs.each do |name, value|
|
54
|
-
translation =
|
55
|
+
translation = record.translations.detect {|t| t.locale.to_s == locale_str && t.attribute_name == name } ||
|
55
56
|
record.translations.build(:locale => locale_str, :attribute_name => name)
|
56
57
|
translation.update_attribute(:value, value)
|
57
58
|
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module SingleTableGlobalize3
|
2
|
+
module ActiveRecord
|
3
|
+
module AttributeReadWrite
|
4
|
+
delegate :translated_locales, :to => :translations
|
5
|
+
def attributes
|
6
|
+
super.merge(translated_attributes)
|
7
|
+
end
|
8
|
+
|
9
|
+
# Deprecate old use of locale
|
10
|
+
def deprecated_options(options)
|
11
|
+
unless options.is_a?(Hash)
|
12
|
+
warn "[DEPRECATION] passing 'locale' as #{options.inspect} is deprecated. Please use {:locale => #{options.inspect}} instead."
|
13
|
+
{:locale => options}
|
14
|
+
else
|
15
|
+
options
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def write_attribute(name, value, options = {})
|
20
|
+
if translated?(name)
|
21
|
+
options = {:locale => SingleTableGlobalize3.locale}.merge(deprecated_options(options))
|
22
|
+
|
23
|
+
# Dirty tracking, paraphrased from
|
24
|
+
# ActiveRecord::AttributeMethods::Dirty#write_attribute.
|
25
|
+
name_str = name.to_s
|
26
|
+
# If there's already a change, delete it if this undoes the change.
|
27
|
+
if attribute_changed?(name_str) && value == changed_attributes[name_str]
|
28
|
+
changed_attributes.delete(name_str)
|
29
|
+
elsif !attribute_changed?(name_str) && value != (old = globalize.fetch(options[:locale], name))
|
30
|
+
changed_attributes[name_str] = old
|
31
|
+
end
|
32
|
+
|
33
|
+
globalize.write(options[:locale], name, value)
|
34
|
+
else
|
35
|
+
super(name, value)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def read_attribute(name, options = {})
|
40
|
+
options = {:translated => true, :locale => nil}.merge(deprecated_options(options))
|
41
|
+
if (self.class.translated?(name) && options[:translated]) && (value = globalize.fetch(options[:locale] || SingleTableGlobalize3.locale, name))
|
42
|
+
value
|
43
|
+
else
|
44
|
+
super(name)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def attribute_names
|
49
|
+
translated_attribute_names.map(&:to_s) + super
|
50
|
+
end
|
51
|
+
|
52
|
+
def translated?(name)
|
53
|
+
self.class.translated?(name)
|
54
|
+
end
|
55
|
+
|
56
|
+
def translated_attributes
|
57
|
+
translated_attribute_names.inject({}) do |attributes, name|
|
58
|
+
attributes.merge(name.to_s => translation[name.to_s].try(:value))
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# This method is basically the method built into Rails
|
63
|
+
# but we have to pass {:translated => false}
|
64
|
+
def untranslated_attributes
|
65
|
+
attrs = {}
|
66
|
+
attribute_names.each do |name|
|
67
|
+
attrs[name] = read_attribute(name, {:translated => false})
|
68
|
+
end
|
69
|
+
attrs
|
70
|
+
end
|
71
|
+
|
72
|
+
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
|
-
# Helper class for storing values per locale. Used by
|
1
|
+
# Helper class for storing values per locale. Used by SingleTableGlobalize3::Adapter
|
2
2
|
# to stash and cache attribute values.
|
3
3
|
|
4
|
-
module
|
4
|
+
module SingleTableGlobalize3
|
5
5
|
module ActiveRecord
|
6
6
|
class Attributes < Hash # TODO: Think about using HashWithIndifferentAccess ?
|
7
7
|
def [](locale)
|
@@ -1,49 +1,7 @@
|
|
1
|
-
module
|
1
|
+
module SingleTableGlobalize3
|
2
2
|
module ActiveRecord
|
3
3
|
module ClassMethods
|
4
|
-
|
5
|
-
|
6
|
-
def with_translations(*locales)
|
7
|
-
locales = [locales].flatten
|
8
|
-
index = locales.pop if locales.last.is_a?(Fixnum)
|
9
|
-
locales = Globalize.fallbacks if locales.empty?
|
10
|
-
joins("LEFT OUTER JOIN #{translation_class.table_name} #{translations_table_name(index)} ON #{translations_table_name(index)}.translatable_id = #{self.table_name}.id").
|
11
|
-
select("distinct #{table_name}.*").
|
12
|
-
where(translated_column_name('locale', index) => locales)
|
13
|
-
end
|
14
|
-
|
15
|
-
def with_translated_attribute(name, value, locales = nil)
|
16
|
-
locales ||= Globalize.fallbacks
|
17
|
-
self.join_index = self.join_index + 1
|
18
|
-
with_translations(locales, self.join_index).where(
|
19
|
-
translated_column_name('attribute_name', self.join_index) => name.to_s,
|
20
|
-
translated_column_name('value', self.join_index) => Array(value).map(&:to_s)
|
21
|
-
)
|
22
|
-
end
|
23
|
-
|
24
|
-
def translated?(name)
|
25
|
-
translated_attribute_names.include?(name.to_sym)
|
26
|
-
end
|
27
|
-
|
28
|
-
def required_attributes
|
29
|
-
validators.map { |v| v.attributes if v.is_a?(ActiveModel::Validations::PresenceValidator) }.flatten
|
30
|
-
end
|
31
|
-
|
32
|
-
def required_translated_attributes
|
33
|
-
translated_attribute_names & required_attributes
|
34
|
-
end
|
35
|
-
|
36
|
-
def translation_class
|
37
|
-
Globalize::ActiveRecord::Translation
|
38
|
-
end
|
39
|
-
|
40
|
-
def translations_table_name(index = nil)
|
41
|
-
"#{translation_class.table_name}#{index}"
|
42
|
-
end
|
43
|
-
|
44
|
-
def translated_column_name(name, index = nil)
|
45
|
-
"#{translations_table_name(index)}.#{name}"
|
46
|
-
end
|
4
|
+
include WithTranslations
|
47
5
|
|
48
6
|
if RUBY_VERSION < '1.9'
|
49
7
|
def respond_to?(method_id, *args, &block)
|
@@ -139,12 +97,7 @@ module Globalize
|
|
139
97
|
|
140
98
|
def translations_accessor(name)
|
141
99
|
define_method(:"#{name}_translations") do
|
142
|
-
|
143
|
-
result[translation.locale] = translation.value
|
144
|
-
end
|
145
|
-
globalize.stash.keys.each_with_object(result) do |locale, result|
|
146
|
-
result[locale] = globalize.fetch_stash(locale, name) if globalize.stash_contains?(locale, name)
|
147
|
-
end
|
100
|
+
translations.attribute_translations(name).merge(globalize.fetch_locales(name))
|
148
101
|
end
|
149
102
|
define_method(:"#{name}_translations=") do |value|
|
150
103
|
value.each do |(locale, value)|
|
@@ -152,17 +105,6 @@ module Globalize
|
|
152
105
|
end
|
153
106
|
end
|
154
107
|
end
|
155
|
-
|
156
|
-
def join_index
|
157
|
-
@join_index = 0 if @join_index.nil? || @join_index > 100
|
158
|
-
@join_index
|
159
|
-
end
|
160
|
-
|
161
|
-
def join_index=(value)
|
162
|
-
@join_index = value
|
163
|
-
end
|
164
108
|
end
|
165
|
-
|
166
109
|
end
|
167
|
-
|
168
110
|
end
|
@@ -1,14 +1,14 @@
|
|
1
|
-
module
|
1
|
+
module SingleTableGlobalize3
|
2
2
|
module ActiveRecord
|
3
3
|
module Exceptions
|
4
4
|
class MigrationError < StandardError; end
|
5
|
-
|
5
|
+
|
6
6
|
class BadFieldName < MigrationError
|
7
7
|
def initialize(field)
|
8
8
|
super("Missing translated field #{field.inspect}")
|
9
9
|
end
|
10
10
|
end
|
11
|
-
|
11
|
+
|
12
12
|
class BadFieldType < MigrationError
|
13
13
|
def initialize(name, type)
|
14
14
|
super("Bad field type for field #{name.inspect} (#{type.inspect}), should be :string or :text")
|
@@ -16,4 +16,4 @@ module Globalize
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
end
|
19
|
-
end
|
19
|
+
end
|
@@ -1,16 +1,12 @@
|
|
1
|
-
module
|
1
|
+
module SingleTableGlobalize3
|
2
2
|
module ActiveRecord
|
3
3
|
module InstanceMethods
|
4
|
-
|
4
|
+
include AttributeReadWrite
|
5
5
|
|
6
6
|
def globalize
|
7
7
|
@globalize ||= Adapter.new(self)
|
8
8
|
end
|
9
9
|
|
10
|
-
def attributes
|
11
|
-
super.merge(translated_attributes)
|
12
|
-
end
|
13
|
-
|
14
10
|
def self.included(base)
|
15
11
|
# Maintain Rails 3.0.x compatibility while adding Rails 3.1.x compatibility
|
16
12
|
if base.method_defined?(:assign_attributes)
|
@@ -36,76 +32,13 @@ module Globalize
|
|
36
32
|
end
|
37
33
|
end
|
38
34
|
|
39
|
-
# Deprecate old use of locale
|
40
|
-
def deprecated_options(options)
|
41
|
-
unless options.is_a?(Hash)
|
42
|
-
warn "[DEPRECATION] passing 'locale' as #{options.inspect} is deprecated. Please use {:locale => #{options.inspect}} instead."
|
43
|
-
{:locale => options}
|
44
|
-
else
|
45
|
-
options
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
def write_attribute(name, value, options = {})
|
50
|
-
if translated?(name)
|
51
|
-
options = {:locale => Globalize.locale}.merge(deprecated_options(options))
|
52
|
-
|
53
|
-
# Dirty tracking, paraphrased from
|
54
|
-
# ActiveRecord::AttributeMethods::Dirty#write_attribute.
|
55
|
-
name_str = name.to_s
|
56
|
-
# If there's already a change, delete it if this undoes the change.
|
57
|
-
if attribute_changed?(name_str) && value == changed_attributes[name_str]
|
58
|
-
changed_attributes.delete(name_str)
|
59
|
-
elsif !attribute_changed?(name_str) && value != (old = globalize.fetch(options[:locale], name))
|
60
|
-
changed_attributes[name_str] = old
|
61
|
-
end
|
62
|
-
|
63
|
-
globalize.write(options[:locale], name, value)
|
64
|
-
else
|
65
|
-
super(name, value)
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
def read_attribute(name, options = {})
|
70
|
-
options = {:translated => true, :locale => nil}.merge(deprecated_options(options))
|
71
|
-
if (self.class.translated?(name) && options[:translated]) && (value = globalize.fetch(options[:locale] || Globalize.locale, name))
|
72
|
-
value
|
73
|
-
else
|
74
|
-
super(name)
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
def attribute_names
|
79
|
-
translated_attribute_names.map(&:to_s) + super
|
80
|
-
end
|
81
|
-
|
82
|
-
def translated?(name)
|
83
|
-
self.class.translated?(name)
|
84
|
-
end
|
85
|
-
|
86
|
-
def translated_attributes
|
87
|
-
translated_attribute_names.inject({}) do |attributes, name|
|
88
|
-
attributes.merge(name.to_s => translation[name.to_s].try(:value))
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
# This method is basically the method built into Rails
|
93
|
-
# but we have to pass {:translated => false}
|
94
|
-
def untranslated_attributes
|
95
|
-
attrs = {}
|
96
|
-
attribute_names.each do |name|
|
97
|
-
attrs[name] = read_attribute(name, {:translated => false})
|
98
|
-
end
|
99
|
-
attrs
|
100
|
-
end
|
101
|
-
|
102
35
|
def set_translations(options)
|
103
36
|
options.keys.each do |locale|
|
104
37
|
options[locale].each do |key, value|
|
105
38
|
raise NoMethodError.new("unknown attribute: #{key}") unless attribute_names.flatten.include?(key.to_s)
|
106
39
|
translation = translation_for(locale, key.to_s)
|
107
40
|
translation.value = value
|
108
|
-
translation.save
|
41
|
+
translation.save!
|
109
42
|
end
|
110
43
|
end
|
111
44
|
globalize.reset
|
@@ -132,7 +65,7 @@ module Globalize
|
|
132
65
|
end
|
133
66
|
|
134
67
|
def translation
|
135
|
-
translations_for_locale(::
|
68
|
+
translations_for_locale(::SingleTableGlobalize3.locale)
|
136
69
|
end
|
137
70
|
|
138
71
|
def translation_for(locale, name, build_if_missing = true)
|
@@ -157,7 +90,7 @@ module Globalize
|
|
157
90
|
end
|
158
91
|
|
159
92
|
def globalize_fallbacks(locale)
|
160
|
-
|
93
|
+
SingleTableGlobalize3.fallbacks(locale)
|
161
94
|
end
|
162
95
|
|
163
96
|
private
|
@@ -200,7 +133,7 @@ module Globalize
|
|
200
133
|
attributes.try(:delete, :locale)
|
201
134
|
|
202
135
|
if locale
|
203
|
-
|
136
|
+
SingleTableGlobalize3.with_locale(locale, &block)
|
204
137
|
else
|
205
138
|
yield
|
206
139
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
module
|
1
|
+
module SingleTableGlobalize3
|
2
2
|
module ActiveRecord
|
3
3
|
class Translation < ::ActiveRecord::Base
|
4
4
|
if self.respond_to?(:table_name=)
|
@@ -28,6 +28,12 @@ module Globalize
|
|
28
28
|
attribute = attribute.to_s
|
29
29
|
where :attribute_name => attribute
|
30
30
|
end
|
31
|
+
|
32
|
+
def attribute_translations(attribute)
|
33
|
+
attribute(attribute).inject(HashWithIndifferentAccess.new) do |hash, translation|
|
34
|
+
hash.update(translation.locale => translation.value)
|
35
|
+
end
|
36
|
+
end
|
31
37
|
end
|
32
38
|
|
33
39
|
def locale
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module SingleTableGlobalize3
|
2
|
+
module ActiveRecord
|
3
|
+
module WithTranslations
|
4
|
+
delegate :translated_locales, :to => :translation_class
|
5
|
+
|
6
|
+
def with_translations(*locales)
|
7
|
+
index = locales.pop if locales.last.is_a?(Fixnum)
|
8
|
+
locales = locales.concat(SingleTableGlobalize3.fallbacks).flatten.map(&:to_s)
|
9
|
+
alias_table_name = translations_table_name(index)
|
10
|
+
|
11
|
+
joins("LEFT OUTER JOIN #{translation_class.table_name} #{alias_table_name} ON #{alias_table_name}.translatable_id = #{table_name}.id").
|
12
|
+
select("distinct #{table_name}.*").
|
13
|
+
where(translated_column_name('locale', index) => locales)
|
14
|
+
end
|
15
|
+
|
16
|
+
def with_translated_attribute(name, value, locales = nil)
|
17
|
+
locales ||= SingleTableGlobalize3.fallbacks
|
18
|
+
self.join_index = self.join_index + 1
|
19
|
+
with_translations(locales, self.join_index).where(
|
20
|
+
translated_column_name('attribute_name', self.join_index) => name.to_s,
|
21
|
+
translated_column_name('value', self.join_index) => Array(value).map(&:to_s)
|
22
|
+
)
|
23
|
+
end
|
24
|
+
|
25
|
+
def translated?(name)
|
26
|
+
translated_attribute_names.include?(name.to_sym)
|
27
|
+
end
|
28
|
+
|
29
|
+
def required_attributes
|
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
|
+
SingleTableGlobalize3::ActiveRecord::Translation
|
39
|
+
end
|
40
|
+
|
41
|
+
def translations_table_name(index = nil)
|
42
|
+
"#{translation_class.table_name}#{index}"
|
43
|
+
end
|
44
|
+
|
45
|
+
def translated_column_name(name, index = nil)
|
46
|
+
"#{translations_table_name(index)}.#{name}"
|
47
|
+
end
|
48
|
+
protected
|
49
|
+
def join_index
|
50
|
+
@join_index = 0 if @join_index.nil? || @join_index > 100
|
51
|
+
@join_index
|
52
|
+
end
|
53
|
+
|
54
|
+
def join_index=(value)
|
55
|
+
@join_index = value
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module SingleTableGlobalize3
|
2
|
+
module ActiveRecord
|
3
|
+
autoload :ActMacro, 'single_table_globalize3/active_record/act_macro'
|
4
|
+
autoload :Adapter, 'single_table_globalize3/active_record/adapter'
|
5
|
+
autoload :AttributeReadWrite, 'single_table_globalize3/active_record/attribute_read_write'
|
6
|
+
autoload :Attributes, 'single_table_globalize3/active_record/attributes'
|
7
|
+
autoload :ClassMethods, 'single_table_globalize3/active_record/class_methods'
|
8
|
+
autoload :WithTranslations, 'single_table_globalize3/active_record/with_translations'
|
9
|
+
autoload :Exceptions, 'single_table_globalize3/active_record/exceptions'
|
10
|
+
autoload :InstanceMethods, 'single_table_globalize3/active_record/instance_methods'
|
11
|
+
autoload :Migration, 'single_table_globalize3/active_record/migration'
|
12
|
+
autoload :Translation, 'single_table_globalize3/active_record/translation'
|
13
|
+
end
|
14
|
+
end
|
@@ -1 +1,73 @@
|
|
1
|
-
require '
|
1
|
+
require 'active_record'
|
2
|
+
require 'patches/active_record/xml_attribute_serializer'
|
3
|
+
require 'patches/active_record/uniqueness_validator'
|
4
|
+
|
5
|
+
module SingleTableGlobalize3
|
6
|
+
autoload :ActiveRecord, 'single_table_globalize3/active_record'
|
7
|
+
|
8
|
+
class << self
|
9
|
+
def locale
|
10
|
+
read_locale || I18n.locale
|
11
|
+
end
|
12
|
+
|
13
|
+
def locale=(locale)
|
14
|
+
set_locale(locale)
|
15
|
+
end
|
16
|
+
|
17
|
+
def with_locale(locale, &block)
|
18
|
+
previous_locale = read_locale
|
19
|
+
set_locale(locale)
|
20
|
+
result = yield(locale)
|
21
|
+
set_locale(previous_locale)
|
22
|
+
result
|
23
|
+
end
|
24
|
+
|
25
|
+
def with_locales(*locales, &block)
|
26
|
+
locales.flatten.map do |locale|
|
27
|
+
with_locale(locale, &block)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def fallbacks=(locales)
|
32
|
+
set_fallbacks(locales)
|
33
|
+
end
|
34
|
+
|
35
|
+
def i18n_fallbacks?
|
36
|
+
I18n.respond_to?(:fallbacks)
|
37
|
+
end
|
38
|
+
|
39
|
+
def fallbacks(for_locale = self.locale)
|
40
|
+
read_fallbacks[for_locale] || default_fallbacks(for_locale)
|
41
|
+
end
|
42
|
+
|
43
|
+
def default_fallbacks(for_locale = self.locale)
|
44
|
+
i18n_fallbacks? ? I18n.fallbacks[for_locale] : [for_locale.to_sym]
|
45
|
+
end
|
46
|
+
|
47
|
+
protected
|
48
|
+
|
49
|
+
def read_locale
|
50
|
+
Thread.current[:globalize_locale]
|
51
|
+
end
|
52
|
+
|
53
|
+
def set_locale(locale)
|
54
|
+
Thread.current[:globalize_locale] = locale.try(:to_sym)
|
55
|
+
end
|
56
|
+
|
57
|
+
def read_fallbacks
|
58
|
+
Thread.current[:fallbacks] || HashWithIndifferentAccess.new
|
59
|
+
end
|
60
|
+
|
61
|
+
def set_fallbacks(locales)
|
62
|
+
fallback_hash = HashWithIndifferentAccess.new
|
63
|
+
|
64
|
+
locales.each do |key, value|
|
65
|
+
fallback_hash[key] = value.presence || [key]
|
66
|
+
end if locales.present?
|
67
|
+
|
68
|
+
Thread.current[:fallbacks] = fallback_hash
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
ActiveRecord::Base.extend(SingleTableGlobalize3::ActiveRecord::ActMacro)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: single_table_globalize3
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sven Fuchs
|
@@ -14,7 +14,7 @@ authors:
|
|
14
14
|
autorequire:
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
|
-
date: 2013-03-
|
17
|
+
date: 2013-03-13 00:00:00.000000000 Z
|
18
18
|
dependencies:
|
19
19
|
- !ruby/object:Gem::Dependency
|
20
20
|
name: activerecord
|
@@ -143,28 +143,28 @@ dependencies:
|
|
143
143
|
- !ruby/object:Gem::Version
|
144
144
|
version: '0'
|
145
145
|
description: Rails I18n de-facto standard library for ActiveRecord 3 model/data translation
|
146
|
-
with single table.
|
146
|
+
with a single table.
|
147
147
|
email: trong.v.tran@gmail.com
|
148
148
|
executables: []
|
149
149
|
extensions: []
|
150
150
|
extra_rdoc_files: []
|
151
151
|
files:
|
152
|
-
- lib/generators/
|
153
|
-
- lib/generators/
|
154
|
-
- lib/globalize/active_record/act_macro.rb
|
155
|
-
- lib/globalize/active_record/adapter.rb
|
156
|
-
- lib/globalize/active_record/attributes.rb
|
157
|
-
- lib/globalize/active_record/class_methods.rb
|
158
|
-
- lib/globalize/active_record/exceptions.rb
|
159
|
-
- lib/globalize/active_record/instance_methods.rb
|
160
|
-
- lib/globalize/active_record/translation.rb
|
161
|
-
- lib/globalize/active_record.rb
|
162
|
-
- lib/globalize.rb
|
152
|
+
- lib/generators/single_table_globalize3/migration_generator.rb
|
153
|
+
- lib/generators/single_table_globalize3/templates/migration.rb
|
163
154
|
- lib/i18n/missing_translations_log_handler.rb
|
164
155
|
- lib/i18n/missing_translations_raise_handler.rb
|
165
|
-
- lib/patches/active_record/query_method.rb
|
166
156
|
- lib/patches/active_record/uniqueness_validator.rb
|
167
157
|
- lib/patches/active_record/xml_attribute_serializer.rb
|
158
|
+
- lib/single_table_globalize3/active_record/act_macro.rb
|
159
|
+
- lib/single_table_globalize3/active_record/adapter.rb
|
160
|
+
- lib/single_table_globalize3/active_record/attribute_read_write.rb
|
161
|
+
- lib/single_table_globalize3/active_record/attributes.rb
|
162
|
+
- lib/single_table_globalize3/active_record/class_methods.rb
|
163
|
+
- lib/single_table_globalize3/active_record/exceptions.rb
|
164
|
+
- lib/single_table_globalize3/active_record/instance_methods.rb
|
165
|
+
- lib/single_table_globalize3/active_record/translation.rb
|
166
|
+
- lib/single_table_globalize3/active_record/with_translations.rb
|
167
|
+
- lib/single_table_globalize3/active_record.rb
|
168
168
|
- lib/single_table_globalize3/version.rb
|
169
169
|
- lib/single_table_globalize3.rb
|
170
170
|
- Gemfile
|
@@ -194,5 +194,5 @@ rubygems_version: 2.0.0
|
|
194
194
|
signing_key:
|
195
195
|
specification_version: 4
|
196
196
|
summary: Rails I18n de-facto standard library for ActiveRecord 3 model/data translation
|
197
|
-
with single table
|
197
|
+
with a single table
|
198
198
|
test_files: []
|
@@ -1,14 +0,0 @@
|
|
1
|
-
require 'rails/generators/active_record'
|
2
|
-
|
3
|
-
module SingleTableGlobalize3
|
4
|
-
module Generators
|
5
|
-
class MigrationGenerator < ActiveRecord::Generators::Base
|
6
|
-
source_root File.expand_path("../templates", __FILE__)
|
7
|
-
argument :name, :type => :string, :default => "application"
|
8
|
-
|
9
|
-
def copy_devise_migration
|
10
|
-
migration_template "migration.rb", "db/migrate/create_globalize_translations"
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
@@ -1,12 +0,0 @@
|
|
1
|
-
module Globalize
|
2
|
-
module ActiveRecord
|
3
|
-
autoload :ActMacro, 'globalize/active_record/act_macro'
|
4
|
-
autoload :Adapter, 'globalize/active_record/adapter'
|
5
|
-
autoload :Attributes, 'globalize/active_record/attributes'
|
6
|
-
autoload :ClassMethods, 'globalize/active_record/class_methods'
|
7
|
-
autoload :Exceptions, 'globalize/active_record/exceptions'
|
8
|
-
autoload :InstanceMethods, 'globalize/active_record/instance_methods'
|
9
|
-
autoload :Migration, 'globalize/active_record/migration'
|
10
|
-
autoload :Translation, 'globalize/active_record/translation'
|
11
|
-
end
|
12
|
-
end
|
data/lib/globalize.rb
DELETED
@@ -1,74 +0,0 @@
|
|
1
|
-
require 'active_record'
|
2
|
-
require 'patches/active_record/xml_attribute_serializer'
|
3
|
-
require 'patches/active_record/query_method'
|
4
|
-
require 'patches/active_record/uniqueness_validator'
|
5
|
-
|
6
|
-
module Globalize
|
7
|
-
autoload :ActiveRecord, 'globalize/active_record'
|
8
|
-
|
9
|
-
class << self
|
10
|
-
def locale
|
11
|
-
read_locale || I18n.locale
|
12
|
-
end
|
13
|
-
|
14
|
-
def locale=(locale)
|
15
|
-
set_locale(locale)
|
16
|
-
end
|
17
|
-
|
18
|
-
def with_locale(locale, &block)
|
19
|
-
previous_locale = read_locale
|
20
|
-
set_locale(locale)
|
21
|
-
result = yield(locale)
|
22
|
-
set_locale(previous_locale)
|
23
|
-
result
|
24
|
-
end
|
25
|
-
|
26
|
-
def with_locales(*locales, &block)
|
27
|
-
locales.flatten.map do |locale|
|
28
|
-
with_locale(locale, &block)
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
def fallbacks=(locales)
|
33
|
-
set_fallbacks(locales)
|
34
|
-
end
|
35
|
-
|
36
|
-
def i18n_fallbacks?
|
37
|
-
I18n.respond_to?(:fallbacks)
|
38
|
-
end
|
39
|
-
|
40
|
-
def fallbacks(for_locale = self.locale)
|
41
|
-
read_fallbacks[for_locale] || default_fallbacks(for_locale)
|
42
|
-
end
|
43
|
-
|
44
|
-
def default_fallbacks(for_locale = self.locale)
|
45
|
-
i18n_fallbacks? ? I18n.fallbacks[for_locale] : [for_locale.to_sym]
|
46
|
-
end
|
47
|
-
|
48
|
-
protected
|
49
|
-
|
50
|
-
def read_locale
|
51
|
-
Thread.current[:globalize_locale]
|
52
|
-
end
|
53
|
-
|
54
|
-
def set_locale(locale)
|
55
|
-
Thread.current[:globalize_locale] = locale.try(:to_sym)
|
56
|
-
end
|
57
|
-
|
58
|
-
def read_fallbacks
|
59
|
-
Thread.current[:fallbacks] || HashWithIndifferentAccess.new
|
60
|
-
end
|
61
|
-
|
62
|
-
def set_fallbacks(locales)
|
63
|
-
fallback_hash = HashWithIndifferentAccess.new
|
64
|
-
|
65
|
-
locales.each do |key, value|
|
66
|
-
fallback_hash[key] = value.presence || [key]
|
67
|
-
end if locales.present?
|
68
|
-
|
69
|
-
Thread.current[:fallbacks] = fallback_hash
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
ActiveRecord::Base.extend(Globalize::ActiveRecord::ActMacro)
|
@@ -1,35 +0,0 @@
|
|
1
|
-
require 'active_record/attribute_methods/query'
|
2
|
-
|
3
|
-
module ActiveRecord
|
4
|
-
module AttributeMethods
|
5
|
-
module Query
|
6
|
-
def query_attribute(attr_name)
|
7
|
-
unless value = read_attribute(attr_name)
|
8
|
-
false
|
9
|
-
else
|
10
|
-
column = self.class.columns_hash[attr_name]
|
11
|
-
if column.nil?
|
12
|
-
|
13
|
-
# TODO submit a rails patch
|
14
|
-
|
15
|
-
# not sure what active_record tests say but i guess this should mean:
|
16
|
-
# call to_i and check zero? if the value is a Numeric or starts with
|
17
|
-
# a digit, so it can meaningfully be typecasted by to_i
|
18
|
-
|
19
|
-
# if Numeric === value || value !~ /[^0-9]/
|
20
|
-
if Numeric === value || value.to_s =~ /^[0-9]/
|
21
|
-
!value.to_i.zero?
|
22
|
-
else
|
23
|
-
return false if ActiveRecord::ConnectionAdapters::Column::FALSE_VALUES.include?(value)
|
24
|
-
!value.blank?
|
25
|
-
end
|
26
|
-
elsif column.number?
|
27
|
-
!value.zero?
|
28
|
-
else
|
29
|
-
!value.blank?
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|