dm-translatable 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm use --create 1.9.2@dm-paperclip
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.8.7
4
+ - 1.9.2
5
+ - 1.9.3
data/Gemfile ADDED
@@ -0,0 +1,20 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem "data_mapper"
4
+ gem "i18n"
5
+
6
+ group :development, :test do
7
+ gem "test-spec"
8
+ gem "yard", "~> 0.6.0"
9
+ gem "bundler", "~> 1.0.0"
10
+ gem "jeweler", "~> 1.6.4"
11
+
12
+ gem "debugger", "~> 1.1.3", :platform => :ruby_19
13
+ gem "simplecov", "~> 0.6.4", :platform => :ruby_19
14
+
15
+ gem 'ruby-debug', :platform => :ruby_18
16
+ gem "rcov", "~> 1.0.0", :platform => :ruby_18
17
+
18
+ gem "database_cleaner", "~> 0.7.2"
19
+ gem "dm-sqlite-adapter"
20
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,107 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ addressable (2.2.8)
5
+ bcrypt-ruby (3.0.1)
6
+ columnize (0.3.6)
7
+ data_mapper (1.2.0)
8
+ dm-aggregates (~> 1.2.0)
9
+ dm-constraints (~> 1.2.0)
10
+ dm-core (~> 1.2.0)
11
+ dm-migrations (~> 1.2.0)
12
+ dm-serializer (~> 1.2.0)
13
+ dm-timestamps (~> 1.2.0)
14
+ dm-transactions (~> 1.2.0)
15
+ dm-types (~> 1.2.0)
16
+ dm-validations (~> 1.2.0)
17
+ data_objects (0.10.8)
18
+ addressable (~> 2.1)
19
+ database_cleaner (0.7.2)
20
+ debugger (1.1.4)
21
+ columnize (>= 0.3.1)
22
+ debugger-linecache (~> 1.1.1)
23
+ debugger-ruby_core_source (~> 1.1.3)
24
+ debugger-linecache (1.1.2)
25
+ debugger-ruby_core_source (>= 1.1.1)
26
+ debugger-ruby_core_source (1.1.3)
27
+ dm-aggregates (1.2.0)
28
+ dm-core (~> 1.2.0)
29
+ dm-constraints (1.2.0)
30
+ dm-core (~> 1.2.0)
31
+ dm-core (1.2.0)
32
+ addressable (~> 2.2.6)
33
+ dm-do-adapter (1.2.0)
34
+ data_objects (~> 0.10.6)
35
+ dm-core (~> 1.2.0)
36
+ dm-migrations (1.2.0)
37
+ dm-core (~> 1.2.0)
38
+ dm-serializer (1.2.2)
39
+ dm-core (~> 1.2.0)
40
+ fastercsv (~> 1.5)
41
+ json (~> 1.6)
42
+ json_pure (~> 1.6)
43
+ multi_json (~> 1.0)
44
+ dm-sqlite-adapter (1.2.0)
45
+ dm-do-adapter (~> 1.2.0)
46
+ do_sqlite3 (~> 0.10.6)
47
+ dm-timestamps (1.2.0)
48
+ dm-core (~> 1.2.0)
49
+ dm-transactions (1.2.0)
50
+ dm-core (~> 1.2.0)
51
+ dm-types (1.2.2)
52
+ bcrypt-ruby (~> 3.0)
53
+ dm-core (~> 1.2.0)
54
+ fastercsv (~> 1.5)
55
+ json (~> 1.6)
56
+ multi_json (~> 1.0)
57
+ stringex (~> 1.4)
58
+ uuidtools (~> 2.1)
59
+ dm-validations (1.2.0)
60
+ dm-core (~> 1.2.0)
61
+ do_sqlite3 (0.10.8)
62
+ data_objects (= 0.10.8)
63
+ fastercsv (1.5.5)
64
+ git (1.2.5)
65
+ i18n (0.6.0)
66
+ jeweler (1.6.4)
67
+ bundler (~> 1.0)
68
+ git (>= 1.2.5)
69
+ rake
70
+ json (1.7.4)
71
+ json_pure (1.7.4)
72
+ linecache (0.46)
73
+ rbx-require-relative (> 0.0.4)
74
+ multi_json (1.3.6)
75
+ rake (0.9.2.2)
76
+ rbx-require-relative (0.0.9)
77
+ rcov (1.0.0)
78
+ ruby-debug (0.10.4)
79
+ columnize (>= 0.1)
80
+ ruby-debug-base (~> 0.10.4.0)
81
+ ruby-debug-base (0.10.4)
82
+ linecache (>= 0.3)
83
+ simplecov (0.6.4)
84
+ multi_json (~> 1.0)
85
+ simplecov-html (~> 0.5.3)
86
+ simplecov-html (0.5.3)
87
+ stringex (1.4.0)
88
+ test-spec (0.10.0)
89
+ uuidtools (2.1.3)
90
+ yard (0.6.8)
91
+
92
+ PLATFORMS
93
+ ruby
94
+
95
+ DEPENDENCIES
96
+ bundler (~> 1.0.0)
97
+ data_mapper
98
+ database_cleaner (~> 0.7.2)
99
+ debugger (~> 1.1.3)
100
+ dm-sqlite-adapter
101
+ i18n
102
+ jeweler (~> 1.6.4)
103
+ rcov (~> 1.0.0)
104
+ ruby-debug
105
+ simplecov (~> 0.6.4)
106
+ test-spec
107
+ yard (~> 0.6.0)
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2012 E-Max
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,87 @@
1
+ == dm-translatable
2
+
3
+ {<img src="https://secure.travis-ci.org/kot-begemot/dm-translatable.png" />}[http://travis-ci.org/kot-begemot/dm-translatable]
4
+
5
+ Whenever you have to deal with multilingual project, where users may fill the post
6
+ in different languages, or you have to provide the content in the same way, this
7
+ gem will save your day.
8
+
9
+ == What it does?
10
+
11
+ This gem interferes heavily with I18n.
12
+ First you need to do is to define the model that accepts multilingual context (there
13
+ might me more than one of them). There you have to specify the fields that are translatable
14
+ and some other details.
15
+ Well,that is pretty much it. Now you can create a model with translations, and
16
+ switching current locale you will get different translations.
17
+ If there is no translation available, you will get nil.
18
+
19
+ Check out the examples below.
20
+
21
+ == Examples
22
+
23
+ Examples of code:
24
+
25
+ class TranslatedNews
26
+ include DataMapper::Resource
27
+
28
+ property :id, Serial
29
+
30
+ attr_accessible :title, :content
31
+ end
32
+
33
+ class News
34
+ include DataMapper::Resource
35
+
36
+ property :id, Serial
37
+ property :author_id, Integer, required: true
38
+
39
+ is :translatable do
40
+ translatable_property :title, String, required: true, unique: true
41
+ translatable_property :content, Text, required: true
42
+ translatable_model 'TranslatedNews'
43
+ translatable_origin :origin_id
44
+ end
45
+
46
+ end
47
+
48
+ An example of application:
49
+
50
+ news = News.create :translations => [{title: "Resent News", content: "That is where the text goes", locale: "en"}]
51
+ news.translations.create title: "Заголовок", content: "Содержание",locale: "ru"
52
+
53
+ news.content
54
+ # => "That is where the text goes"
55
+
56
+ ::I18n.locale = "ru"
57
+ news.content
58
+ # => "Сюди идет текст"
59
+
60
+ ::I18n.locale = "de"
61
+ news.content
62
+ # => nil
63
+
64
+ ::I18n.locale = ::I18n.default_locale
65
+ news.content
66
+ # => "That is where the text goes"
67
+
68
+ == NB! Errors handling
69
+
70
+ Even if the translation was invalid(eg. Locale was missing) the original model will still be saved.
71
+ So later you'll have to +UPDATE+ it
72
+
73
+ == Contributing to dm-translatable
74
+
75
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
76
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
77
+ * Fork the project
78
+ * Start a feature/bugfix branch
79
+ * Commit and push until you are happy with your contribution
80
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
81
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
82
+
83
+ == Copyright
84
+
85
+ Copyright (c) 2012 E-Max. See LICENSE.txt for
86
+ further details.
87
+
data/Rakefile ADDED
@@ -0,0 +1,38 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17
+ gem.name = "dm-translatable"
18
+ gem.homepage = "http://github.com/kot-begemot/dm-translatable"
19
+ gem.license = "MIT"
20
+ gem.summary = %Q{An esay way to manage the translations for datamapper}
21
+ gem.description = %Q{This game was build to make whole proccess of working with translation for DM to be almost invisble. That was THE AIM.}
22
+ gem.email = "max@studentify.nl"
23
+ gem.authors = ["E-Max"]
24
+ # dependencies defined in Gemfile
25
+ end
26
+ Jeweler::RubygemsDotOrgTasks.new
27
+
28
+ require 'rake/testtask'
29
+ Rake::TestTask.new(:test) do |test|
30
+ test.libs << 'lib' << 'test'
31
+ test.pattern = 'test/**/test_*.rb'
32
+ test.verbose = true
33
+ end
34
+
35
+ task :default => :test
36
+
37
+ require 'yard'
38
+ YARD::Rake::YardocTask.new
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,88 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "dm-translatable"
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["E-Max"]
12
+ s.date = "2012-08-14"
13
+ s.description = "This game was build to make whole proccess of working with translation for DM to be almost invisble. That was THE AIM."
14
+ s.email = "max@studentify.nl"
15
+ s.extra_rdoc_files = [
16
+ "LICENSE.txt",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".rvmrc",
22
+ ".travis.yml",
23
+ "Gemfile",
24
+ "Gemfile.lock",
25
+ "LICENSE.txt",
26
+ "README.rdoc",
27
+ "Rakefile",
28
+ "VERSION",
29
+ "dm-translatable.gemspec",
30
+ "lib/dm-translatable.rb",
31
+ "test/helper.rb",
32
+ "test/news.rb",
33
+ "test/support/data_mapper.rb",
34
+ "test/support/database_cleaner.rb",
35
+ "test/test_dm-translatable.rb"
36
+ ]
37
+ s.homepage = "http://github.com/kot-begemot/dm-translatable"
38
+ s.licenses = ["MIT"]
39
+ s.require_paths = ["lib"]
40
+ s.rubygems_version = "1.8.10"
41
+ s.summary = "An esay way to manage the translations for datamapper"
42
+
43
+ if s.respond_to? :specification_version then
44
+ s.specification_version = 3
45
+
46
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
47
+ s.add_runtime_dependency(%q<data_mapper>, [">= 0"])
48
+ s.add_runtime_dependency(%q<i18n>, [">= 0"])
49
+ s.add_development_dependency(%q<test-spec>, [">= 0"])
50
+ s.add_development_dependency(%q<yard>, ["~> 0.6.0"])
51
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
52
+ s.add_development_dependency(%q<jeweler>, ["~> 1.6.4"])
53
+ s.add_development_dependency(%q<debugger>, ["~> 1.1.3"])
54
+ s.add_development_dependency(%q<simplecov>, ["~> 0.6.4"])
55
+ s.add_development_dependency(%q<ruby-debug>, [">= 0"])
56
+ s.add_development_dependency(%q<rcov>, ["~> 1.0.0"])
57
+ s.add_development_dependency(%q<database_cleaner>, ["~> 0.7.2"])
58
+ s.add_development_dependency(%q<dm-sqlite-adapter>, [">= 0"])
59
+ else
60
+ s.add_dependency(%q<data_mapper>, [">= 0"])
61
+ s.add_dependency(%q<i18n>, [">= 0"])
62
+ s.add_dependency(%q<test-spec>, [">= 0"])
63
+ s.add_dependency(%q<yard>, ["~> 0.6.0"])
64
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
65
+ s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
66
+ s.add_dependency(%q<debugger>, ["~> 1.1.3"])
67
+ s.add_dependency(%q<simplecov>, ["~> 0.6.4"])
68
+ s.add_dependency(%q<ruby-debug>, [">= 0"])
69
+ s.add_dependency(%q<rcov>, ["~> 1.0.0"])
70
+ s.add_dependency(%q<database_cleaner>, ["~> 0.7.2"])
71
+ s.add_dependency(%q<dm-sqlite-adapter>, [">= 0"])
72
+ end
73
+ else
74
+ s.add_dependency(%q<data_mapper>, [">= 0"])
75
+ s.add_dependency(%q<i18n>, [">= 0"])
76
+ s.add_dependency(%q<test-spec>, [">= 0"])
77
+ s.add_dependency(%q<yard>, ["~> 0.6.0"])
78
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
79
+ s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
80
+ s.add_dependency(%q<debugger>, ["~> 1.1.3"])
81
+ s.add_dependency(%q<simplecov>, ["~> 0.6.4"])
82
+ s.add_dependency(%q<ruby-debug>, [">= 0"])
83
+ s.add_dependency(%q<rcov>, ["~> 1.0.0"])
84
+ s.add_dependency(%q<database_cleaner>, ["~> 0.7.2"])
85
+ s.add_dependency(%q<dm-sqlite-adapter>, [">= 0"])
86
+ end
87
+ end
88
+
@@ -0,0 +1,221 @@
1
+ require 'dm-core'
2
+ require 'i18n'
3
+
4
+ class String
5
+ def constantize
6
+ self.split("::").tap do |s|
7
+ s.shift if s.first.empty?
8
+ end.inject(Module) {|acc, val| acc.const_get(val)}
9
+ end
10
+ end
11
+
12
+ module DataMapper
13
+ module Is
14
+ ###
15
+ # In order to made the model Translatable, an additional fields should
16
+ # should be added first to it. Here is an example of it might be implemented:
17
+ #
18
+ # Examples:
19
+ #
20
+ # class TranslatedNews
21
+ # include DataMapper::Resource
22
+ #
23
+ # property :id, Serial
24
+ #
25
+ # attr_accessible :title, :content
26
+ # end
27
+ #
28
+ # class News
29
+ # include DataMapper::Resource
30
+ #
31
+ # property :id, Serial
32
+ # property :author_id, Integer, required: true
33
+ #
34
+ # is :translatable do
35
+ # translatable_property :title, String, required: true, unique: true
36
+ # translatable_property :content, Text, required: true
37
+ # translatable_model TranslatedNews
38
+ # translatable_origin :origin_id
39
+ # end
40
+ #
41
+ # end
42
+ #
43
+ # An example of application:
44
+ #
45
+ # news = News.create :translations => [{title: "Resent News", content: "That is where the text goes", locale: "en"}]
46
+ # news.translations.create title: "Заголовок", content: "Содержание",locale: "ru"
47
+ #
48
+ # news.content
49
+ # # => "That is where the text goes"
50
+ #
51
+ # ::I18n.locale = "ru"
52
+ # news.content
53
+ # # => "Сюди идет текст"
54
+ #
55
+ # ::I18n.locale = "de"
56
+ # news.content
57
+ # # => nil
58
+ #
59
+ # ::I18n.locale = ::I18n.default_locale
60
+ # news.content
61
+ # # => "That is where the text goes"
62
+ #
63
+ module Translatable
64
+
65
+ def is_translatable
66
+ extend DataMapper::Is::Translatable::ClassMethods
67
+ include DataMapper::Is::Translatable::InstanceMethods
68
+
69
+ translatable_define_hash
70
+ yield
71
+ translatable_register
72
+ end
73
+
74
+ module ClassMethods
75
+
76
+ protected
77
+
78
+ ###
79
+ # Fields that are translatable.
80
+ # Those fields should be defined in the original model including all the related params.
81
+ # Examples:
82
+ #
83
+ # translatable_property :title, String, required: true, unique: true
84
+ # translatable_property :content, Text
85
+ #
86
+ # NB! Will raise an error if there was no fields specified
87
+ #
88
+ def translatable_property *args
89
+ (@translatable[:properties] ||= []) << args
90
+ end
91
+
92
+ ###
93
+ # Defines model that will be treated as translation handler.
94
+ # Model can be defined as String, Symbol or Constant.
95
+ # Examples:
96
+ #
97
+ # translated_model TranslatedNews
98
+ # translated_model "TranslatedNews"
99
+ # translated_model :TranslatedNews
100
+ #
101
+ # Default: Translatable<ModelName>
102
+ #
103
+ def translatable_model model_name
104
+ @translatable[:model] = translatable_model_prepared model_name
105
+ end
106
+
107
+ ###
108
+ # Define the key that the translation will be used for belongs_to association,
109
+ # to communicate with original model
110
+ # Example:
111
+ #
112
+ # translatable_origin :news
113
+ #
114
+ # Default: :origin
115
+ #
116
+ def translatable_origin origin_key
117
+ @translatable[:origin] = translatable_origin_prepared origin_key
118
+ end
119
+
120
+ ###
121
+ # Define the key that the translation will be used for belongs_to association,
122
+ # to communicate with original model
123
+ # Example:
124
+ #
125
+ # translatable_origin :language
126
+ #
127
+ # Default: :locale
128
+ #
129
+ def translatable_locale locale_attr
130
+ @translatable[:locale] = translatable_locale_prepared locale_attr
131
+ end
132
+
133
+ ###
134
+ # Returns Model as a constant that deals with translations
135
+ def translatable_model_prepared model_name = nil
136
+ model_constant = model_name
137
+ model_constant ||= "Translatable#{self.name}"
138
+ model_constant.to_s.constantize
139
+ end
140
+
141
+
142
+ def translatable_origin_prepared origin_key = nil
143
+ origin_key || "origin"
144
+ end
145
+
146
+ def translatable_locale_prepared locale = nil
147
+ locale || "locale"
148
+ end
149
+
150
+ ###
151
+ # Define hash that contains all the translations
152
+ def translatable_define_hash
153
+ @translatable = {}
154
+ end
155
+
156
+ ###
157
+ # Handles all the registring routine, defining methods,
158
+ # properties, and everything else
159
+ def translatable_register
160
+ raise ArgumentError.new("At least one property should be defined") if [nil, []].include?(@translatable[:properties])
161
+ [:model,:origin,:locale].each { |hash_key| @translatable[hash_key] ||= send "translatable_#{hash_key}_prepared" }
162
+
163
+ translatable_register_properties_for_origin
164
+ translatable_register_properties_for_translatable
165
+ end
166
+
167
+ ###
168
+ # Handle the routine to define all th required stuff on the original maodel
169
+ def translatable_register_properties_for_origin
170
+ has Infinity, :translations, @translatable[:model].name, :child_key => [ :"#{@translatable[:origin]}_id" ]
171
+
172
+ @translatable[:properties].each do |p|
173
+ self.module_eval <<-RUBY, __FILE__, __LINE__ + 1
174
+ def #{p.first}
175
+ current_translation && current_translation.#{p.first}
176
+ end
177
+ RUBY
178
+ end
179
+ end
180
+
181
+ def translatable_register_properties_for_translatable
182
+ @translatable[:properties].each do |p|
183
+ @translatable[:model].__send__(:property, *p)
184
+ end
185
+
186
+ @translatable[:model].module_eval <<-RUBY, __FILE__, __LINE__ + 1
187
+ property :#{@translatable[:locale]}, String, :required => true
188
+ property :#{@translatable[:origin]}_id, String, :required => true
189
+
190
+ belongs_to :#{@translatable[:origin]}, "#{self.name}"
191
+
192
+ before :valid? do
193
+ # Small hack to go around form submition problem
194
+ # Without it it whould complai ther the original_id should be type of Integer
195
+ self.__send__("#{@translatable[:origin]}_id=", nil) if self.__send__("#{@translatable[:origin]}_id") == ''
196
+ end
197
+ RUBY
198
+ end
199
+ end
200
+
201
+ module InstanceMethods
202
+
203
+ protected
204
+
205
+ def translatable_locale_changed?
206
+ @translatable_locale.to_s != ::I18n.locale.to_s
207
+ end
208
+
209
+ def current_translation
210
+ if translatable_locale_changed?
211
+ @translatable_locale = ::I18n.locale.to_s
212
+ @current_translation = translations.first(:locale => @translatable_locale)
213
+ end
214
+ @current_translation
215
+ end
216
+ end
217
+ end
218
+ end
219
+ end
220
+
221
+ DataMapper::Model.append_extensions DataMapper::Is::Translatable
data/test/helper.rb ADDED
@@ -0,0 +1,27 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ if RUBY_VERSION >= '1.9.0'
4
+ require "debugger"
5
+ else
6
+ require 'ruby-debug'
7
+ end
8
+
9
+ begin
10
+ Bundler.setup(:default, :development)
11
+ rescue Bundler::BundlerError => e
12
+ $stderr.puts e.message
13
+ $stderr.puts "Run `bundle install` to install missing gems"
14
+ exit e.status_code
15
+ end
16
+ require 'test/unit'
17
+
18
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
19
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
20
+ require 'dm-translatable'
21
+
22
+ require File.expand_path("support/data_mapper", File.dirname(__FILE__))
23
+ require File.expand_path("support/database_cleaner", File.dirname(__FILE__))
24
+
25
+ class Test::Unit::TestCase
26
+ include OrmSetup
27
+ end
data/test/news.rb ADDED
@@ -0,0 +1,34 @@
1
+ require 'data_mapper'
2
+ require 'dm-translatable'
3
+
4
+ class Author
5
+ include DataMapper::Resource
6
+
7
+ property :id, Serial
8
+ property :name, String, :required => true
9
+ end
10
+
11
+ class TranslatableNews
12
+ include DataMapper::Resource
13
+
14
+ property :id, Serial
15
+
16
+ end
17
+
18
+ class News
19
+ include DataMapper::Resource
20
+
21
+ # property <name>, <type>
22
+ property :id, Serial
23
+ property :author_id, Integer
24
+ timestamps :created_at
25
+
26
+ belongs_to :author
27
+
28
+ is :translatable do
29
+ translatable_property :title, String, :required => true, :unique => true
30
+ translatable_property :content, Text, :required => true
31
+ end
32
+ end
33
+
34
+ DataMapper.auto_migrate!
@@ -0,0 +1,3 @@
1
+
2
+ DataMapper::Logger.new($stdout, :debug)
3
+ DataMapper.setup(:default, 'sqlite::memory:')
@@ -0,0 +1,13 @@
1
+ require 'database_cleaner'
2
+
3
+ DatabaseCleaner.strategy = :truncation
4
+
5
+ module OrmSetup
6
+ def before_setup
7
+ DatabaseCleaner.start
8
+ end
9
+
10
+ def after_teardown
11
+ DatabaseCleaner.clean
12
+ end
13
+ end
@@ -0,0 +1,160 @@
1
+ # encoding: utf-8
2
+ require 'helper'
3
+ require 'news'
4
+
5
+ class TestDmTranslatable < Test::Unit::TestCase
6
+
7
+ def setup
8
+ before_setup
9
+ end
10
+
11
+ def teardown
12
+ after_teardown
13
+ end
14
+
15
+ def test_translatable_hash_is_defined
16
+ th = News.instance_variable_get :@translatable
17
+
18
+ assert_kind_of Hash, th
19
+ assert th.has_key?(:properties)
20
+ end
21
+
22
+ def test_translatable_hash_has_default_model
23
+ assert_equal ::TranslatableNews, News.send(:translatable_model_prepared, 'TranslatableNews')
24
+ end
25
+
26
+ def test_translatable_assepts_constant_as_model
27
+ assert_equal ::TranslatableNews, News.send(:translatable_model_prepared, ::TranslatableNews)
28
+ end
29
+
30
+ def test_translatable_assepts_sting_as_model
31
+ assert_equal ::TranslatableNews, News.send(:translatable_model_prepared, "TranslatableNews")
32
+ end
33
+
34
+ def test_translatable_assepts_symbol_as_model
35
+ assert_equal ::TranslatableNews, News.send(:translatable_model_prepared, :TranslatableNews)
36
+ end
37
+
38
+ def test_instance_respond_to_translatable_methods
39
+ news = News.new
40
+
41
+ assert news.respond_to?(:title), "title methods is missing for News instance"
42
+ assert news.respond_to?(:content), "content methods is missing for News instance"
43
+ end
44
+
45
+ def test_translated_instance_has_translatable_methods
46
+ news = TranslatableNews.new
47
+
48
+ assert news.respond_to?(:title), "Title method is missing for TranslatableNews instance"
49
+ assert news.respond_to?(:content), "Content method is missing for TranslatableNews instance"
50
+ end
51
+
52
+ def test_translated_instance_has_relation_to_origin
53
+ news = TranslatableNews.new
54
+
55
+ assert news.respond_to?(:locale), "Locale method is missing for TranslatableNews instance"
56
+ assert news.respond_to?(:origin_id), "Origin methods is missing for TranslatableNews instance"
57
+ assert news.respond_to?(:origin), "Origin methods is missing for TranslatableNews instance"
58
+ end
59
+
60
+ def test_create_without_translation
61
+ news = News.create
62
+
63
+ assert news.saved?
64
+ assert_nil TranslatableNews.last
65
+ end
66
+
67
+ def test_create_with_translation
68
+ news = News.create :translations => [{ :title => "Заголовок", :content => "Содержание", :locale => "ru"}]
69
+
70
+ assert news.saved?
71
+
72
+ t_news = TranslatableNews.last
73
+ assert_equal news.id, t_news.origin_id.to_i
74
+ assert_equal "Заголовок", t_news.title
75
+ assert_equal "Содержание", t_news.content
76
+ assert_equal "ru", t_news.locale
77
+ end
78
+
79
+ def test_create_with_translation_with_multiple_locales
80
+ news = News.create :translations => [{ :title => "Заголовок", :content => "Содержание", :locale => "ru"},
81
+ {:title => "Resent News", :content => "That is where the text goes", :locale => "en"}]
82
+
83
+ assert news.saved?
84
+
85
+ t_news = TranslatableNews.first
86
+ assert_equal news.id, t_news.origin_id.to_i
87
+ assert_equal "Заголовок", t_news.title
88
+ assert_equal "Содержание", t_news.content
89
+ assert_equal "ru", t_news.locale
90
+
91
+ t_news = TranslatableNews.last
92
+ assert_equal news.id, t_news.origin_id.to_i
93
+ assert_equal "Resent News", t_news.title
94
+ assert_equal "That is where the text goes", t_news.content
95
+ assert_equal "en", t_news.locale
96
+ end
97
+
98
+ def test_access_of_default_translation
99
+ news = News.create :translations => [{:title => "Заголовок", :content => "Содержание", :locale => "ru"},
100
+ {:title => "Resent News", :content => "That is where the text goes", :locale => "en"}]
101
+
102
+ assert news.saved?
103
+
104
+ assert_equal "Resent News", news.title
105
+ assert_equal "That is where the text goes", news.content
106
+ end
107
+
108
+ def test_access_of_other_translation
109
+ news = News.create :translations => [{:title => "Заголовок", :content => "Содержание", :locale => "ru"},
110
+ {:title => "Resent News", :content => "That is where the text goes", :locale => "en"}]
111
+
112
+ assert news.saved?
113
+
114
+ ::I18n.locale = :ru
115
+ assert_equal "Заголовок", news.title
116
+ assert_equal "Содержание", news.content
117
+ ::I18n.locale = ::I18n.default_locale
118
+ end
119
+
120
+ def test_adding_the_translation
121
+ news = News.create :translations => [{:title => "Resent News", :content => "That is where the text goes", :locale => "en"}]
122
+
123
+ assert news.saved?
124
+
125
+ t_news = news.translations.create :title => "Заголовок", :content => "Содержание",:locale => "ru"
126
+
127
+ assert t_news.saved?
128
+ assert t_news.saved?
129
+ end
130
+
131
+ def test_getting_different_translations
132
+ news = News.create :translations => [{:title => "Resent News", :content => "That is where the text goes", :locale => "en"}]
133
+
134
+ assert news.saved?
135
+
136
+ t_news = news.translations.create :title => "Заголовок", :content => "Содержание",:locale => "ru"
137
+ assert t_news.saved?
138
+
139
+ assert_equal "Resent News", news.title
140
+ assert_equal "That is where the text goes", news.content
141
+
142
+ ::I18n.locale = :ru
143
+
144
+ assert_equal "Заголовок", news.title
145
+ assert_equal "Содержание", news.content
146
+ ::I18n.locale = ::I18n.default_locale
147
+ end
148
+
149
+ def test_access_of_other_translation
150
+ news = News.create :translations => [{:title => "Заголовок", :content => "Содержание", :locale => "ru"},
151
+ {:title => "Resent News", :content => "That is where the text goes", :locale => "en"}]
152
+
153
+ assert news.saved?
154
+
155
+ ::I18n.locale = :de
156
+ assert_nil news.title
157
+ assert_nil news.content
158
+ ::I18n.locale = ::I18n.default_locale
159
+ end
160
+ end
metadata ADDED
@@ -0,0 +1,199 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dm-translatable
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - E-Max
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-08-14 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: data_mapper
16
+ requirement: &77385520 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *77385520
25
+ - !ruby/object:Gem::Dependency
26
+ name: i18n
27
+ requirement: &77385160 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *77385160
36
+ - !ruby/object:Gem::Dependency
37
+ name: test-spec
38
+ requirement: &77384830 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *77384830
47
+ - !ruby/object:Gem::Dependency
48
+ name: yard
49
+ requirement: &77384510 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 0.6.0
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *77384510
58
+ - !ruby/object:Gem::Dependency
59
+ name: bundler
60
+ requirement: &77384110 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ~>
64
+ - !ruby/object:Gem::Version
65
+ version: 1.0.0
66
+ type: :development
67
+ prerelease: false
68
+ version_requirements: *77384110
69
+ - !ruby/object:Gem::Dependency
70
+ name: jeweler
71
+ requirement: &77383810 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ~>
75
+ - !ruby/object:Gem::Version
76
+ version: 1.6.4
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: *77383810
80
+ - !ruby/object:Gem::Dependency
81
+ name: debugger
82
+ requirement: &77383340 !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ~>
86
+ - !ruby/object:Gem::Version
87
+ version: 1.1.3
88
+ type: :development
89
+ prerelease: false
90
+ version_requirements: *77383340
91
+ - !ruby/object:Gem::Dependency
92
+ name: simplecov
93
+ requirement: &77383040 !ruby/object:Gem::Requirement
94
+ none: false
95
+ requirements:
96
+ - - ~>
97
+ - !ruby/object:Gem::Version
98
+ version: 0.6.4
99
+ type: :development
100
+ prerelease: false
101
+ version_requirements: *77383040
102
+ - !ruby/object:Gem::Dependency
103
+ name: ruby-debug
104
+ requirement: &77382780 !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ type: :development
111
+ prerelease: false
112
+ version_requirements: *77382780
113
+ - !ruby/object:Gem::Dependency
114
+ name: rcov
115
+ requirement: &77382500 !ruby/object:Gem::Requirement
116
+ none: false
117
+ requirements:
118
+ - - ~>
119
+ - !ruby/object:Gem::Version
120
+ version: 1.0.0
121
+ type: :development
122
+ prerelease: false
123
+ version_requirements: *77382500
124
+ - !ruby/object:Gem::Dependency
125
+ name: database_cleaner
126
+ requirement: &77382230 !ruby/object:Gem::Requirement
127
+ none: false
128
+ requirements:
129
+ - - ~>
130
+ - !ruby/object:Gem::Version
131
+ version: 0.7.2
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: *77382230
135
+ - !ruby/object:Gem::Dependency
136
+ name: dm-sqlite-adapter
137
+ requirement: &77381940 !ruby/object:Gem::Requirement
138
+ none: false
139
+ requirements:
140
+ - - ! '>='
141
+ - !ruby/object:Gem::Version
142
+ version: '0'
143
+ type: :development
144
+ prerelease: false
145
+ version_requirements: *77381940
146
+ description: This game was build to make whole proccess of working with translation
147
+ for DM to be almost invisble. That was THE AIM.
148
+ email: max@studentify.nl
149
+ executables: []
150
+ extensions: []
151
+ extra_rdoc_files:
152
+ - LICENSE.txt
153
+ - README.rdoc
154
+ files:
155
+ - .document
156
+ - .rvmrc
157
+ - .travis.yml
158
+ - Gemfile
159
+ - Gemfile.lock
160
+ - LICENSE.txt
161
+ - README.rdoc
162
+ - Rakefile
163
+ - VERSION
164
+ - dm-translatable.gemspec
165
+ - lib/dm-translatable.rb
166
+ - test/helper.rb
167
+ - test/news.rb
168
+ - test/support/data_mapper.rb
169
+ - test/support/database_cleaner.rb
170
+ - test/test_dm-translatable.rb
171
+ homepage: http://github.com/kot-begemot/dm-translatable
172
+ licenses:
173
+ - MIT
174
+ post_install_message:
175
+ rdoc_options: []
176
+ require_paths:
177
+ - lib
178
+ required_ruby_version: !ruby/object:Gem::Requirement
179
+ none: false
180
+ requirements:
181
+ - - ! '>='
182
+ - !ruby/object:Gem::Version
183
+ version: '0'
184
+ segments:
185
+ - 0
186
+ hash: -913307725
187
+ required_rubygems_version: !ruby/object:Gem::Requirement
188
+ none: false
189
+ requirements:
190
+ - - ! '>='
191
+ - !ruby/object:Gem::Version
192
+ version: '0'
193
+ requirements: []
194
+ rubyforge_project:
195
+ rubygems_version: 1.8.10
196
+ signing_key:
197
+ specification_version: 3
198
+ summary: An esay way to manage the translations for datamapper
199
+ test_files: []