translatable_attributes 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ **/.*.sw?
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in translatable_attributes.gemspec
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1,4 @@
1
+ Translatable Attributes
2
+ =======================
3
+
4
+ Works with I18n to allow you to magically translate an attribute of an object.
data/Rakefile ADDED
@@ -0,0 +1,18 @@
1
+ require 'bundler'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+
5
+ Bundler::GemHelper.install_tasks
6
+
7
+ Rake::TestTask.new do |t|
8
+ t.libs << 'lib'
9
+ t.pattern = "test/**/*_test.rb"
10
+ t.verbose = false
11
+ end
12
+
13
+ Rake::RDocTask.new do |t|
14
+ t.main = "README.md"
15
+ t.rdoc_files.include "README.md", "lib/**/*.lib"
16
+ end
17
+
18
+ task :default => :test
@@ -0,0 +1,83 @@
1
+ require 'rubygems'
2
+ require 'i18n/active_record'
3
+ # Including this module into your model will allow you to add arbitrary
4
+ # attributes whose values are persisted in multiple languages in the database.
5
+ #
6
+ # For example, supposing you have an online shop, and you need to store the
7
+ # description of products in English and German. First, you should ensure that
8
+ # I18n.available_locales returns [:en, :de] (at least).
9
+ #
10
+ # class Product
11
+ # translatable_attribute_accessor :description
12
+ # end
13
+ #
14
+ # product = Product.create => a new Product#123
15
+ # product.description_en = "A thing"
16
+ # product.description_de = "Ein Ding"
17
+ #
18
+ # The descriptions will be persisted in the translations table (or whatever
19
+ # your I18n::Backend::ActiveRecord is using - see that gem for more info),
20
+ # with the key 'product.descriptions.123'.
21
+ module TranslatableAttributes
22
+ def self.included(mod)
23
+ mod.send(:extend, ClassMethods)
24
+ mod.send(:include, InstanceMethods)
25
+ mod.send(:after_save, :save_translatable_attributes)
26
+ end
27
+
28
+ module ClassMethods
29
+ # Adds a reader and writer for each available locale for each of the given
30
+ # attributes. For example (and assuming that the available locales are :en
31
+ # and :de):
32
+ #
33
+ # I18n.available_locales # => [:en, :de]
34
+ #
35
+ # class Post < ActiveModel::Base
36
+ # translatable_attribute_accessor :title, :body
37
+ # end
38
+ #
39
+ # This creates the methods `title_en`, `title_en=`, `title_de`,
40
+ # `title_de=`, `body_en`, `body_en=`, `body_de` and `body_de=`
41
+ def translatable_attribute_accessor(*attributes)
42
+ attributes.each do |attr|
43
+ I18n.available_locales.map(&:to_s).each do |locale|
44
+ class_eval do
45
+ name = "#{attr.to_s}_#{locale.gsub('-', '_').downcase}"
46
+
47
+ define_method name do
48
+ translatable_attribute_record(attr, locale).value
49
+ end
50
+
51
+ define_method "#{name}=" do |value|
52
+ translatable_attribute_record(attr, locale).value = value
53
+ end
54
+
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+
61
+ module InstanceMethods
62
+ def save_translatable_attributes
63
+ @translatable_attribute_records.each do |locale, records|
64
+ records.each do |attr, record|
65
+ record.key = translatable_attribute_record_key(attr)
66
+ record.save!
67
+ end
68
+ end unless @translatable_attribute_records.nil?
69
+ end
70
+
71
+ def translatable_attribute_record_key(attr)
72
+ "#{self.class.name.demodulize.tableize}.#{to_param}.#{attr}"
73
+ end
74
+
75
+ def translatable_attribute_record(attr, locale)
76
+ key = translatable_attribute_record_key(attr)
77
+ @translatable_attribute_records ||= {}
78
+ @translatable_attribute_records[locale] ||= {}
79
+ @translatable_attribute_records[locale][attr] ||= I18n::Backend::ActiveRecord::Translation.locale(locale).find_by_key(key)
80
+ @translatable_attribute_records[locale][attr] ||= I18n::Backend::ActiveRecord::Translation.locale(locale).build
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,3 @@
1
+ module TranslatableAttributes
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,79 @@
1
+ $: << File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ require 'test/unit'
3
+ require 'translatable_attributes'
4
+
5
+ class TranslatableAttributesTest < Test::Unit::TestCase
6
+ class Model < ActiveRecord::Base; end
7
+
8
+ def setup
9
+ ActiveRecord::Base.establish_connection(
10
+ :adapter => 'sqlite3',
11
+ :database => ':memory:'
12
+ )
13
+
14
+ ActiveRecord::Base.connection.create_table :models, :force => true do |t|
15
+ t.string :name
16
+ end
17
+
18
+ ActiveRecord::Base.connection.create_table :translations, :force => true do |t|
19
+ t.string :locale
20
+ t.string :key
21
+ t.string :value
22
+ t.text :interpolations
23
+ t.boolean :is_proc
24
+ end
25
+
26
+ I18n.backend = I18n::Backend::ActiveRecord.new
27
+ I18n.available_locales = %W(en de-DE)
28
+
29
+ Model.send(:include, TranslatableAttributes)
30
+ Model.send(:translatable_attribute_accessor, :foo)
31
+
32
+ @model = Model.create!
33
+ end
34
+
35
+ def test_setup
36
+ assert_nothing_raised do
37
+ model = Model.create!(:name => "Heidi Klum")
38
+ assert_equal "Heidi Klum", model.name
39
+ end
40
+ assert_nothing_raised do
41
+ I18n::Backend::ActiveRecord::Translation.create!(:locale => 'en', :key => 'foo', :value => 'bar')
42
+ assert_equal "bar", I18n.t("foo")
43
+ end
44
+ end
45
+
46
+ def test_creation_of_methods
47
+ assert @model.respond_to?('foo_en')
48
+ assert @model.respond_to?('foo_en=')
49
+ assert @model.respond_to?('foo_de_de')
50
+ assert @model.respond_to?('foo_de_de=')
51
+ end
52
+
53
+ def test_accessors
54
+ @model.foo_en = "Boo"
55
+ assert_equal "Boo", @model.foo_en
56
+ @model.foo_de_de = "Bü"
57
+ assert_equal "Bü", @model.foo_de_de
58
+ end
59
+
60
+ def test_after_save
61
+ count = I18n::Backend::ActiveRecord::Translation.count
62
+
63
+ @model.foo_en = "Hello"
64
+ @model.foo_de_de = "Hello"
65
+ @model.save
66
+ assert_equal count += 2, I18n::Backend::ActiveRecord::Translation.count
67
+
68
+ Model.create(:foo_en => "Boo")
69
+ assert_equal count += 1, I18n::Backend::ActiveRecord::Translation.count
70
+
71
+ Model.create(:foo_en => "Bar", :foo_de_de => "Yo")
72
+ assert_equal count += 2, I18n::Backend::ActiveRecord::Translation.count
73
+ end
74
+
75
+ def test_key_and_locale_method
76
+ key = @model.translatable_attribute_record_key("x_y")
77
+ assert_equal "models.#{@model.id}.x_y", key
78
+ end
79
+ end
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "translatable_attributes/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "translatable_attributes"
7
+ s.version = TranslatableAttributes::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["JJ Buckley"]
10
+ s.email = ["translatable_attributes@bjjb.org"]
11
+ s.homepage = "http://jjbuckley.github.com/translatable_attributes"
12
+ s.summary = %q{Automagic attribute translations for ActiveRecord}
13
+ s.description = %q{A Ruby module which fakes out internationalised attributes on the fly.}
14
+
15
+ s.files = `git ls-files`.split("\n")
16
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
+ s.require_paths = ["lib"]
19
+
20
+ s.add_dependency 'i18n-active_record', '>= 0.0.2'
21
+ end
metadata ADDED
@@ -0,0 +1,90 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: translatable_attributes
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - JJ Buckley
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-02-03 00:00:00 +01:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: i18n-active_record
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 27
30
+ segments:
31
+ - 0
32
+ - 0
33
+ - 2
34
+ version: 0.0.2
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ description: A Ruby module which fakes out internationalised attributes on the fly.
38
+ email:
39
+ - translatable_attributes@bjjb.org
40
+ executables: []
41
+
42
+ extensions: []
43
+
44
+ extra_rdoc_files: []
45
+
46
+ files:
47
+ - .gitignore
48
+ - Gemfile
49
+ - README.md
50
+ - Rakefile
51
+ - lib/translatable_attributes.rb
52
+ - lib/translatable_attributes/version.rb
53
+ - test/translatable_attributes_test.rb
54
+ - translatable_attributes.gemspec
55
+ has_rdoc: true
56
+ homepage: http://jjbuckley.github.com/translatable_attributes
57
+ licenses: []
58
+
59
+ post_install_message:
60
+ rdoc_options: []
61
+
62
+ require_paths:
63
+ - lib
64
+ required_ruby_version: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ hash: 3
70
+ segments:
71
+ - 0
72
+ version: "0"
73
+ required_rubygems_version: !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ hash: 3
79
+ segments:
80
+ - 0
81
+ version: "0"
82
+ requirements: []
83
+
84
+ rubyforge_project:
85
+ rubygems_version: 1.3.7
86
+ signing_key:
87
+ specification_version: 3
88
+ summary: Automagic attribute translations for ActiveRecord
89
+ test_files: []
90
+