⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 db_translate.rb

📁 A Hotel Management System based on Ruby on Rails.
💻 RB
📖 第 1 页 / 共 2 页
字号:
module Globalize # :nodoc:

  class WrongLanguageError < ActiveRecord::ActiveRecordError
    attr_reader :original_language, :active_language
    def initialize(orig_lang, active_lang)
      @original_language = orig_lang
      @active_language   = active_lang
    end
  end
  
  class TranslationTrampleError < ActiveRecord::ActiveRecordError; end

  module DbTranslate  # :nodoc:

    def self.included(base)
      base.extend(ClassMethods)
    end

    module ClassMethods
=begin rdoc
          Specifies fields that can be translated. These are normal ActiveRecord
          fields, with corresponding database columns, but they are shadowed
          by translations in a special translation table. All the translation
          stuff is done behind the scenes.
          
          === Example:
          
          ==== In your model:
            class Product < ActiveRecord::Base
              translates :name, :description
            end
          
          ==== In your controller:
            Locale.set("en_US")
            product.name -> guitar
            
            Locale.set("es_ES")
            product.name -> guitarra
=end
      def translates(*facets)

        # parse out options hash
        options = facets.pop if facets.last.kind_of? Hash
        options ||= {}

        facets_string = "[" + facets.map {|facet| ":#{facet}"}.join(", ") + "]"
        class_eval <<-HERE
          @@facet_options = {}
          attr_writer :fully_loaded
          def fully_loaded?; @fully_loaded; end
          @@globalize_facets = #{facets_string}
          @@preload_facets ||= @@globalize_facets
          class << self

            def sqlite?; connection.kind_of? ActiveRecord::ConnectionAdapters::SQLiteAdapter end

            def globalize_facets
              @@globalize_facets
            end

            def globalize_facets_hash
              @@globalize_facets_hash ||= globalize_facets.inject({}) {|hash, facet|
                hash[facet.to_s] = true; hash
              }
            end            

            def untranslated_fields
              @@untranslated_fields ||= 
                column_names.map {|cn| cn.intern } - globalize_facets
            end

            def preload_facets; @@preload_facets; end
            def postload_facets
              @@postload_facets ||= @@globalize_facets - @@preload_facets
            end
            alias_method :globalize_old_find, :find unless
              respond_to? :globalize_old_find
          end
          alias_method :globalize_old_reload,   :reload
          alias_method :globalize_old_destroy,  :destroy
          alias_method :globalize_old_create_or_update, :create_or_update
        
          include Globalize::DbTranslate::TranslateObjectMethods
          extend  Globalize::DbTranslate::TranslateClassMethods        

        HERE

        facets.each do |facet|
          bidi = (!(options[facet] && !options[facet][:bidi_embed])).to_s
          class_eval <<-HERE
            @@facet_options[:#{facet}] ||= {}
            @@facet_options[:#{facet}][:bidi] = #{bidi}

            def #{facet}
              if not_original_language
                raise WrongLanguageError.new(@original_language, Locale.language)
              end
              load_other_translations if 
                !fully_loaded? && !self.class.preload_facets.include?(:#{facet})
              result = read_attribute(:#{facet})
              return nil if result.nil?
              result.direction = #{facet}_is_base? ? 
                (Locale.base_language ? Locale.base_language.direction : nil) : 
                (@original_language ? @original_language.direction : nil)

              # insert bidi embedding characters, if necessary
              if @@facet_options[:#{facet}][:bidi] && 
                  Locale.language && Locale.language.direction && result.direction
                if Locale.language.direction == 'ltr' && result.direction == 'rtl'
                  bidi_str = "\xe2\x80\xab" + result + "\xe2\x80\xac"
                  bidi_str.direction = result.direction
                  return bidi_str
                elsif Locale.language.direction == 'rtl' && result.direction == 'ltr'
                  bidi_str = "\xe2\x80\xaa" + result + "\xe2\x80\xac"
                  bidi_str.direction = result.direction
                  return bidi_str
                end
              end
              
              return result
            end

            def #{facet}=(arg)
              raise WrongLanguageError.new(@original_language, Locale.language) if
                not_original_language
              write_attribute(:#{facet}, arg)
            end

            def #{facet}_is_base?
              self['#{facet}_not_base'].nil?
            end          
          HERE
        end

      end

=begin rdoc
      Optionally specifies translated fields to be preloaded on <tt>find</tt>. For instance,
      in a product catalog, you may want to do a <tt>find</tt> of the first 10 products:

        Product.find(:all, :limit => 10, :order => "name")

      But you wouldn't want to load the complete descriptions and specs of all the
      products, just the names and summaries. So you'd specify:

        class Product < ActiveRecord::Base
          translates :name, :summary, :description, :specs
          translates_preload :name, :summary
          ...
        end

      By default (if no translates_preload is specified), Globalize will preload
      the first field given to <tt>translates</tt>. It will also fully load on
      a <tt>find(:first)</tt> or when <tt>:translate_all => true</tt> is given as a find option.
=end
      def translates_preload(*facets)
      module_eval <<-HERE
        @@preload_facets = facets
      HERE
      end

    end

    module TranslateObjectMethods # :nodoc: all

      module_eval <<-HERE
      def not_original_language
        return false if @original_language.nil?
        return @original_language != Locale.language
      end

      def set_original_language
        @original_language = Locale.language      
      end
      HERE

      def load_other_translations
        postload_facets = self.class.postload_facets
        return if postload_facets.empty? || new_record?

        table_name = self.class.table_name
        facet_selection = postload_facets.join(", ")
        base = connection.select_one("SELECT #{facet_selection} " +
          " FROM #{table_name} WHERE #{self.class.primary_key} = #{id}", 
          "loading base for load_other_translations")
        base.each {|key, val| write_attribute( key, val ) }

        unless Locale.base?
          trs = ModelTranslation.find(:all, 
            :conditions => [ "table_name = ? AND item_id = ? AND language_id = ? AND " +
            "facet IN (#{[ '?' ] * postload_facets.size * ', '})", table_name,
            self.id, Locale.active.language.id ] + postload_facets.map {|facet| facet.to_s} )
          trs ||= []
          trs.each do |tr|
            attr = tr.text || base[tr.facet.to_s]
            write_attribute( tr.facet, attr )
          end
        end
        self.fully_loaded = true
      end

      def destroy
        globalize_old_destroy
        ModelTranslation.delete_all( [ "table_name = ? AND item_id = ?", 
          self.class.table_name, id ])        
      end

      def reload
        globalize_old_reload
        set_original_language
      end

      private  
      
        # Returns copy of the attributes hash where all the values have been safely quoted for use in
        # an SQL statement.
        # REDEFINED to include only untranslated fields. We don't want to overwrite the 
        # base translation with other translations.
        def attributes_with_quotes(include_primary_key = true)
          if Locale.base?
            attributes.inject({}) do |quoted, (name, value)|
              if column = column_for_attribute(name)
                quoted[name] = quote(value, column) unless !include_primary_key && column.primary
              end
              quoted
            end
          else
            attributes.inject({}) do |quoted, (name, value)|
              if !self.class.globalize_facets_hash.has_key?(name) && 
                  column = column_for_attribute(name)
                quoted[name] = quote(value, column) unless !include_primary_key && column.primary
              end
              quoted
            end
          end          
        end

        def create_or_update
          globalize_old_create_or_update
          update_translation if Locale.active
        end
        
        def update_translation
          raise WrongLanguageError.new(@original_language, Locale.language) if
            not_original_language

          set_original_language

          # nothing to do, facets updated in main model

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -