translatable_ar 1.0.2 → 1.0.3

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.
@@ -26,40 +26,50 @@ class TranslatableAR
26
26
  @translatable_ar_attributes << attribute
27
27
  @translatable_ar_attributes.uniq!
28
28
  end
29
-
30
- def define_translatable_ar_methods(attribute)
31
- serialize attribute, TranslatableAR.coder
29
+
30
+ def define_translatable_ar_methods(attribute)
31
+ serialize "#{attribute}_i18n", TranslatableAR.coder_or_default_object
32
32
  class_eval do
33
- define_translatable_ar_collection(attribute)
34
33
  define_translatable_ar_writer(attribute)
35
34
  define_translatable_ar_reader(attribute)
35
+ define_translatable_ar_changed?(attribute)
36
36
  end
37
37
  end
38
38
 
39
- def define_translatable_ar_collection(attribute)
40
- define_method("#{attribute}_translations") do
41
- self["#{attribute}"] ||= {}
42
- end
43
- end
44
-
45
39
  def define_translatable_ar_reader(attribute)
46
40
  define_method("#{attribute}") do
47
- send("#{attribute}_translations")[I18n.locale.to_s]
41
+ if respond_to?("#{attribute}_i18n")
42
+ send("#{attribute}_i18n")[I18n.locale.to_s]
43
+ else
44
+ super()
45
+ end
48
46
  end
49
47
  end
50
48
 
51
49
  def define_translatable_ar_writer(attribute)
52
50
  define_method("#{attribute}=") do |value|
53
- if value.is_a?(Hash)
54
- translations = value
51
+ if respond_to?("#{attribute}_i18n")
52
+ if value.is_a?(Hash)
53
+ send("#{attribute}_i18n=", value)
54
+ else
55
+ send("#{attribute}_i18n")[I18n.locale.to_s] = value
56
+ end
55
57
  else
56
- translations = send("#{attribute}_translations")
57
- translations[I18n.locale.to_s] = value
58
+ super(value)
58
59
  end
59
- super(translations)
60
60
  end
61
61
  end
62
-
62
+
63
+ def define_translatable_ar_changed?(attribute)
64
+ define_method("#{attribute}_changed?") do |value|
65
+ if respond_to?("#{attribute}_i18n")
66
+ send("#{attribute}_i18n_changed?")
67
+ else
68
+ super(value)
69
+ end
70
+ end
71
+ end
72
+
63
73
  end
64
74
  end
65
75
  end
data/lib/railtie.rb CHANGED
@@ -26,12 +26,43 @@ class TranslatableAr < Rails::Railtie
26
26
  end
27
27
 
28
28
  def create_migration_file
29
- Rails.application.eager_load! # load models
30
- migration_template template_path, 'db/migrate/setup_translatable_ar.rb'
29
+ Rails.application.eager_load! # trigger translates method call in models
30
+ time = Time.now.utc.strftime("%Y%m%d%H%M%S")
31
+
32
+ migration_template 'setup.rb', "db/migrate/setup_translatable_ar_#{time}.rb"
33
+ end
34
+
35
+ def models
36
+ models = []
37
+ TranslatableAR.models.each do |model|
38
+ model.translatable_ar_attributes.each do |attribute|
39
+ if model.columns_hash["#{attribute}_i18n"].nil?
40
+ models << model
41
+ end
42
+ end
43
+ end
44
+ models.uniq!
45
+ end
46
+
47
+ def attributes
48
+ attributes = []
49
+ attribute_struct = Struct.new(:name, :model)
50
+ TranslatableAR.models.each do |model|
51
+ model.translatable_ar_attributes.each do |attribute|
52
+ if model.columns_hash["#{attribute}_i18n"].nil?
53
+ attributes << attribute_struct.new(attribute, model)
54
+ end
55
+ end
56
+ end
57
+ attributes
58
+ end
59
+
60
+ def column_type
61
+ uses_hstore? ? :hstore : :text
31
62
  end
32
63
 
33
- def template_path
34
- TranslatableAR.uses_hstore? ? 'hstore.rb' : 'text.rb'
64
+ def uses_hstore?
65
+ TranslatableAR.uses_hstore?
35
66
  end
36
67
 
