Created
November 25, 2008 11:34
-
-
Save karmi/28889 to your computer and use it in GitHub Desktop.
I ♥ Ruby so much...
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| class CreateCategories < ActiveRecord::Migration | |
| def self.up | |
| create_table :categories do |t| | |
| t.string :name_en, | |
| :name_cz, | |
| :name_es | |
| t.timestamps | |
| end | |
| end | |
| def self.down | |
| drop_table :categories | |
| end | |
| end | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| class CreateProducts < ActiveRecord::Migration | |
| def self.up | |
| create_table :products do |t| | |
| t.string :name | |
| t.text :description | |
| t.datetime :manufactured_on | |
| t.timestamps | |
| end | |
| end | |
| def self.down | |
| drop_table :products | |
| end | |
| end | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| class CreateTranslations < ActiveRecord::Migration | |
| def self.up | |
| create_table :translations do |t| | |
| t.string :name | |
| t.text :description | |
| t.string :locale | |
| t.string :translatable_type | |
| t.integer :translatable_id | |
| t.timestamps | |
| end | |
| add_index :translations, [:locale, :translatable_id, :translatable_type], :name => "lang_index", :unique => true | |
| end | |
| def self.down | |
| drop_table :translations | |
| end | |
| end | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| class Category < ActiveRecord::Base | |
| I18n.backend.send(:init_translations) if I18n.available_locales.blank? | |
| self.class_eval do | |
| Category.columns_hash.collect { |c| c[0] if c[1].type == :string or c[1].type == :text }.compact.each do |attribute_name| | |
| puts attribute_name | |
| if includes_locale = I18n.available_locales.find { |locale| attribute_name =~ Regexp.new("_#{locale}$") } | |
| method_name = attribute_name.sub( Regexp.new("(\w*)_#{includes_locale}$"), '\1' ) | |
| unless method_defined?(method_name.to_sym) | |
| # Use like this: | |
| # c = Category.first | |
| # c.name_en | |
| # => "Category one" | |
| # c.name | |
| # => "Category one" | |
| # I18n.locale = 'es' | |
| # c.name | |
| # => "Categoria uno" | |
| puts "Defining localized getter '#{method_name}'" | |
| define_method(method_name) do |*args| | |
| lookup_locale = args.shift || I18n.locale | |
| puts "Arguments: #{args.inspect}" | |
| puts "Lookup locale: #{lookup_locale}" | |
| return @attributes["#{method_name}_#{lookup_locale}"] | |
| end | |
| # And now try this | |
| # c = Category.first | |
| # I18n.locale = 'es' | |
| # c.name | |
| # => "Categoria uno" | |
| # c.name = 'Pues, vamos a modificar este registro!' | |
| # c.save | |
| # >> UPDATE `categories` SET `name_es` = 'Pues, vamos a modificar este registro!' ... WHERE ... | |
| puts "Defining localized setter '#{method_name}='" | |
| define_method("#{method_name}=") do |args| | |
| raise ArgumentError, | |
| "argument must be a String, like 'Salut' or a hash of values, like :es => '¡Hola!'" unless args.is_a?(String) || args.is_a?(Hash) | |
| locale = args.is_a?(Hash) ? args.keys.first : I18n.locale | |
| value = args.is_a?(Hash) ? args.values.first : args | |
| puts "Arguments: #{args.inspect}" | |
| puts "Lookup locale: #{locale}" | |
| self.send(:"#{method_name}_#{locale}=", value) if self.respond_to?(:"#{method_name}_#{locale}") | |
| end | |
| end | |
| end | |
| end | |
| end #:nodoc: class_eval | |
| end #:nodoc: class | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| class Product < ActiveRecord::Base | |
| # This is really it | |
| has_many :translations, :as => :translatable | |
| self.class_eval do | |
| Product.columns_hash.collect { |c| c[0] if c[1].type == :string or c[1].type == :text }.compact.each do |attribute_name| | |
| # Use like this: | |
| # p = Product.first | |
| # p.name | |
| # => "Product two" | |
| # I18n.locale = :cz | |
| # p.name | |
| # => "Produkt 2" | |
| # I18n.locale = :en | |
| # p.name(:cz) | |
| # => "Produkt 2" | |
| puts "Re-defining method '#{attribute_name}' for #{self.class.name}" | |
| define_method(attribute_name) do |*args| | |
| lookup_locale = args.shift || I18n.locale | |
| puts "Arguments: #{args.inspect}" | |
| puts "Lookup locale: #{lookup_locale}" | |
| return @attributes[attribute_name] if lookup_locale.to_s == I18n.default_locale.to_s # Do not lookup anything if passed locale is default | |
| if translation = self.translations.find_by_locale(lookup_locale.to_s) | |
| translation.attributes[attribute_name] | |
| end | |
| end | |
| # This is needed so Rails form helpers like f.text_field :name actually work. They call _before_type_cast. | |
| # See http://github.com/rails/rails/tree/2-2-stable/actionpack%2Flib%2Faction_view%2Fhelpers%2Fform_helper.rb#L649-655 | |
| alias :"#{attribute_name}_before_type_cast" :"#{attribute_name}" | |
| # And now try this: | |
| # p = Product.first | |
| # p.name | |
| # => "Product two" | |
| # p.name = 'This is product two' | |
| # p.save | |
| # p.reload.name | |
| # => "This is product two" | |
| # I18n.locale = 'cz' | |
| # p.name | |
| # => "Produkt 2" | |
| # p.name = 'Produkt dvě' | |
| # p.save | |
| # p.reload.name | |
| # => "Produkt dvě" | |
| # p.name={:es => 'Esto es un nombre de producto dos'} | |
| # p.save | |
| # >> INSERT INTO `translations` (`name` ... `locale` ...) VALUES('Esto es un nombre de producto dos' ... 'es' ...) | |
| # p.reload.name | |
| # => "Produkt dvě" | |
| # p.name(:es) | |
| # => "Esto es un nombre de producto dos" | |
| puts "Re-defining method '#{attribute_name}=(value)' #{self.class.name}" | |
| define_method("#{attribute_name}=") do |args| | |
| puts "Arguments: #{args.inspect}" | |
| raise ArgumentError, | |
| "argument must be a String, like 'Salut' or a hash of values, like :es => '¡Hola!'" unless args.is_a?(String) || args.is_a?(Hash) | |
| # TODO : Allow passing more locales and values at once, like this <tt>p.name={ :cz => 'Ahoj', :es => 'Hola' }</tt> | |
| locale = args.is_a?(Hash) ? args.keys.first : I18n.locale | |
| value = args.is_a?(Hash) ? args.values.first : args | |
| puts "Write to locale: #{locale}" | |
| puts "Value: #{value}" | |
| super(value.to_s) and return if locale.to_s == I18n.default_locale.to_s | |
| raise ActiveRecord::RecordNotSaved, "you cannot add translations to unsaved record" if new_record? | |
| if translation = self.translations.find_by_locale(locale.to_s) | |
| translation.update_attribute(attribute_name.to_sym, value.to_s) | |
| else | |
| self.translations.create!(:locale => locale.to_s, attribute_name.to_s => value.to_s) | |
| end | |
| end | |
| end | |
| end #:nodoc: class_eval | |
| # Returns true if object has translation for passed locale | |
| def has_translation?(locale) | |
| !translations.find_by_locale(locale.to_s).nil? | |
| end | |
| end | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment