teonimesic-translated_attributes 0.5.7

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.
@@ -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