37
68
  end
@@ -0,0 +1,43 @@
1
+ class <%= migration_class_name %> < ActiveRecord::Migration
2
+
3
+ def up
4
+
5
+ <% if uses_hstore? -%>
6
+ execute "CREATE EXTENSION IF NOT EXISTS hstore"
7
+ <% end -%>
8
+
9
+ <% attributes.each do |attribute| -%>
10
+ add_column :<%= attribute.model.table_name %>, :<%= attribute.name %>_i18n, :<%= column_type %>
11
+ <% end -%>
12
+
13
+ <% if uses_hstore?
14
+ attributes.each do |attribute| -%>
15
+ add_hstore_index :<%= attribute.model.table_name %>, :<%= attribute.name %>_i18n
16
+ <% end
17
+ end-%>
18
+
19
+ <% models.each do |model| -%>
20
+ puts "Preparing existing <%= model.to_s %> objects ..."
21
+ <%= model.to_s %>.reset_column_information
22
+ <%= model.to_s %>.all.each do |object|
23
+ <% attributes.select{|a| a.model == model}.each do |attribute| -%>
24
+ object.<%=attribute.name%> = object[:<%=attribute.name%>]
25
+ <% end -%>
26
+ object.save
27
+ end
28
+ <% end -%>
29
+ end
30
+
31
+ def down
32
+ <% attributes.each do |attribute| -%>
33
+ remove_column :<%= attribute.model.table_name %>, :<%= attribute.name %>_i18n
34
+ <% end -%>
35
+
36
+ <% if uses_hstore?
37
+ attributes.each do |attribute| -%>
38
+ remove_hstore_index :<%= attribute.model.table_name %>, :<%= attribute.name %>_i18n
39
+ <% end
40
+ end-%>
41
+ end
42
+
43
+ end
@@ -1,15 +1,18 @@
1
1
  class TranslatableAR
2
2
 
3
3
  class << self
4
- attr_accessor :models, :coder
5
- def coder
6
- @coder ||= Object # Use ActiveRecord's default serializer class
4
+ attr_accessor :models, :coder_or_default_object
5
+ def coder_or_default_object
6
+ @coder_or_default_object ||= Hash
7
7
  end
8
8
  def models
9
9
  @models ||= []
10
10
  end
11
11
  def uses_hstore?
12
- @coder == ActiveRecord::Coders::Hstore rescue false
12
+ @coder_or_default_object == ActiveRecord::Coders::Hstore rescue false
13
+ end
14
+ def use_hstore!
15
+ @coder_or_default_object = ActiveRecord::Coders::Hstore
13
16
  end
14
17
  end
15
18
 
@@ -6,37 +6,38 @@ class ProductTest < ActiveSupport::TestCase
6
6
 
7
7
  test "build with nested locale values" do
8
8
  p = Product.new(:name => {'en' => 'Chair', 'da' => 'Stol'}, image_url: '/image1.png')
9
- assert_equal 'Chair', p.name_translations['en']
10
- assert_equal 'Stol', p.name_translations['da']
9
+ assert_equal 'Chair', p.name_i18n['en']
10
+ assert_equal 'Stol', p.name_i18n['da']
11
11
  assert_equal '/image1.png', p.image_url
12
12
  end
13
13
 
14
14
  test "build with default locale" do
15
15
  p = Product.new(name: 'Table', image_url: '/image1.png')
16
16
  assert_equal('Table', p.name)
17
- assert_equal({'en' => 'Table'}, p.name_translations)
17
+ assert_equal({'en' => 'Table'}, p.name_i18n)
18
18
  assert_equal '/image1.png', p.image_url
19
19
  end
20
20
 
21
21
  test "create with nested locale values" do
22
- p = Product.create(:name => {'en' => 'Chair', 'da' => 'Stol'}, image_url: '/image1.png')
23
- assert_equal 'Chair', p.name_translations['en']
24
- assert_equal 'Stol', p.name_translations['da']
22
+ p = Product.create(:name => {'en' => 'Chair', 'da' => 'Stol'}, image_url: '/image1.png', permalink: 'asd')
23
+ assert_equal 'Chair', p.name_i18n['en']
24
+ assert_equal 'Stol', p.name_i18n['da']
25
25
  assert_equal '/image1.png', p.image_url
