translatable 0.2.4 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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/.travis.yml
CHANGED
data/Gemfile
CHANGED
@@ -1,21 +1,25 @@
|
|
1
1
|
source "http://rubygems.org"
|
2
2
|
|
3
3
|
gem "activerecord"
|
4
|
+
gem "activesupport", :require => false
|
4
5
|
gem "i18n"
|
5
6
|
|
7
|
+
group :debug do
|
8
|
+
gem "simplecov", ">= 0.6.0", :platform => :ruby_19
|
9
|
+
gem "debugger", "~> 1.1.3", :platform => :ruby_19
|
10
|
+
gem "ruby-debug", :platform => :ruby_18
|
11
|
+
end
|
12
|
+
|
6
13
|
group :development do
|
7
14
|
gem "yard"
|
8
15
|
gem "jeweler", ">= 1.6.0"
|
9
|
-
gem "bundler", ">= 1.
|
10
|
-
gem "simplecov", ">= 0.6.0", :platform => :ruby_19
|
11
|
-
gem "rcov", ">= 1.0.0", :platform => :ruby_18
|
16
|
+
gem "bundler", ">= 1.2.0"
|
12
17
|
end
|
13
18
|
|
14
19
|
group :test do
|
15
|
-
gem "
|
16
|
-
|
17
|
-
gem "
|
18
|
-
gem 'ruby-debug', :platform => :ruby_18
|
20
|
+
gem "rails"
|
21
|
+
gem "test-unit"
|
22
|
+
gem "shoulda"
|
19
23
|
|
20
24
|
gem "database_cleaner"
|
21
25
|
gem "sqlite3"
|
data/Gemfile.lock
CHANGED
@@ -1,6 +1,20 @@
|
|
1
1
|
GEM
|
2
2
|
remote: http://rubygems.org/
|
3
3
|
specs:
|
4
|
+
actionmailer (3.1.8)
|
5
|
+
actionpack (= 3.1.8)
|
6
|
+
mail (~> 2.3.3)
|
7
|
+
actionpack (3.1.8)
|
8
|
+
activemodel (= 3.1.8)
|
9
|
+
activesupport (= 3.1.8)
|
10
|
+
builder (~> 3.0.0)
|
11
|
+
erubis (~> 2.7.0)
|
12
|
+
i18n (~> 0.6)
|
13
|
+
rack (~> 1.3.6)
|
14
|
+
rack-cache (~> 1.2)
|
15
|
+
rack-mount (~> 0.8.2)
|
16
|
+
rack-test (~> 0.6.1)
|
17
|
+
sprockets (~> 2.0.4)
|
4
18
|
activemodel (3.1.8)
|
5
19
|
activesupport (= 3.1.8)
|
6
20
|
builder (~> 3.0.0)
|
@@ -10,6 +24,9 @@ GEM
|
|
10
24
|
activesupport (= 3.1.8)
|
11
25
|
arel (~> 2.2.3)
|
12
26
|
tzinfo (~> 0.3.29)
|
27
|
+
activeresource (3.1.8)
|
28
|
+
activemodel (= 3.1.8)
|
29
|
+
activesupport (= 3.1.8)
|
13
30
|
activesupport (3.1.8)
|
14
31
|
multi_json (>= 1.0, < 1.3)
|
15
32
|
arel (2.2.3)
|
@@ -23,29 +40,78 @@ GEM
|
|
23
40
|
debugger-linecache (1.1.2)
|
24
41
|
debugger-ruby_core_source (>= 1.1.1)
|
25
42
|
debugger-ruby_core_source (1.1.3)
|
43
|
+
erubis (2.7.0)
|
26
44
|
git (1.2.5)
|
45
|
+
hike (1.2.1)
|
27
46
|
i18n (0.6.0)
|
28
47
|
jeweler (1.6.4)
|
29
48
|
bundler (~> 1.0)
|
30
49
|
git (>= 1.2.5)
|
31
50
|
rake
|
51
|
+
json (1.7.5)
|
32
52
|
linecache (0.46)
|
33
53
|
rbx-require-relative (> 0.0.4)
|
54
|
+
mail (2.3.3)
|
55
|
+
i18n (>= 0.4.0)
|
56
|
+
mime-types (~> 1.16)
|
57
|
+
treetop (~> 1.4.8)
|
58
|
+
mime-types (1.19)
|
34
59
|
multi_json (1.2.0)
|
60
|
+
polyglot (0.3.3)
|
61
|
+
rack (1.3.6)
|
62
|
+
rack-cache (1.2)
|
63
|
+
rack (>= 0.4)
|
64
|
+
rack-mount (0.8.3)
|
65
|
+
rack (>= 1.0.0)
|
66
|
+
rack-ssl (1.3.2)
|
67
|
+
rack
|
68
|
+
rack-test (0.6.2)
|
69
|
+
rack (>= 1.0)
|
70
|
+
rails (3.1.8)
|
71
|
+
actionmailer (= 3.1.8)
|
72
|
+
actionpack (= 3.1.8)
|
73
|
+
activerecord (= 3.1.8)
|
74
|
+
activeresource (= 3.1.8)
|
75
|
+
activesupport (= 3.1.8)
|
76
|
+
bundler (~> 1.0)
|
77
|
+
railties (= 3.1.8)
|
78
|
+
railties (3.1.8)
|
79
|
+
actionpack (= 3.1.8)
|
80
|
+
activesupport (= 3.1.8)
|
81
|
+
rack-ssl (~> 1.3.2)
|
82
|
+
rake (>= 0.8.7)
|
83
|
+
rdoc (~> 3.4)
|
84
|
+
thor (~> 0.14.6)
|
35
85
|
rake (0.9.2.2)
|
36
86
|
rbx-require-relative (0.0.9)
|
37
|
-
|
87
|
+
rdoc (3.12)
|
88
|
+
json (~> 1.4)
|
38
89
|
ruby-debug (0.10.4)
|
39
90
|
columnize (>= 0.1)
|
40
91
|
ruby-debug-base (~> 0.10.4.0)
|
41
92
|
ruby-debug-base (0.10.4)
|
42
93
|
linecache (>= 0.3)
|
94
|
+
shoulda (3.3.2)
|
95
|
+
shoulda-context (~> 1.0.1)
|
96
|
+
shoulda-matchers (~> 1.4.1)
|
97
|
+
shoulda-context (1.0.1)
|
98
|
+
shoulda-matchers (1.4.1)
|
99
|
+
activesupport (>= 3.0.0)
|
43
100
|
simplecov (0.6.4)
|
44
101
|
multi_json (~> 1.0)
|
45
102
|
simplecov-html (~> 0.5.3)
|
46
103
|
simplecov-html (0.5.3)
|
104
|
+
sprockets (2.0.4)
|
105
|
+
hike (~> 1.2)
|
106
|
+
rack (~> 1.0)
|
107
|
+
tilt (~> 1.1, != 1.3.0)
|
47
108
|
sqlite3 (1.3.6)
|
48
|
-
test-
|
109
|
+
test-unit (2.5.3)
|
110
|
+
thor (0.14.6)
|
111
|
+
tilt (1.3.3)
|
112
|
+
treetop (1.4.12)
|
113
|
+
polyglot
|
114
|
+
polyglot (>= 0.3.1)
|
49
115
|
tzinfo (0.3.33)
|
50
116
|
yard (0.6.8)
|
51
117
|
|
@@ -54,14 +120,16 @@ PLATFORMS
|
|
54
120
|
|
55
121
|
DEPENDENCIES
|
56
122
|
activerecord
|
57
|
-
|
123
|
+
activesupport
|
124
|
+
bundler (>= 1.2.0)
|
58
125
|
database_cleaner
|
59
126
|
debugger (~> 1.1.3)
|
60
127
|
i18n
|
61
128
|
jeweler (>= 1.6.0)
|
62
|
-
|
129
|
+
rails
|
63
130
|
ruby-debug
|
131
|
+
shoulda
|
64
132
|
simplecov (>= 0.6.0)
|
65
133
|
sqlite3
|
66
|
-
test-
|
134
|
+
test-unit
|
67
135
|
yard
|
data/Rakefile
CHANGED
@@ -28,12 +28,16 @@ Jeweler::RubygemsDotOrgTasks.new
|
|
28
28
|
require 'rake/testtask'
|
29
29
|
Rake::TestTask.new(:test) do |test|
|
30
30
|
test.libs << 'lib' << 'test'
|
31
|
-
test.pattern = 'test
|
31
|
+
test.pattern = 'test/**/*_test.rb'
|
32
32
|
test.verbose = true
|
33
33
|
end
|
34
34
|
|
35
35
|
task :default => :test
|
36
36
|
|
37
|
-
|
38
|
-
|
37
|
+
begin
|
38
|
+
require 'yard'
|
39
|
+
YARD::Rake::YardocTask.new
|
40
|
+
rescue LoadError
|
41
|
+
$stderr.puts "Skipping Yard tasks"
|
42
|
+
end
|
39
43
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.3.0
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require "translatable/generator_helper"
|
2
|
+
|
3
|
+
module Translatable
|
4
|
+
module Generators
|
5
|
+
class ModelGenerator < Rails::Generators::NamedBase
|
6
|
+
include Translatable::GeneratorHelper
|
7
|
+
|
8
|
+
desc "Creates ActiveRecord model and injects translatable block into it"
|
9
|
+
|
10
|
+
class_option :translated_model, :type => :string, :desc => "Defines the model responsible for translations"
|
11
|
+
class_option :origin, :type => :string, :desc => "Defines the association name for translation record that deals with origin"
|
12
|
+
class_option :locale, :type => :string, :desc => "Defines the column for translation record that keeps the locale"
|
13
|
+
|
14
|
+
def create_model
|
15
|
+
self.attributes = attrs
|
16
|
+
parse_attributes!
|
17
|
+
invoke "active_record:model", [class_name], {migration: true, timestamps: true} unless model_exists?
|
18
|
+
end
|
19
|
+
|
20
|
+
# all public methods in here will be run in order
|
21
|
+
def inject_translatable_block
|
22
|
+
inject_into_class model_path, class_name, generate_translatable_block
|
23
|
+
end
|
24
|
+
|
25
|
+
protected
|
26
|
+
|
27
|
+
def generate_translatable_block
|
28
|
+
block = " translatable do"
|
29
|
+
attributes.each do |attr|
|
30
|
+
block << "\n translatable :#{attr.name}, :presence => true#, :uniqueness => true"
|
31
|
+
end
|
32
|
+
block << (options[:translated_model].nil? ?
|
33
|
+
"\n #translatable_model 'Translated#{class_name}'" :
|
34
|
+
"\n translatable_model '#{options[:translated_model]}'")
|
35
|
+
block << (options[:origin].nil? ?
|
36
|
+
"\n #translatable_origin :#{singular_table_name}" :
|
37
|
+
"\n translatable_origin :#{options[:origin]}")
|
38
|
+
block << (options[:locale].nil? ?
|
39
|
+
"\n #translatable_locale :locale" :
|
40
|
+
"\n translatable_locale :#{options[:locale]}")
|
41
|
+
block << "\n end\n"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require "translatable/generator_helper"
|
2
|
+
|
3
|
+
module Translatable
|
4
|
+
module Generators
|
5
|
+
class TranslationGenerator < Rails::Generators::NamedBase
|
6
|
+
include Translatable::GeneratorHelper
|
7
|
+
|
8
|
+
desc "Creates ActiveRecord for translation dealer"
|
9
|
+
|
10
|
+
class_option :prefix, :type => :string, :default => "translatable", :desc => "Specifies the prefix to used tof translation dealer (Default: translatable)"
|
11
|
+
class_option :origin, :type => :string, :default => "origin", :desc => "Specifies the association name to be use for origin (Default: origin)"
|
12
|
+
class_option :locale, :type => :string, :default => "locale", :desc => "Specifies the column to be use for locale (Default: locale)"
|
13
|
+
|
14
|
+
def create_model
|
15
|
+
self.attributes = attrs
|
16
|
+
parse_attributes!
|
17
|
+
invoke "active_record:model", [class_name] + attrs + ["#{options[:origin]}_id:integer:true", "#{options[:locale]}:string"], {migration: true, timestamps: true} unless model_exists?
|
18
|
+
end
|
19
|
+
|
20
|
+
# all public methods in here will be run in order
|
21
|
+
def inject_translatable_block
|
22
|
+
inject_into_class model_path, class_name, generate_translatable_block
|
23
|
+
end
|
24
|
+
|
25
|
+
protected
|
26
|
+
|
27
|
+
def generate_translatable_block
|
28
|
+
block = <<CONTENT
|
29
|
+
# This class deals purely with translations themselves. Hence, any edition of
|
30
|
+
# should be avoided.
|
31
|
+
# In later gem version its existance might not be necessary.
|
32
|
+
CONTENT
|
33
|
+
unless attributes.empty?
|
34
|
+
block << " attr_accessible :#{attributes.map(&:name).join(", :")}\n"
|
35
|
+
end
|
36
|
+
block << " #attr_protected :#{options[:origin]}_id, :#{options[:locale]}\n"
|
37
|
+
block
|
38
|
+
end
|
39
|
+
|
40
|
+
def file_name
|
41
|
+
"#{options[:prefix].downcase}_#{@file_name}"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,254 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
require 'i18n'
|
3
|
+
|
4
|
+
module Translatable
|
5
|
+
###
|
6
|
+
# In order to made the model Translatable, an additional fields should
|
7
|
+
# should be added first to it. Here is an example of it might be implemented:
|
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 ActiveRecord
|
54
|
+
|
55
|
+
def translatable
|
56
|
+
extend Translatable::ActiveRecord::ClassMethods
|
57
|
+
include Translatable::ActiveRecord::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(locale = ::I18n.locale)
|
203
|
+
locale = locale.to_s
|
204
|
+
@current_translation = if translations.loaded?
|
205
|
+
translations.select { |t| t.send(:"#{@translatable[:locale]}") == locale }
|
206
|
+
else
|
207
|
+
translations.where(:"#{@translatable[:locale]}" => locale)
|
208
|
+
end.first
|
209
|
+
end
|
210
|
+
alias_method :set_current_translation, :translatable_set_current
|
211
|
+
RUBY
|
212
|
+
end
|
213
|
+
|
214
|
+
def translatable_register_properties_for_translatable
|
215
|
+
@translatable[:model].module_eval <<-RUBY, __FILE__, __LINE__ + 1
|
216
|
+
validates :#{@translatable[:locale]}, :presence => true
|
217
|
+
validates :#{@translatable[:locale]}, :format => { :with => /[a-z]{2}/}, :if => Proc.new {|record| !record.#{@translatable[:locale]}.blank? }
|
218
|
+
validates :#{@translatable[:locale]}, :uniqueness => { :scope => :#{@translatable[:origin]}_id }
|
219
|
+
|
220
|
+
belongs_to :#{@translatable[:origin]}, :class_name => "#{self.name}"
|
221
|
+
RUBY
|
222
|
+
|
223
|
+
unless @translatable[:attr_accessible].nil?
|
224
|
+
@translatable[:model].module_eval <<-RUBY, __FILE__, __LINE__ + 1
|
225
|
+
attr_#{!!@translatable[:attr_accessible] ? "accessible" : "protected" } :#{@translatable[:locale]}, :#{@translatable[:origin]}_id
|
226
|
+
RUBY
|
227
|
+
end
|
228
|
+
|
229
|
+
@translatable[:properties].each do |p|
|
230
|
+
if p.size > 1
|
231
|
+
@translatable[:model].module_eval <<-RUBY, __FILE__, __LINE__ + 1
|
232
|
+
validates :#{p.first}, #{p.last.inspect}
|
233
|
+
RUBY
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
module InstanceMethods
|
240
|
+
def current_translation
|
241
|
+
update_current_translation unless @translatable_locale
|
242
|
+
@current_translation
|
243
|
+
end
|
244
|
+
|
245
|
+
def update_current_translation
|
246
|
+
translatable_set_current(@translatable_locale = ::I18n.locale.to_s)
|
247
|
+
end
|
248
|
+
|
249
|
+
def other_translations
|
250
|
+
translations - [current_translation]
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end
|
254
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Translatable
|
2
|
+
module GeneratorHelper
|
3
|
+
def self.included(base)
|
4
|
+
base.class_eval do
|
5
|
+
attr_accessor :attributes
|
6
|
+
argument :attrs, type: :array, default: [], banner: "field[:type][:index] field[:type][:index]"
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
protected
|
11
|
+
|
12
|
+
def model_path
|
13
|
+
File.join(destination_root, 'app/models', class_path, "#{file_name}.rb")
|
14
|
+
end
|
15
|
+
|
16
|
+
def model_exists?
|
17
|
+
File.exists?(model_path)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|