translatable 0.2.4 → 0.3.0
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.
- data/.travis.yml +2 -2
- data/Gemfile +11 -7
- data/Gemfile.lock +73 -5
- data/Rakefile +7 -3
- data/VERSION +1 -1
- data/lib/generators/translatable/model_generator.rb +45 -0
- data/lib/generators/translatable/translation_generator.rb +45 -0
- data/lib/translatable/active_record.rb +254 -0
- data/lib/translatable/engine.rb +6 -0
- data/lib/translatable/generator_helper.rb +20 -0
- data/lib/translatable.rb +13 -258
- data/test/cases/translatable_test.rb +276 -0
- data/test/generators/model_generator_test.rb +97 -0
- data/test/generators/translation_generator_test.rb +71 -0
- data/test/support/active_record.rb +4 -1
- data/test/{messages.rb → support/models/messages.rb} +0 -0
- data/test/{news.rb → support/models/news.rb} +0 -0
- data/test/{posts.rb → support/models/posts.rb} +0 -0
- data/test/{helper.rb → test_helper.rb} +18 -6
- data/translatable.gemspec +20 -16
- metadata +38 -39
- data/test/test_translatable.rb +0 -273
data/lib/translatable.rb
CHANGED
@@ -1,261 +1,16 @@
|
|
1
|
-
require 'active_record'
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
# Examples:
|
10
|
-
#
|
11
|
-
# class Author < ActiveRecord::Base
|
12
|
-
# validates :name, :presence => true
|
13
|
-
# end
|
14
|
-
#
|
15
|
-
# class TranslatableNews < ActiveRecord::Base #
|
16
|
-
# attr_accessible :title, :content
|
17
|
-
# end
|
18
|
-
#
|
19
|
-
# class News < ActiveRecord::Base
|
20
|
-
#
|
21
|
-
# belongs_to :author
|
22
|
-
#
|
23
|
-
# translatable do
|
24
|
-
# translatable :title, :presence => true, :uniqueness => true
|
25
|
-
# translatable :content, :presence => true
|
26
|
-
# translatable_model "TranslatedNews"
|
27
|
-
# translatable_origin :origin_id
|
28
|
-
# end
|
29
|
-
#
|
30
|
-
# attr_accessible :author_id, :author
|
31
|
-
# end
|
32
|
-
#
|
33
|
-
# An example of application:
|
34
|
-
#
|
35
|
-
# news = News.create :translations_attributes => [{title: "Resent News", content: "That is where the text goes", locale: "en"}]
|
36
|
-
# news.translations.create title: "Заголовок", content: "Содержание",locale: "ru"
|
37
|
-
#
|
38
|
-
# news.content
|
39
|
-
# # => "That is where the text goes"
|
40
|
-
#
|
41
|
-
# ::I18n.locale = "ru"
|
42
|
-
# news.content
|
43
|
-
# # => "Сюди идет текст"
|
44
|
-
#
|
45
|
-
# ::I18n.locale = "de"
|
46
|
-
# news.content
|
47
|
-
# # => nil
|
48
|
-
#
|
49
|
-
# ::I18n.locale = ::I18n.default_locale
|
50
|
-
# news.content
|
51
|
-
# # => "That is where the text goes"
|
52
|
-
#
|
53
|
-
module Translatable
|
54
|
-
|
55
|
-
def translatable
|
56
|
-
extend ActiveRecord::Translatable::ClassMethods
|
57
|
-
include ActiveRecord::Translatable::InstanceMethods
|
58
|
-
|
59
|
-
translatable_define_hash
|
60
|
-
yield
|
61
|
-
translatable_register
|
62
|
-
end
|
63
|
-
|
64
|
-
module ClassMethods
|
65
|
-
|
66
|
-
protected
|
67
|
-
|
68
|
-
###
|
69
|
-
# Fields that are translatable.
|
70
|
-
# Those fields should be defined in the original model including all the related params.
|
71
|
-
# Examples:
|
72
|
-
#
|
73
|
-
# translatable_property :title, String, required: true, unique: true
|
74
|
-
# translatable_property :content, Text
|
75
|
-
#
|
76
|
-
# NB! Will raise an error if there was no fields specified
|
77
|
-
#
|
78
|
-
def translatable *args
|
79
|
-
(@translatable[:properties] ||= []) << args
|
80
|
-
end
|
81
|
-
|
82
|
-
###
|
83
|
-
# Defines model that will be treated as translation handler.
|
84
|
-
# Model can be defined as String, Symbol or Constant.
|
85
|
-
# Examples:
|
86
|
-
#
|
87
|
-
# translated_model TranslatedNews
|
88
|
-
# translated_model "TranslatedNews"
|
89
|
-
# translated_model :TranslatedNews
|
90
|
-
#
|
91
|
-
# Default: Translatable<ModelName>
|
92
|
-
#
|
93
|
-
def translatable_model model_name
|
94
|
-
@translatable[:model] = translatable_model_prepared model_name
|
95
|
-
end
|
96
|
-
|
97
|
-
###
|
98
|
-
# Define the key that the translation will be used for belongs_to association,
|
99
|
-
# to communicate with original model
|
100
|
-
# Example:
|
101
|
-
#
|
102
|
-
# translatable_origin :news
|
103
|
-
#
|
104
|
-
# Default: :origin
|
105
|
-
#
|
106
|
-
def translatable_origin origin_key
|
107
|
-
@translatable[:origin] = translatable_origin_prepared origin_key
|
108
|
-
end
|
109
|
-
|
110
|
-
###
|
111
|
-
# Will not register the attributes as accessible.
|
112
|
-
# IMPORTANT: Translatable block will be evaluated on the model after it
|
113
|
-
# was loaded, so it will modify certain thing on final version. Hence this thing is needed.
|
114
|
-
# Examples:
|
115
|
-
#
|
116
|
-
# translatable_attr_protected
|
117
|
-
#
|
118
|
-
# Default: false
|
119
|
-
#
|
120
|
-
def translatable_attr_protected
|
121
|
-
@translatable[:attr_accessible] = false
|
122
|
-
end
|
123
|
-
|
124
|
-
###
|
125
|
-
# Will not register the attributes as accessible.
|
126
|
-
# IMPORTANT: Translatable block will be evaluated on the model after it
|
127
|
-
# was loaded, so it will modify certain thing on final version. Hence this thing is needed.
|
128
|
-
# Examples:
|
129
|
-
#
|
130
|
-
# translatable_attr_protected
|
131
|
-
#
|
132
|
-
# Default: false
|
133
|
-
#
|
134
|
-
def translatable_attr_accessible
|
135
|
-
@translatable[:attr_accessible] = true
|
136
|
-
end
|
137
|
-
|
138
|
-
###
|
139
|
-
# Define the key that the translation will be used for belongs_to association,
|
140
|
-
# to communicate with original model
|
141
|
-
# Example:
|
142
|
-
#
|
143
|
-
# translatable_origin :language
|
144
|
-
#
|
145
|
-
# Default: :locale
|
146
|
-
#
|
147
|
-
def translatable_locale locale_attr
|
148
|
-
@translatable[:locale] = translatable_locale_prepared locale_attr
|
149
|
-
end
|
150
|
-
|
151
|
-
###
|
152
|
-
# Returns Model as a constant that deals with translations
|
153
|
-
def translatable_model_prepared model_name = nil
|
154
|
-
model_constant = model_name
|
155
|
-
model_constant ||= "Translatable#{self.name}"
|
156
|
-
model_constant.to_s.constantize
|
157
|
-
end
|
158
|
-
|
159
|
-
|
160
|
-
def translatable_origin_prepared origin_key = nil
|
161
|
-
origin_key || "origin"
|
162
|
-
end
|
163
|
-
|
164
|
-
def translatable_locale_prepared locale = nil
|
165
|
-
locale || "locale"
|
166
|
-
end
|
167
|
-
|
168
|
-
###
|
169
|
-
# Define hash that contains all the translations
|
170
|
-
def translatable_define_hash
|
171
|
-
@translatable = {}
|
172
|
-
end
|
173
|
-
|
174
|
-
###
|
175
|
-
# Handles all the registring routine, defining methods,
|
176
|
-
# properties, and everything else
|
177
|
-
def translatable_register
|
178
|
-
raise ArgumentError.new("At least one property should be defined") if [nil, []].include?(@translatable[:properties])
|
179
|
-
[:model,:origin,:locale].each { |hash_key| @translatable[hash_key] ||= send "translatable_#{hash_key}_prepared" }
|
180
|
-
|
181
|
-
translatable_register_properties_for_origin
|
182
|
-
translatable_register_properties_for_translatable
|
183
|
-
end
|
184
|
-
|
185
|
-
###
|
186
|
-
# Handle the routine to define all th required stuff on the original maodel
|
187
|
-
def translatable_register_properties_for_origin
|
188
|
-
has_many :translations, :class_name => @translatable[:model].name, :foreign_key => :"#{@translatable[:origin]}_id"
|
189
|
-
accepts_nested_attributes_for :translations
|
190
|
-
attr_accessible :translations_attributes
|
191
|
-
|
192
|
-
@translatable[:properties].each do |p|
|
193
|
-
accessible_as = (p.last.delete(:as) || p.first rescue p.first)
|
194
|
-
self.module_eval <<-RUBY, __FILE__, __LINE__ + 1
|
195
|
-
def #{accessible_as}
|
196
|
-
current_translation.try(:#{p.first})
|
197
|
-
end
|
198
|
-
RUBY
|
199
|
-
end
|
200
|
-
|
201
|
-
self.module_eval <<-RUBY, __FILE__, __LINE__ + 1
|
202
|
-
def translatable_set_current
|
203
|
-
@current_translation = if translations.loaded?
|
204
|
-
translations.select { |t| t.send(:"#{@translatable[:locale]}") == @translatable_locale }
|
205
|
-
else
|
206
|
-
translations.where(:"#{@translatable[:locale]}" => @translatable_locale)
|
207
|
-
end.first
|
208
|
-
end
|
209
|
-
protected :translatable_set_current
|
210
|
-
RUBY
|
211
|
-
end
|
212
|
-
|
213
|
-
def translatable_register_properties_for_translatable
|
214
|
-
@translatable[:model].module_eval <<-RUBY, __FILE__, __LINE__ + 1
|
215
|
-
validates :#{@translatable[:locale]}, :presence => true
|
216
|
-
validates :#{@translatable[:locale]}, :format => { :with => /[a-z]{2}/}, :if => Proc.new {|record| !record.#{@translatable[:locale]}.blank? }
|
217
|
-
validates :#{@translatable[:locale]}, :uniqueness => { :scope => :#{@translatable[:origin]}_id }
|
218
|
-
|
219
|
-
belongs_to :#{@translatable[:origin]}, :class_name => "#{self.name}"
|
220
|
-
RUBY
|
221
|
-
|
222
|
-
unless @translatable[:attr_accessible].nil?
|
223
|
-
@translatable[:model].module_eval <<-RUBY, __FILE__, __LINE__ + 1
|
224
|
-
attr_#{!!@translatable[:attr_accessible] ? "accessible" : "protected" } :#{@translatable[:locale]}, :#{@translatable[:origin]}_id
|
225
|
-
RUBY
|
226
|
-
end
|
227
|
-
|
228
|
-
@translatable[:properties].each do |p|
|
229
|
-
if p.size > 1
|
230
|
-
@translatable[:model].module_eval <<-RUBY, __FILE__, __LINE__ + 1
|
231
|
-
validates :#{p.first}, #{p.last.inspect}
|
232
|
-
RUBY
|
233
|
-
end
|
234
|
-
end
|
235
|
-
end
|
236
|
-
end
|
237
|
-
|
238
|
-
module InstanceMethods
|
239
|
-
|
240
|
-
def current_translation
|
241
|
-
if translatable_locale_changed?
|
242
|
-
@translatable_locale = ::I18n.locale.to_s
|
243
|
-
translatable_set_current
|
244
|
-
end
|
245
|
-
@current_translation
|
246
|
-
end
|
247
|
-
|
248
|
-
def other_translations
|
249
|
-
translations - [current_translation]
|
250
|
-
end
|
251
|
-
|
252
|
-
protected
|
253
|
-
|
254
|
-
def translatable_locale_changed?
|
255
|
-
@translatable_locale.to_s != ::I18n.locale.to_s
|
256
|
-
end
|
1
|
+
require 'translatable/active_record'
|
2
|
+
|
3
|
+
if defined?(Rails)
|
4
|
+
require 'translatable/engine'
|
5
|
+
|
6
|
+
ActiveSupport.on_load(:active_record) do
|
7
|
+
ActiveSupport.on_load(:i18n) do
|
8
|
+
ActiveRecord::Base.extend Translatable::ActiveRecord
|
257
9
|
end
|
258
10
|
end
|
11
|
+
else
|
12
|
+
require 'active_record'
|
13
|
+
require 'i18n'
|
14
|
+
|
15
|
+
ActiveRecord::Base.extend Translatable::ActiveRecord
|
259
16
|
end
|
260
|
-
|
261
|
-
ActiveRecord::Base.extend ActiveRecord::Translatable
|
@@ -0,0 +1,276 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'test_helper'
|
3
|
+
require 'support/models/news'
|
4
|
+
require 'support/models/posts'
|
5
|
+
require 'support/models/messages'
|
6
|
+
|
7
|
+
class TranslatableTest < Test::Unit::TestCase
|
8
|
+
context "Translatable hash" do
|
9
|
+
should "Define default" do
|
10
|
+
th = News.instance_variable_get :@translatable
|
11
|
+
|
12
|
+
assert_kind_of Hash, th
|
13
|
+
assert th.has_key?(:properties)
|
14
|
+
end
|
15
|
+
|
16
|
+
should "Has dafault model" do
|
17
|
+
assert_equal ::TranslatableNews, News.send(:translatable_model_prepared, 'TranslatableNews')
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
context "Translatable model preparation" do
|
22
|
+
should "Accept constant" do
|
23
|
+
assert_equal ::TranslatableNews, News.send(:translatable_model_prepared, ::TranslatableNews)
|
24
|
+
end
|
25
|
+
|
26
|
+
should "Accept string" do
|
27
|
+
assert_equal ::TranslatableNews, News.send(:translatable_model_prepared, "TranslatableNews")
|
28
|
+
end
|
29
|
+
|
30
|
+
should "Accept symbol" do
|
31
|
+
assert_equal ::TranslatableNews, News.send(:translatable_model_prepared, :TranslatableNews)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context "Instance" do
|
36
|
+
should "Respond to translatable methods" do
|
37
|
+
news = News.new
|
38
|
+
|
39
|
+
assert news.respond_to?(:title), "title methods is missing for News instance"
|
40
|
+
assert news.respond_to?(:content), "content methods is missing for News instance"
|
41
|
+
end
|
42
|
+
|
43
|
+
should "Creates without translation" do
|
44
|
+
news = News.create
|
45
|
+
|
46
|
+
assert news.persisted?
|
47
|
+
assert_nil TranslatableNews.last
|
48
|
+
end
|
49
|
+
|
50
|
+
should "Have no other translation" do
|
51
|
+
news = News.create :translations_attributes => [{ :title => "Заголовок", :content => "Содержание", :locale => "ru"}]
|
52
|
+
|
53
|
+
assert news.persisted?
|
54
|
+
|
55
|
+
t_news = TranslatableNews.last
|
56
|
+
assert_equal [t_news], news.other_translations
|
57
|
+
::I18n.locale = :ru
|
58
|
+
assert_equal [], news.other_translations
|
59
|
+
::I18n.locale = ::I18n.default_locale
|
60
|
+
end
|
61
|
+
|
62
|
+
should "Provide errors on creation" do
|
63
|
+
news = News.create :translations_attributes => [{:title => "Заголовок", :content => "Содержание", :locale => "ru"},
|
64
|
+
{:title => "Resent News", :content => "That is where the text goes", :locale => ""}]
|
65
|
+
|
66
|
+
assert news.new_record?
|
67
|
+
|
68
|
+
assert_equal ["Translations locale can't be blank"], news.errors.full_messages
|
69
|
+
|
70
|
+
news.translations.each do |t|
|
71
|
+
assert t.new_record?
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
context "Translatable instance" do
|
77
|
+
should "Respond to translatable methods" do
|
78
|
+
news = TranslatableNews.new
|
79
|
+
|
80
|
+
assert news.respond_to?(:title), "Title method is missing for TranslatableNews instance"
|
81
|
+
assert news.respond_to?(:content), "Content method is missing for TranslatableNews instance"
|
82
|
+
end
|
83
|
+
|
84
|
+
should "Respond to methods related to origin" do
|
85
|
+
news = TranslatableNews.new
|
86
|
+
|
87
|
+
assert news.respond_to?(:locale), "Locale method is missing for TranslatableNews instance"
|
88
|
+
assert news.respond_to?(:origin_id), "Origin methods is missing for TranslatableNews instance"
|
89
|
+
assert news.respond_to?(:origin), "Origin methods is missing for TranslatableNews instance"
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
context "Creation with translation" do
|
94
|
+
should "Assign to origin" do
|
95
|
+
news = News.create
|
96
|
+
t_news = TranslatableNews.create :title => "Заголовок", :content => "Содержание", :locale => "ru", :origin_id => news.id
|
97
|
+
|
98
|
+
assert t_news.persisted?
|
99
|
+
|
100
|
+
t_news = TranslatableNews.last
|
101
|
+
assert_equal news.id, t_news.origin_id
|
102
|
+
assert_equal "Заголовок", t_news.title
|
103
|
+
assert_equal "Содержание", t_news.content
|
104
|
+
assert_equal "ru", t_news.locale
|
105
|
+
end
|
106
|
+
|
107
|
+
should "Create translation on origin creation" do
|
108
|
+
news = News.create :translations_attributes => [{ :title => "Заголовок", :content => "Содержание", :locale => "ru"}]
|
109
|
+
|
110
|
+
assert news.persisted?
|
111
|
+
|
112
|
+
t_news = TranslatableNews.last
|
113
|
+
assert_equal news.id, t_news.origin_id.to_i
|
114
|
+
assert_equal "Заголовок", t_news.title
|
115
|
+
assert_equal "Содержание", t_news.content
|
116
|
+
assert_equal "ru", t_news.locale
|
117
|
+
end
|
118
|
+
|
119
|
+
should "Create multiple translations" do
|
120
|
+
news = News.create :translations_attributes => [{ :title => "Заголовок", :content => "Содержание", :locale => "ru"},
|
121
|
+
{:title => "Resent News", :content => "That is where the text goes", :locale => "en"}]
|
122
|
+
|
123
|
+
assert news.persisted?
|
124
|
+
|
125
|
+
t_news = TranslatableNews.first
|
126
|
+
assert_equal news.id, t_news.origin_id.to_i
|
127
|
+
assert_equal "Заголовок", t_news.title
|
128
|
+
assert_equal "Содержание", t_news.content
|
129
|
+
assert_equal "ru", t_news.locale
|
130
|
+
|
131
|
+
t_news = TranslatableNews.last
|
132
|
+
assert_equal news.id, t_news.origin_id.to_i
|
133
|
+
assert_equal "Resent News", t_news.title
|
134
|
+
assert_equal "That is where the text goes", t_news.content
|
135
|
+
assert_equal "en", t_news.locale
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
context "Current translation" do
|
140
|
+
should "Set default translation" do
|
141
|
+
news = News.create :translations_attributes => [{:title => "Заголовок", :content => "Содержание", :locale => "ru"},
|
142
|
+
{:title => "Resent News", :content => "That is where the text goes", :locale => "en"}]
|
143
|
+
|
144
|
+
assert news.persisted?
|
145
|
+
|
146
|
+
assert_equal "Resent News", news.title
|
147
|
+
assert_equal "That is where the text goes", news.content
|
148
|
+
end
|
149
|
+
|
150
|
+
should "Been set equal to current locale" do
|
151
|
+
news = News.create :translations_attributes => [{:title => "Заголовок", :content => "Содержание", :locale => "ru"},
|
152
|
+
{:title => "Resent News", :content => "That is where the text goes", :locale => "en"}]
|
153
|
+
|
154
|
+
assert news.persisted?
|
155
|
+
|
156
|
+
::I18n.locale = :ru
|
157
|
+
assert_equal "Заголовок", news.title
|
158
|
+
assert_equal "Содержание", news.content
|
159
|
+
::I18n.locale = ::I18n.default_locale
|
160
|
+
end
|
161
|
+
|
162
|
+
should "Not been set if unavailable" do
|
163
|
+
news = News.create :translations_attributes => [{:title => "Заголовок", :content => "Содержание", :locale => "ru"},
|
164
|
+
{:title => "Resent News", :content => "That is where the text goes", :locale => "en"}]
|
165
|
+
|
166
|
+
assert news.persisted?
|
167
|
+
|
168
|
+
::I18n.locale = :de
|
169
|
+
assert_nil news.title
|
170
|
+
assert_nil news.content
|
171
|
+
end
|
172
|
+
|
173
|
+
should "Be be switched on locale switching" do
|
174
|
+
news = News.create :translations_attributes => [{:title => "Resent News", :content => "That is where the text goes", :locale => "en"}]
|
175
|
+
|
176
|
+
assert news.persisted?
|
177
|
+
|
178
|
+
t_news = news.translations.create :title => "Заголовок", :content => "Содержание",:locale => "ru"
|
179
|
+
assert t_news.persisted?
|
180
|
+
|
181
|
+
::I18n.locale = ::I18n.default_locale
|
182
|
+
|
183
|
+
assert_equal "Resent News", news.title
|
184
|
+
assert_equal "That is where the text goes", news.content
|
185
|
+
|
186
|
+
::I18n.locale = :ru
|
187
|
+
|
188
|
+
assert_equal "Заголовок", news.title
|
189
|
+
assert_equal "Содержание", news.content
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
should "Add translation to existing record" do
|
194
|
+
news = News.create :translations_attributes => [{:title => "Resent News", :content => "That is where the text goes", :locale => "en"}]
|
195
|
+
|
196
|
+
assert news.persisted?
|
197
|
+
|
198
|
+
t_news = news.translations.create :title => "Заголовок", :content => "Содержание",:locale => "ru"
|
199
|
+
|
200
|
+
assert t_news.persisted?
|
201
|
+
assert t_news.persisted?
|
202
|
+
end
|
203
|
+
|
204
|
+
should "Define validations" do
|
205
|
+
post = Post.create :translations_attributes => [{:title => "Заголовок",:content => "Содержание", :locale => "ru"},
|
206
|
+
{:title => "Resent Post", :content => "That is where the text goes", :locale => "en"}]
|
207
|
+
assert post.persisted?, "Message had errors: #{post.errors.inspect}"
|
208
|
+
|
209
|
+
post = Post.create :translations_attributes => [{:content => "Содержание", :locale => "ru"},
|
210
|
+
{:title => "Resent Post 2", :content => "That is where the text goes", :locale => "en"}]
|
211
|
+
|
212
|
+
assert post.new_record?, "Message had errors: #{post.errors.full_messages.inspect}"
|
213
|
+
assert_equal ["Translations title can't be blank"], post.errors.full_messages
|
214
|
+
|
215
|
+
post = Post.create :translations_attributes => [{:title => "Заголовок 2", :locale => "ru"},
|
216
|
+
{:title => "Resent Post 3", :content => "That is where the text goes", :locale => "en"}]
|
217
|
+
|
218
|
+
assert post.new_record?, "Message had errors: #{post.errors.full_messages.inspect}"
|
219
|
+
assert_equal ["Translations content can't be blank"], post.errors.full_messages
|
220
|
+
|
221
|
+
post = Post.create :translations_attributes => [{:title => "Заголовок", :content => "Содержание", :locale => "ru"},
|
222
|
+
{:title => "Resent Post 3", :content => "That is where the text goes", :locale => "en"}]
|
223
|
+
|
224
|
+
assert post.new_record?, "Message had errors: #{post.errors.full_messages.inspect}"
|
225
|
+
assert_equal ["Translations title has already been taken"], post.errors.full_messages
|
226
|
+
end
|
227
|
+
|
228
|
+
def test_origin_is_owerwrittent
|
229
|
+
post = Post.create :translations_attributes => [{:title => "Заголовок",:content => "Содержание", :locale => "ru"},
|
230
|
+
{:title => "Resent Post", :content => "That is where the text goes", :locale => "en"}]
|
231
|
+
assert post.persisted?, "Message had errors: #{post.errors.inspect}"
|
232
|
+
|
233
|
+
assert_not_equal post.object_id, post.translations.first.post.object_id
|
234
|
+
end
|
235
|
+
|
236
|
+
should "Accept aliases for fileds" do
|
237
|
+
post = Post.create :translations_attributes => [{:title => "Заголовок",:content => "Содержание", :locale => "ru"},
|
238
|
+
{:title => "Resent Post", :content => "That is where the text goes", :locale => "en"}]
|
239
|
+
assert post.persisted?, "Message had errors: #{post.errors.inspect}"
|
240
|
+
|
241
|
+
assert_equal "Resent Post", post.translated_title
|
242
|
+
|
243
|
+
::I18n.locale = :ru
|
244
|
+
assert_equal "Заголовок", post.translated_title
|
245
|
+
::I18n.locale = ::I18n.default_locale
|
246
|
+
end
|
247
|
+
|
248
|
+
context "Mass assigment" do
|
249
|
+
should "Be available to mass assigment by default" do
|
250
|
+
tp = TranslatableNews.new( :title => "Resent News", :content => "That is where the text goes", :locale => "en", :origin_id => 1)
|
251
|
+
|
252
|
+
assert_equal "Resent News", tp.title
|
253
|
+
assert_equal "That is where the text goes", tp.content
|
254
|
+
assert_equal "en", tp.locale
|
255
|
+
assert_equal 1, tp.origin_id
|
256
|
+
end
|
257
|
+
|
258
|
+
should "Protect internal fields on desire" do
|
259
|
+
tm = TranslatedMessage.new( :title => "Resent Post", :content => "That is where the text goes", :locale => "en", :message_id => 1)
|
260
|
+
|
261
|
+
assert_equal "Resent Post", tm.title
|
262
|
+
assert_equal "That is where the text goes", tm.content
|
263
|
+
assert_equal nil, tm.locale
|
264
|
+
assert_equal nil, tm.message_id
|
265
|
+
end
|
266
|
+
|
267
|
+
should "Allow multiple assigment rules" do
|
268
|
+
tm = TranslatedMessage.new( {:title => "Resent Post", :content => "That is where the text goes", :locale => "en", :message_id => 1}, :as => :editor)
|
269
|
+
|
270
|
+
assert_equal "Resent Post", tm.title
|
271
|
+
assert_equal "That is where the text goes", tm.content
|
272
|
+
assert_equal "en", tm.locale
|
273
|
+
assert_equal nil, tm.message_id
|
274
|
+
end
|
275
|
+
end
|
276
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
require "rails"
|
3
|
+
require 'rails/generators'
|
4
|
+
require "generators/translatable/model_generator"
|
5
|
+
|
6
|
+
class ModelGeneratorTest < Rails::Generators::TestCase
|
7
|
+
tests Translatable::Generators::ModelGenerator
|
8
|
+
destination File.expand_path("../../../tmp", __FILE__)
|
9
|
+
setup :prepare_destination
|
10
|
+
teardown :cleanup_destination_root
|
11
|
+
|
12
|
+
should "Create required files with default options" do
|
13
|
+
run_generator %w(article title:string content:string)
|
14
|
+
assert_file "app/models/article.rb", <<CONTENT
|
15
|
+
class Article < ActiveRecord::Base
|
16
|
+
translatable do
|
17
|
+
translatable :title, :presence => true#, :uniqueness => true
|
18
|
+
translatable :content, :presence => true#, :uniqueness => true
|
19
|
+
#translatable_model 'TranslatedArticle'
|
20
|
+
#translatable_origin :article
|
21
|
+
#translatable_locale :locale
|
22
|
+
end
|
23
|
+
end
|
24
|
+
CONTENT
|
25
|
+
assert_migration "db/migrate/create_articles.rb", <<CONTENT
|
26
|
+
class CreateArticles < ActiveRecord::Migration
|
27
|
+
def change
|
28
|
+
create_table :articles do |t|
|
29
|
+
|
30
|
+
t.timestamps
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
CONTENT
|
35
|
+
end
|
36
|
+
|
37
|
+
should "Create required files with special options" do
|
38
|
+
run_generator %w(article title:string content:string --translated_model=ArticleTranslation --origin=post --locale=language)
|
39
|
+
assert_file "app/models/article.rb", <<CONTENT
|
40
|
+
class Article < ActiveRecord::Base
|
41
|
+
translatable do
|
42
|
+
translatable :title, :presence => true#, :uniqueness => true
|
43
|
+
translatable :content, :presence => true#, :uniqueness => true
|
44
|
+
translatable_model 'ArticleTranslation'
|
45
|
+
translatable_origin :post
|
46
|
+
translatable_locale :language
|
47
|
+
end
|
48
|
+
end
|
49
|
+
CONTENT
|
50
|
+
assert_migration "db/migrate/create_articles.rb", <<CONTENT
|
51
|
+
class CreateArticles < ActiveRecord::Migration
|
52
|
+
def change
|
53
|
+
create_table :articles do |t|
|
54
|
+
|
55
|
+
t.timestamps
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
CONTENT
|
60
|
+
end
|
61
|
+
|
62
|
+
should "Inject into existing class" do
|
63
|
+
create_model_file
|
64
|
+
run_generator %w(article title:string content:string)
|
65
|
+
|
66
|
+
assert_file "app/models/article.rb", <<CONTENT
|
67
|
+
class Article < ActiveRecord::Base
|
68
|
+
translatable do
|
69
|
+
translatable :title, :presence => true#, :uniqueness => true
|
70
|
+
translatable :content, :presence => true#, :uniqueness => true
|
71
|
+
#translatable_model 'TranslatedArticle'
|
72
|
+
#translatable_origin :article
|
73
|
+
#translatable_locale :locale
|
74
|
+
end
|
75
|
+
attr_accessor :created_at, :updated_at
|
76
|
+
end
|
77
|
+
CONTENT
|
78
|
+
assert_no_migration "db/migrate/create_articles.rb"
|
79
|
+
end
|
80
|
+
|
81
|
+
protected
|
82
|
+
|
83
|
+
def create_model_file
|
84
|
+
FileUtils.mkdir_p File.join(destination_root, "app", "models")
|
85
|
+
f = File.open(File.join(destination_root, "app", "models", "article.rb"), "w+")
|
86
|
+
f.write <<CONTENT
|
87
|
+
class Article < ActiveRecord::Base
|
88
|
+
attr_accessor :created_at, :updated_at
|
89
|
+
end
|
90
|
+
CONTENT
|
91
|
+
f.close
|
92
|
+
end
|
93
|
+
|
94
|
+
def cleanup_destination_root
|
95
|
+
FileUtils.rm_rf destination_root
|
96
|
+
end
|
97
|
+
end
|