26
+ assert_equal 1, Product.count
26
27
  end
27
28
 
28
29
  test "create with default locale" do
29
30
  p = Product.create(name: 'Table', image_url: '/image1.png')
30
31
  assert_equal 'Table', p.name
31
- assert_equal({'en' => 'Table'}, p.name_translations)
32
+ assert_equal({'en' => 'Table'}, p.name_i18n)
32
33
  assert_equal '/image1.png', p.image_url
33
34
  end
34
35
 
35
36
  test "update with nested locale values" do
36
37
  p = Product.new
37
38
  p.update_attributes(:name => {'en' => 'Chair', 'da' => 'Stol'}, image_url: '/image1.png')
38
- assert_equal 'Chair', p.name_translations['en']
39
- assert_equal 'Stol', p.name_translations['da']
39
+ assert_equal 'Chair', p.name_i18n['en']
40
+ assert_equal 'Stol', p.name_i18n['da']
40
41
  assert_equal '/image1.png', p.image_url
41
42
  end
42
43
 
@@ -44,7 +45,7 @@ class ProductTest < ActiveSupport::TestCase
44
45
  p = Product.new
45
46
  p.update_attributes(name: 'Table', image_url: '/image1.png')
46
47
  assert_equal 'Table', p.name
47
- assert_equal({'en' => 'Table'}, p.name_translations)
48
+ assert_equal({'en' => 'Table'}, p.name_i18n)
48
49
  assert_equal '/image1.png', p.image_url
49
50
  end
50
51
 
@@ -62,14 +63,14 @@ class ProductTest < ActiveSupport::TestCase
62
63
  p.name = 'Bord'
63
64
 
64
65
  assert_equal 'Bord', p.name
65
- assert_equal({'en' => 'Table', 'da' => 'Bord'}, p.name_translations)
66
+ assert_equal({'en' => 'Table', 'da' => 'Bord'}, p.name_i18n)
66
67
 
67
68
  p.save
68
69
 
69
70
  I18n.locale = :en
70
71
 
71
72
  assert_equal 'Table', p.name
72
- assert_equal({'en' => 'Table', 'da' => 'Bord'}, p.name_translations)
73
+ assert_equal({'en' => 'Table', 'da' => 'Bord'}, p.name_i18n)
73
74
 
74
75
  end
75
76
 
@@ -78,8 +79,8 @@ class ProductTest < ActiveSupport::TestCase
78
79
  test "build from collection with nested locale values" do
79
80
  c = Category.create(name: 'Furniture')
80
81
  p = c.products.build(:name => {'en' => 'Chair', 'da' => 'Stol'}, image_url: '/image1.png')
81
- assert_equal 'Chair', p.name_translations['en']
82
- assert_equal 'Stol', p.name_translations['da']
82
+ assert_equal 'Chair', p.name_i18n['en']
83
+ assert_equal 'Stol', p.name_i18n['da']
83
84
  assert_equal '/image1.png', p.image_url
84
85
  end
85
86
 
@@ -87,15 +88,15 @@ class ProductTest < ActiveSupport::TestCase
87
88
  c = Category.create(name: 'Furniture')
88
89
  p = c.products.build(name: 'Table', image_url: '/image1.png')
89
90
  assert_equal('Table', p.name)
90
- assert_equal({'en' => 'Table'}, p.name_translations)
91
+ assert_equal({'en' => 'Table'}, p.name_i18n)
91
92
  assert_equal '/image1.png', p.image_url
92
93
  end
93
94
 
94
95
  test "create from collection with nested locale values" do
95
96
  c = Category.create(name: 'Furniture')
96
97
  p = c.products.create(:name => {'en' => 'Chair', 'da' => 'Stol'}, image_url: '/image1.png')
97
- assert_equal 'Chair', p.name_translations['en']
98
- assert_equal 'Stol', p.name_translations['da']
98
+ assert_equal 'Chair', p.name_i18n['en']
99
+ assert_equal 'Stol', p.name_i18n['da']
99
100
  assert_equal '/image1.png', p.image_url
100
101
  end
101
102
 
