teonimesic-translated_attributes 0.5.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,2 @@
1
+ pkg/*
2
+ *.gemspec
@@ -0,0 +1,58 @@
1
+ This is an adaptation on Michael Grosser's translated attributes, but lightly adapted for rails 3 and my own needs.
2
+
3
+ Rails plugin/ActiveRecord gem that creates 'virtual' attributes, which can be added on the fly without overhead or migrations, while storing all the data in a never-changing translations table.
4
+ This keeps the attatched model light and allows to add/remove fields on the fly without migrations.
5
+
6
+ Validations work like normal with current field (e.g. title) or any translation (e.g. title_in_en)
7
+
8
+ Usage
9
+ =====
10
+ - Add 'gem teonimesic-translated_attributes to Gemfile'
11
+ - run 'rails g translated_attributes' and run migration
12
+
13
+ Adding attributes:
14
+ class Product < ActiveRecord::Base
15
+ translated_attributes :description, :title, :additional_info
16
+ end
17
+
18
+ Setting / getting
19
+ #getter
20
+ product.title -> 'Hello' #when I18n.locale is :en
21
+ product.title_in_fr -> 'Bonyour'
22
+ product.title_in_de -> 'Hallo'
23
+
24
+ #setter
25
+ product.title = 'Simple setting' #sets title_in_en when I18n.locale == :en
26
+ product.title_in_de = 'Spezifisches speichern'
27
+
28
+ #generic setter/getter
29
+ product.set_title('Specific setting', :en)
30
+ product.get_title(:en) -> 'Specific setting'
31
+
32
+
33
+ Usage with saving works exactly like normal saving, e.g. new/create/update_attributes...
34
+ Product.new(:title_in_en=>'Hello').save!
35
+ product.update_attribute(:title, 'Goodbye')
36
+
37
+ Or you can use the :index option on FormBuilder's' methods for the following usage: (works with new/create/update_attributes as well)
38
+ Product.new(
39
+ en: {title: 'Ruby', description: 'A very cool programing language', additional_info: 'It's free!'}
40
+ pt: {title: 'Ruby', description: 'Uma linguagem de programação muito legal', additional_info: 'É gratis!'}
41
+ )
42
+
43
+ - Translations are stored on 'save'
44
+ - blank translations are NOT stored
45
+ - translations are accessable via .translations or as hash via .translated_attributes
46
+
47
+ Options
48
+ =======
49
+ translated_attributes :title, :heading,
50
+ :table_name => 'user_translations', #default is translations
51
+ :nil_to_blank => true, #return unfound translations as blank strings ('') instead of nil (default false),
52
+ :translatable_name => 'translated' #name of the associated translatable (Product has_many :translations a Translation belongs_to XXX), default is :translatable
53
+ Authors
54
+ ======
55
+ [Michael Grosser](http://pragmatig.wordpress.com) and [Stefano Diem Benatti](http://heavenstudio.com.br)
56
+ grosser.michael@gmail.com, stefano.diem@gmail.com
57
+ Hereby placed under public domain, do what you want, just do not hold us accountable...
58
+ Also i would like to thanks Michael Grosser for his work on the original gem, it has the best API for database translations that i found for Ruby/Rails.
@@ -0,0 +1,24 @@
1
+ require 'rake'
2
+ require 'rspec/core/rake_task'
3
+
4
+ begin
5
+ username = 'teonimesic'
6
+ project_name = 'translated_attributes'
7
+ require 'jeweler'
8
+ Jeweler::Tasks.new do |gem|
9
+ gem.name = "#{username}-#{project_name}"
10
+ gem.summary = "An adaptation of grossers's translatable attributes"
11
+ gem.email = "stefano.diem@gmail.com"
12
+ gem.homepage = "http://github.com/teonimesic/#{project_name}"
13
+ gem.authors = ["Michael Grosser","Stefano Diem Benatti"]
14
+ gem.add_dependency 'activerecord'
15
+ gem.add_dependency 'rspec-core', '>= 2.0.0.beta.13'
16
+ end
17
+
18
+ Jeweler::GemcutterTasks.new
19
+ rescue LoadError
20
+ puts "Jeweler, or one of its dependencies, is not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
21
+ end
22
+
23
+ RSpec::Core::RakeTask.new(:spec)
24
+ task :default => :spec
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.5.7
data/init.rb ADDED
@@ -0,0 +1,2 @@
1
+ #Needed to load when used as Rails plugin
2
+ require 'translated_attributes'
@@ -0,0 +1,8 @@
1
+ Description:
2
+ Generates the migration file for TranslatedAttributes.
3
+
4
+ Example:
5
+ rails generate translated_attributes
6
+
7
+ This will create:
8
+ db/migration/<migration step>_add_translations.rb
@@ -0,0 +1,18 @@
1
+ class AddTranslations < ActiveRecord::Migration
2
+ def self.up
3
+ #you can remove the limit/null constrains
4
+ #this is simply my recommended way of setting things up (save + limits needed storage space)
5
+ create_table :translations do |t|
6
+ t.integer :translatable_id, :null=>false
7
+ t.string :translatable_type, :limit=>40, :null=>false
8
+ t.string :language, :limit=>2, :null=>false
9
+ t.string :attr, :limit=>40, :null=>false
10
+ t.text :text, :null=>false
11
+ end
12
+ add_index :translations, [:translatable_id, :translatable_type]
13
+ end
14
+
15
+ def self.down
16
+ drop_table :translations
17
+ end
18
+ end
@@ -0,0 +1,15 @@
1
+ require 'rails/generators/migration'
2
+
3
+ class TranslatedAttributesGenerator < Rails::Generators::Base
4
+ include Rails::Generators::Migration
5
+
6
+ source_root File.expand_path('../templates', __FILE__)
7
+
8
+ def self.next_migration_number(dirname)
9
+ Time.now.strftime("%Y%m%d%H%M%S")
10
+ end
11
+
12
+ def create_migration
13
+ migration_template "#{self.class.source_root}/migration.rb", File.join('db/migrate', "add_translations.rb")
14
+ end
15
+ end
@@ -0,0 +1,175 @@
1
+ module TranslatedAttributes
2
+ module ClassMethods
3
+ # translated_attributes :title, :description, :table_name=>'my_translations'
4
+ def translated_attributes(*args)
5
+ #store options
6
+ cattr_accessor :translated_attributes_options
7
+ options = args.extract_options! || {}
8
+ self.translated_attributes_options = options.merge(:fields=>args.map(&:to_sym))
9
+
10
+ #create translations class
11
+ table_name = options[:table_name] || :translations
12
+ class_name = table_name.to_s.classify
13
+
14
+ associated = options[:translatable_name] || :translatable
15
+ begin
16
+ klass = Object.const_get(class_name)
17
+ rescue
18
+ klass = Class.new(ActiveRecord::Base)
19
+ Object.const_set(class_name, klass)
20
+ klass.set_table_name table_name
21
+ klass.belongs_to associated, :polymorphic => true
22
+ end
23
+
24
+ #set translations
25
+ has_many :translations, :as => associated, :dependent => :delete_all, :class_name=>klass.name
26
+
27
+ #include methods
28
+ include TranslatedAttributes::InstanceMethods
29
+ end
30
+ end
31
+
32
+ module InstanceMethods
33
+ def self.included(base)
34
+ fields = base.translated_attributes_options[:fields]
35
+ fields.each do |field|
36
+ base.class_eval <<-GETTER_AND_SETTER
37
+ def get_#{field}(locale=nil)
38
+ get_translated_attribute(locale, :#{field})
39
+ end
40
+
41
+ def set_#{field}(value, locale=I18n.locale)
42
+ set_translated_attribute(locale, :#{field}, value)
43
+ end
44
+
45
+ #generic aliases (and since e.g. title=(a,b) would not be possible)
46
+ alias #{field} get_#{field}
47
+ alias #{field}= set_#{field}
48
+ GETTER_AND_SETTER
49
+ end
50
+
51
+ base.after_save :store_translated_attributes
52
+ end
53
+
54
+ def attributes=(new_attributes, *args)
55
+ if I18n.available_locales.any?{|locale| new_attributes.stringify_keys.include? locale.to_s }
56
+ non_serialized_attributes = new_attributes
57
+ I18n.available_locales.each do |l|
58
+ new_attributes = get_language_attributes(l,non_serialized_attributes)
59
+ self.class.language(l){ super }
60
+ end
61
+ else
62
+ super
63
+ end
64
+ end
65
+
66
+ def get_language_attributes(lang, params)
67
+ local_params = {}
68
+ if (params.include?(lang) || params.include?(lang.to_s) ) && I18n.available_locales.include?(lang.to_sym)
69
+ local_params = params.stringify_keys[lang.to_s]
70
+ end
71
+ params.reject{|k,v| I18n.available_locales.include? k.to_sym }.merge(local_params)
72
+ end
73
+
74
+ def get_translated_attribute(locale, field)
75
+ text = if locale
76
+ translated_attributes_for(locale)[field]
77
+ else
78
+ #try to find anything...
79
+ #current, english, anything else
80
+ found = translated_attributes_for(I18n.locale)[field] || translated_attributes_for(:en)[field]
81
+ if found
82
+ found
83
+ else
84
+ found = translated_attributes.detect{|locale, attributes| not attributes[field].blank?}
85
+ found ? found[1][field] : nil
86
+ end
87
+ end
88
+
89
+ if self.class.translated_attributes_options[:nil_to_blank]
90
+ text || ''
91
+ else
92
+ text
93
+ end
94
+ end
95
+
96
+ def set_translated_attribute(locale, field, value)
97
+ old_value = translated_attributes_for(locale)[field]
98
+ return if old_value == value
99
+ changed_attributes.merge!("#{field}_in_#{locale}" => old_value)
100
+ translated_attributes_for(locale)[field] = value
101
+ @translated_attributes_changed = true
102
+ end
103
+
104
+ def translated_attributes
105
+ return @translated_attributes if @translated_attributes
106
+ merge_db_translations_with_instance_variable
107
+ @translated_attributes ||= {}.with_indifferent_access
108
+ end
109
+
110
+ def translated_attributes= hash
111
+ @db_translations_merged = false #overwrite what we set here
112
+ @translated_attributes_changed = true #store changes we made
113
+ @translated_attributes = hash.with_indifferent_access
114
+ end
115
+
116
+ def respond_to?(name, *args)
117
+ return true if parse_translated_attribute_method(name)
118
+ super
119
+ end
120
+
121
+ def method_missing(name, *args)
122
+ field, locale = parse_translated_attribute_method(name)
123
+ return super unless field
124
+ if name.to_s.include? '=' #is setter ?
125
+ send("set_#{field}", args[0], locale)
126
+ else
127
+ send("get_#{field}", locale)
128
+ end
129
+ end
130
+
131
+ protected
132
+
133
+ def store_translated_attributes
134
+ return true unless @translated_attributes_changed
135
+ translations.delete_all
136
+ @translated_attributes.each do |locale, attributes|
137
+ attributes.each do |attribute, value|
138
+ next if value.blank?
139
+ next unless self.class.translated_attributes_options[:fields].include? attribute.to_sym
140
+ translations.create!(:attr=>attribute, :text=>value, :language=>locale)
141
+ end
142
+ end
143
+ @translated_attributes_changed = false
144
+ end
145
+
146
+ private
147
+
148
+ def merge_db_translations_with_instance_variable
149
+ return if new_record? or @db_translations_merged
150
+ @db_translations_merged = true
151
+ translations.each do |t|
152
+ translated_attributes_for(t.language)[t.attr] = t.text
153
+ end
154
+ end
155
+
156
+ def parse_translated_attribute_method(name)
157
+ return false if name.to_s !~ /^([a-zA-Z_]+)_in_([a-z]{2})[=]?$/
158
+ field = $1; locale = $2
159
+ return false unless is_translated_attribute?(field)
160
+ return field, locale
161
+ end
162
+
163
+ def is_translated_attribute?(method_name)
164
+ fields = self.class.translated_attributes_options[:fields]
165
+ fields.include? method_name.sub('=','').to_sym
166
+ end
167
+
168
+ def translated_attributes_for(locale)
169
+ translated_attributes[locale] ||= {}.with_indifferent_access
170
+ translated_attributes[locale]
171
+ end
172
+ end
173
+ end
174
+
175
+ ActiveRecord::Base.send :extend, TranslatedAttributes::ClassMethods
@@ -0,0 +1,42 @@
1
+ require_relative 'spec_helper'
2
+
3
+ describe 'Integration' do
4
+ before do
5
+ Translation.delete_all
6
+ UserTranslation.delete_all
7
+ end
8
+
9
+ it "manages different translations appropriatly" do
10
+ User.create(:name_in_en=>'User1NameEn', :name_in_de=>'User1NameDe')
11
+ User.create(:name_in_en=>'User2NameEn', :name_in_fr=>'User2NameFr')
12
+ Product.create(:title=>'Product1TitleEn', :title_in_de=>'Product1TitleDe')
13
+
14
+ User.first.translated_attributes = {}
15
+ u = User.last
16
+ u.translated_attributes = {:fr=>{:name=>'User1NameFr'}}
17
+ u.save!
18
+
19
+ UserTranslation.count.should == 3
20
+ Translation.count.should == 2
21
+ User.last.name.should == 'User1NameFr'
22
+ end
23
+
24
+ it "cleans up translations" do
25
+ User.create!(:name=>'u1')
26
+ Product.create!(:title=>'p1',:description=>'d1')
27
+ Product.create!(:title=>'p2')
28
+
29
+ Translation.count.should == 3
30
+ UserTranslation.count.should == 1
31
+
32
+ Product.destroy_all
33
+
34
+ Translation.count.should == 0
35
+ UserTranslation.count.should == 1
36
+
37
+ User.destroy_all
38
+
39
+ Translation.count.should == 0
40
+ UserTranslation.count.should == 0
41
+ end
42
+ end
@@ -0,0 +1,31 @@
1
+ ActiveRecord::Schema.define(:version => 1) do
2
+ create_table :users do |t|
3
+ end
4
+
5
+ create_table :products do |t|
6
+ end
7
+
8
+ %w[translations user_translations].each do |table|
9
+ create_table table do |t|
10
+ t.integer :translatable_id, :null=>false
11
+ t.string :translatable_type, :limit=>40, :null=>false
12
+ t.string :language, :limit=>2, :null=>false
13
+ t.string :attr, :limit=>40, :null=>false
14
+ t.text :text, :null=>false
15
+ end
16
+ end
17
+ end
18
+
19
+ #create model
20
+ class User < ActiveRecord::Base
21
+ translated_attributes :name, :table_name=>:user_translations, :nil_to_blank=>true
22
+ end
23
+
24
+ class Shop < ActiveRecord::Base
25
+ set_table_name :products
26
+ translated_attributes :shop_name
27
+ end
28
+
29
+ class Product < ActiveRecord::Base
30
+ translated_attributes :title, :description
31
+ end
@@ -0,0 +1,17 @@
1
+ # ---- requirements
2
+ require 'rubygems'
3
+ require 'rspec'
4
+ require 'active_record'
5
+
6
+ $:.unshift File.expand_path('../lib', __FILE__)
7
+
8
+ # ---- setup environment/plugin
9
+ ActiveRecord::Base.establish_connection({
10
+ :adapter => "sqlite3",
11
+ :database => ":memory:",
12
+ })
13
+
14
+ #ActiveRecord::Base.logger = Logger.new(STDOUT)
15
+
16
+ require File.expand_path("../init", File.dirname(__FILE__))
17
+
@@ -0,0 +1,305 @@
1
+ require_relative 'spec_helper'
2
+ require_relative 'models'
3
+
4
+ describe 'Translated attributes' do
5
+ before do
6
+ I18n.locale = :en
7
+ end
8
+
9
+ describe 'caching' do
10
+ it "is nil when nothing is set" do
11
+ Product.new.title.should == nil
12
+ Product.new.description.should == nil
13
+ end
14
+
15
+ it 'can be set' do
16
+ p = Product.new
17
+ p.title = 'abc'
18
+ p.title.should == 'abc'
19
+ end
20
+
21
+ it 'can be overwritten' do
22
+ p = Product.new
23
+ p.title = 'abc'
24
+ p.title = 'def'
25
+ p.title.should == 'def'
26
+ end
27
+
28
+ it "ca be unset" do
29
+ p = Product.new
30
+ p.title = 'abc'
31
+ p.title = nil
32
+ p.title.should == nil
33
+ end
34
+
35
+ it "sets the current language" do
36
+ p = Product.new
37
+ p.title = 'abc'
38
+ p.title_in_en.should == 'abc'
39
+ end
40
+
41
+ it "can be set in different languages" do
42
+ p = Product.new
43
+ p.title = 'abc'
44
+ p.title_in_de.should == nil
45
+ I18n.locale = :de
46
+ p.title = 'bcd'
47
+ p.title_in_de.should == 'bcd'
48
+ end
49
+
50
+ it "returns current language when current can be found" do
51
+ I18n.locale = :de
52
+ p = Product.new
53
+ p.title_in_de = 'abc'
54
+ p.title_in_en = 'def'
55
+ p.title.should == 'abc'
56
+ end
57
+
58
+ it "returns english translation when current cannot be found" do
59
+ I18n.locale = :de
60
+ p = Product.new
61
+ p.title_in_en = 'abc'
62
+ p.title.should == 'abc'
63
+ end
64
+
65
+ it "returns any translation when current and english cannot be found" do
66
+ I18n.locale = :fr
67
+ p = Product.new
68
+ p.title_in_de = 'abc'
69
+ p.title.should == 'abc'
70
+ end
71
+ end
72
+
73
+ describe 'storing' do
74
+ it "stores nothing when nothing was set" do
75
+ lambda{ Product.create! }.should_not change(Translation, :count)
76
+ Product.last.title.should == nil
77
+ end
78
+
79
+ it "stores column as translation on save" do
80
+ lambda{ Product.create!(:title=>'x') }.should change(Translation, :count).by(+1)
81
+ end
82
+
83
+ it "stores nothing when blank was set" do
84
+ lambda{ Product.create! :title=>' ' }.should_not change(Translation, :count)
85
+ Product.last.title.should == nil
86
+ end
87
+
88
+ it "creates no translation when validations fail" do
89
+ p = Product.new :title=>'xxx'
90
+ p.should_receive(:valid?).and_return false
91
+ lambda{ p.save }.should_not change(Translation, :count)
92
+ end
93
+
94
+ it "is stored after save" do
95
+ p = Product.create!(:title=>'1')
96
+ p.title = '2'
97
+ p.save!
98
+ Product.last.title.should == '2'
99
+ end
100
+
101
+ it "does not create unecessary translations on change" do
102
+ p = Product.create!(:title=>'1')
103
+ lambda{
104
+ p.title = '2'
105
+ p.save!
106
+ }.should_not change(Translation, :count)
107
+ end
108
+
109
+ it "does not update translations when nothing changed" do
110
+ p = Product.create!(:title=>'xx')
111
+ p.title = 'xx'
112
+ lambda{ p.save }.should_not change{Translation.last.id}
113
+ end
114
+
115
+ it "works through update_attribute" do
116
+ p = Product.create!(:title=>'xx', :description=>'dd')
117
+ p.update_attribute(:title, 'yy')
118
+ Product.last.title.should == 'yy'
119
+ Product.last.description.should == 'dd'
120
+ end
121
+
122
+ it "works through update_attributes" do
123
+ p = Product.create!(:title=>'xx', :description=>'dd')
124
+ p.update_attributes(:title=>'yy')
125
+ Product.last.title.should == 'yy'
126
+ Product.last.description.should == 'dd'
127
+ end
128
+
129
+ it "works through attributes=" do
130
+ p = Product.create!(:title=>'xx', :description=>'dd')
131
+ p.attributes = {:title=>'yy'}
132
+ p.save!
133
+ Product.last.title.should == 'yy'
134
+ Product.last.description.should == 'dd'
135
+ end
136
+
137
+ it "loads translations once" do
138
+ Product.create!(:title=>'xx', :description=>'yy')
139
+ p = Product.last
140
+ p.should_receive(:translations).and_return []
141
+ p.title.should == nil
142
+ p.description.should == nil
143
+ end
144
+
145
+ it "deletes the existing translation when changing to blank" do
146
+ p = Product.create!(:title=>'1')
147
+ lambda{
148
+ p.title = ''
149
+ p.save!
150
+ }.should change(Translation, :count).by(-1)
151
+ Product.last.title.should == nil
152
+ end
153
+
154
+ it "can store multiple translations at once" do
155
+ lambda{
156
+ Product.create!(:title_in_de=>'Hallo', :title_in_en=>'Hello')
157
+ }.should change(Translation, :count).by(+2)
158
+ Product.last.title_in_de.should == 'Hallo'
159
+ Product.last.title.should == 'Hello'
160
+ end
161
+
162
+ it "deletes translations when translatable is destroyed" do
163
+ Translation.delete_all
164
+ Product.create!(:title=>'t1')
165
+ Product.create!(:title=>'t2',:description=>'d2')
166
+ Translation.count.should == 3
167
+
168
+ Product.last.destroy
169
+
170
+ Translation.count.should == 1
171
+ Translation.first.text.should == 't1'
172
+ end
173
+
174
+ it "is not influenced by reloading" do
175
+ p = Product.create!(:title=>'t1', :description=>'d1')
176
+ p.title = 't2'
177
+ p.reload
178
+ p.description = 'd2'
179
+ p.save!
180
+ Product.last.title.should == 't2'
181
+ Product.last.description.should == 'd2'
182
+ end
183
+ end
184
+
185
+ describe 'classes' do
186
+ it "does not define them twice" do
187
+ Translation.instance_variable_set '@test', 1
188
+ class XXX < ActiveRecord::Base
189
+ set_table_name :products
190
+ translated_attributes :name
191
+ end
192
+ Translation.instance_variable_get('@test').should == 1
193
+ end
194
+
195
+ it "stores options seperately" do
196
+ Shop.translated_attributes_options[:fields].should_not == Product.translated_attributes_options[:fields]
197
+ end
198
+ end
199
+
200
+ describe 'different tables' do
201
+ it "creates the model for each table_name" do
202
+ Translation
203
+ UserTranslation
204
+ end
205
+
206
+ it "creates translations in set table" do
207
+ Product.create!(:title=>'yyy')
208
+ Translation.last.text.should == 'yyy'
209
+
210
+ User.create!(:name=>'xxx')
211
+ UserTranslation.last.text.should == 'xxx'
212
+ end
213
+ end
214
+
215
+ describe 'nil to blank' do
216
+ it "converts all unfound fields to blank" do
217
+ User.new.name.should == ''
218
+ end
219
+ end
220
+
221
+ describe :translated_attributes do
222
+ it "is a empty hash when nothing was set" do
223
+ Product.new.translated_attributes.should == {}
224
+ end
225
+
226
+ it "can be modified" do
227
+ Product.new.translated_attributes.should_not be_frozen
228
+ end
229
+ end
230
+
231
+ describe :translated_attriutes= do
232
+ it "stores all translations" do
233
+ p = Product.create!
234
+ p.translated_attributes = {:de=>{:title=>'de title',:description=>'de descr'}}
235
+ p.title_in_de.should == 'de title'
236
+ p.description_in_de.should == 'de descr'
237
+ p.title_in_en.should == nil
238
+ end
239
+
240
+ it "overwrites existing translations" do
241
+ p = Product.create!(:title=>'en title')
242
+ p.translated_attributes = {:de=>{:title=>'de title',:description=>'de descr'}}
243
+ p.title_in_de.should == 'de title'
244
+ p.description_in_de.should == 'de descr'
245
+ p.title_in_en.should == nil
246
+ end
247
+
248
+ it "stores and overwrites on save" do
249
+ p = Product.create!(:title=>'en title')
250
+ p.translated_attributes = {:de=>{:title=>'de title',:description=>'de descr'}}
251
+ p.save!
252
+ Product.last.title.should == 'de title'
253
+ Product.last.title_in_de.should == 'de title'
254
+ end
255
+
256
+ it "does not store unknown attributes" do
257
+ p = Product.new
258
+ p.translated_attributes = {:de=>{:xxx=>'de title',:description=>'de descr'}}
259
+ lambda{
260
+ p.save!
261
+ }.should change(Translation, :count).by(+1)
262
+ end
263
+
264
+ it "does not alter the given hash" do
265
+ p = Product.create!(:title=>'en title')
266
+ hash = {:de=>{:title=>'de title',:description=>'de descr'}}
267
+ p.translated_attributes = hash
268
+ hash['de'].should == nil #not converted to indifferent access
269
+ hash[:de][:title].should == 'de title' #still has all attributes
270
+ end
271
+
272
+ it "stores given hash indifferent" do
273
+ p = Product.new
274
+ p.translated_attributes = {'de'=>{'title'=>'title de'}}
275
+ p.translated_attributes[:de][:title].should == 'title de'
276
+ end
277
+ end
278
+
279
+ describe :method_missing do
280
+ it "ignores calls without _in_" do
281
+ lambda{Product.new.title_xxx}.should raise_error
282
+ end
283
+ it "ignores calls with a non-supported attribute" do
284
+ lambda{Product.new.foo_in_de}.should raise_error
285
+ end
286
+ end
287
+
288
+ describe :respond_to? do
289
+ it "ignores calls without _in_" do
290
+ Product.new.respond_to?(:title_xx_xx).should == false
291
+ end
292
+
293
+ it "ignores calls with a non-supported attribute" do
294
+ Product.new.respond_to?(:foo_in_de).should == false
295
+ end
296
+
297
+ it "responds to translated column" do
298
+ Product.new.respond_to?(:title_in_en).should == true
299
+ end
300
+
301
+ it "responds to normal methods" do
302
+ Product.new.respond_to?(:new_record?).should == true
303
+ end
304
+ end
305
+ end
metadata ADDED
@@ -0,0 +1,109 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: teonimesic-translated_attributes
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 5
8
+ - 7
9
+ version: 0.5.7
10
+ platform: ruby
11
+ authors:
12
+ - Michael Grosser
13
+ - Stefano Diem Benatti
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-07-12 00:00:00 -03:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: activerecord
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ segments:
30
+ - 0
31
+ version: "0"
32
+ type: :runtime
33
+ version_requirements: *id001
34
+ - !ruby/object:Gem::Dependency
35
+ name: rspec-core
36
+ prerelease: false
37
+ requirement: &id002 !ruby/object:Gem::Requirement
38
+ none: false
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ segments:
43
+ - 2
44
+ - 0
45
+ - 0
46
+ - beta
47
+ - 13
48
+ version: 2.0.0.beta.13
49
+ type: :runtime
50
+ version_requirements: *id002
51
+ description:
52
+ email: stefano.diem@gmail.com
53
+ executables: []
54
+
55
+ extensions: []
56
+
57
+ extra_rdoc_files:
58
+ - README.markdown
59
+ files:
60
+ - .gitignore
61
+ - README.markdown
62
+ - Rakefile
63
+ - VERSION
64
+ - init.rb
65
+ - lib/generators/translated_attributes/USAGE
66
+ - lib/generators/translated_attributes/templates/migration.rb
67
+ - lib/generators/translated_attributes/translated_attributes_generator.rb
68
+ - lib/translated_attributes.rb
69
+ - spec/integration_spec.rb
70
+ - spec/models.rb
71
+ - spec/spec_helper.rb
72
+ - spec/translated_attributes_spec.rb
73
+ has_rdoc: true
74
+ homepage: http://github.com/teonimesic/translated_attributes
75
+ licenses: []
76
+
77
+ post_install_message:
78
+ rdoc_options:
79
+ - --charset=UTF-8
80
+ require_paths:
81
+ - lib
82
+ required_ruby_version: !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ segments:
88
+ - 0
89
+ version: "0"
90
+ required_rubygems_version: !ruby/object:Gem::Requirement
91
+ none: false
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ segments:
96
+ - 0
97
+ version: "0"
98
+ requirements: []
99
+
100
+ rubyforge_project:
101
+ rubygems_version: 1.3.7
102
+ signing_key:
103
+ specification_version: 3
104
+ summary: An adaptation of grossers's translatable attributes
105
+ test_files:
106
+ - spec/integration_spec.rb
107
+ - spec/models.rb
108
+ - spec/spec_helper.rb
109
+ - spec/translated_attributes_spec.rb