@@ -103,7 +104,7 @@ class ProductTest < ActiveSupport::TestCase
103
104
  c = Category.create(name: 'Furniture')
104
105
  p = c.products.create(name: 'Table', image_url: '/image1.png')
105
106
  assert_equal 'Table', p.name
106
- assert_equal({'en' => 'Table'}, p.name_translations)
107
+ assert_equal({'en' => 'Table'}, p.name_i18n)
107
108
  assert_equal '/image1.png', p.image_url
108
109
  end
109
110
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: translatable_ar
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.0.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-02-08 00:00:00.000000000 Z
12
+ date: 2013-04-11 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activerecord
@@ -27,8 +27,7 @@ dependencies:
27
27
  - - ! '>='
28
28
  - !ruby/object:Gem::Version
29
29
  version: '0'
30
- description: No joins. No locale columns. Attribute translations are saved in-column
31
- as a serialized hash.
30
+ description: Translations are saved in-column as a serialized hash or using HStore.
32
31
  email: kasperbn@gmail.com
33
32
  executables: []
34
33
  extensions: []
@@ -36,8 +35,7 @@ extra_rdoc_files: []
36
35
  files:
37
36
  - lib/active_record_methods.rb
38
37
  - lib/railtie.rb
39
- - lib/templates/hstore.rb
40
- - lib/templates/text.rb
38
+ - lib/templates/setup.rb
41
39
  - lib/translatable_ar.rb
42
40
  - lib/translatable_ar_class.rb
43
41
  - test/rails_3.2.11/test/unit/product_test.rb
@@ -62,9 +60,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
62
60
  version: '0'
63
61
  requirements: []
64
62
  rubyforge_project:
65
- rubygems_version: 1.8.24
63
+ rubygems_version: 1.8.25
66
64
  signing_key:
67
65
  specification_version: 3
68
- summary: Less painful i18n for your active record models
66
+ summary: i18n for your active record models with HStore / serialized attribute
69
67
  test_files:
70
68
  - test/rails_3.2.11/test/unit/product_test.rb
@@ -1,72 +0,0 @@
1
- class SetupTranslatableAr < ActiveRecord::Migration
2
-
3
- def up
4
- <% TranslatableAR.models.each do |model| -%>
5
- <% model.translatable_ar_attributes.each do |attribute| -%>
6
- add_column :<%= model.table_name %>, :<%= attribute %>_i18n_temp, :hstore
7
- <% end -%>
8
- <% end -%>
9
- <% TranslatableAR.models.each do |model| -%>
10
-
11
- <%= model.to_s %>.translates <%= model.translatable_ar_attributes.map {|a| ":#{a}_i18n_temp" }.join(', ') %>
12
- <%= model.to_s %>.all.each do |object|
13
- <% model.translatable_ar_attributes.each do |attribute| -%>
14
- if object[:<%=attribute%>].is_a? Hash
15
- object.<%=attribute%>_i18n_temp = object[:<%=attribute%>]
16
- else
17
- object.<%=attribute%>_i18n_temp = {'<%= I18n.locale%>' => object[:<%=attribute%>]}
18
- end
19
- <% end -%>
20
- object.save if object.changed?
21
- end
22
- <% end -%>
23
- <% TranslatableAR.models.each do |model| -%>
24
- <% model.translatable_ar_attributes.each do |attribute| -%>
25
- remove_column :<%= model.table_name %>, :<%= attribute %>
26
- rename_column :<%= model.table_name %>, :<%= attribute%>_i18n_temp, :<%= attribute %>
27
- <% end -%>
28
- <% end -%>
29
-
30
- <% TranslatableAR.models.each do |model| -%>
31
- <% model.translatable_ar_attributes.each do |attribute| -%>
32
- # execute "CREATE INDEX <%= model.table_name%>_gin_<%= attribute %> ON <%= model.table_name %> USING GIN(<%= attribute %>);"
33
- <% end -%>
34
- <% end -%>
35
- end
36
-
37
- def down
38
- <% TranslatableAR.models.each do |model| -%>
39
- <% model.translatable_ar_attributes.each do |attribute| -%>
40
- add_column :<%= model.table_name %>, :<%= attribute %>_i18n_temp, :<%= model.columns_hash[attribute.to_s].type %>
41
- <% end -%>
42
- <% end -%>
43
- <% TranslatableAR.models.each do |model| -%>
44
-
45
- <%= model.to_s %>.translates <%= model.translatable_ar_attributes.map {|a| ":#{a}_i18n_temp" }.join(', ') %>
46
- <%= model.to_s %>.all.each do |object|
47
- <% model.translatable_ar_attributes.each do |attribute| -%>
48
- if object[:<%=attribute%>].is_a? Hash
49
- object.<%=attribute%>_i18n_temp = object[:<%=attribute%>]['<%= I18n.locale%>']
50
- else
51
- object.<%=attribute%>_i18n_temp = object[:<%=attribute%>]
52
- end
53
- <% end -%>
54
- object.save if object.changed?
55
- end
56
- <% end -%>
57
-
58
- <% TranslatableAR.models.each do |model| -%>
59
- <% model.translatable_ar_attributes.each do |attribute| -%>
60
- execute "DROP INDEX <%= model.table_name%>_gin_<%= attribute %>;"
61
- <% end -%>
62
- <% end -%>
63
-
64
- <% TranslatableAR.models.each do |model| -%>
65
- <% model.translatable_ar_attributes.each do |attribute| -%>
66
- remove_column :<%= model.table_name %>, :<%= attribute %>
67
- rename_column :<%= model.table_name %>, :<%= attribute%>_i18n_temp, :<%= attribute %>
68
- <% end -%>
69
- <% end -%>
70
- end
71
-
72
- end
@@ -1,53 +0,0 @@
1
- class SetupTranslatableAr < ActiveRecord::Migration
2
-
3
- def up
4
- <% TranslatableAR.models.each do |model| -%>
5
- <% model.translatable_ar_attributes.each do |attribute| -%>
6
- add_column :<%= model.table_name %>, :<%= attribute %>_i18n_temp, :text
7
- <% end -%>
8
- <% end -%>
9
- <% TranslatableAR.models.each do |model| -%>
10
-
11
- <%= model.to_s %>.translates <%= model.translatable_ar_attributes.map {|a| ":#{a}_i18n_temp" }.join(', ') %>
12
- <%= model.to_s %>.all.each do |object|
13
- <% model.translatable_ar_attributes.each do |attribute| -%>
14
- if object[:<%=attribute%>].is_a? Hash
15
- object.<%=attribute%>_i18n_temp = object[:<%=attribute%>]
16
- else
17
- object.<%=attribute%>_i18n_temp = {'<%= I18n.default_locale%>' => object[:<%=attribute%>]}
18
- end
19
- <% end -%>
20
- object.save if object.changed?
21
- end
22
- <% end -%>
23
- <% TranslatableAR.models.each do |model| -%>
24
- <% model.translatable_ar_attributes.each do |attribute| -%>
25
- remove_column :<%= model.table_name %>, :<%= attribute %>
26
- rename_column :<%= model.table_name %>, :<%= attribute%>_i18n_temp, :<%= attribute %>
27
- <% end -%>
28
- <% end -%>
29
- end
30
-
31
- def down
32
- <% TranslatableAR.models.each do |model| -%>
33
- <% model.translatable_ar_attributes.each do |attribute| -%>
34
- add_column :<%= model.table_name %>, :<%= attribute %>_i18n_temp, :<%= model.columns_hash[attribute.to_s].type %>
35
- <% end -%>
36
- <% end -%>
37
- <% TranslatableAR.models.each do |model| -%>
38
-
39
- <%= model.to_s %>.all.each do |object|
40
- <% model.translatable_ar_attributes.each do |attribute| -%>
41
- object.<%=attribute%>_i18n_temp = object[:<%=attribute%>]['<%= I18n.default_locale%>']
42
- <% end -%>
43
- object.save if object.changed?
44
- <% end -%>
45
- <% TranslatableAR.models.each do |model| -%>
46
- <% model.translatable_ar_attributes.each do |attribute| -%>
47
- remove_column :<%= model.table_name %>, :<%= attribute %>
48
- rename_column :<%= model.table_name %>, :<%= attribute%>_i18n_temp, :<%= attribute %>
49
- <% end -%>
50
- <% end -%>
51
- end
52
-
53
- end