mongo_mapper用于本地化的自定义数据类型

时间:2011-02-17 15:21:34

标签: ruby-on-rails ruby mongodb mongomapper

我创建了一个LocalizedString自定义数据类型,用于使用mongo_mapper存储/显示翻译。

这适用于一个字段,但只要我引入另一个字段,它们就会被写入每个字段,并且只显示两个字段的一个值。 to_mongo和from_mongo似乎没有正常运作。请任何人帮忙吗?她是代码:

class LocalizedString

  attr_accessor :translations

  def self.from_mongo(value)

    puts self.inspect
    @translations ||= if value.is_a?(Hash)
        value
      elsif value.nil?
        {}
      else
        { I18n.locale.to_s => value }
    end

    @translations[I18n.locale.to_s]
  end

  def self.to_mongo(value)
    puts self.inspect
    if value.is_a?(Hash)
      @translations = value  
    else
      @translations[I18n.locale.to_s] = value
    end

    @translations
  end
end

非常感谢 瑞克

3 个答案:

答案 0 :(得分:1)

问题是,在你的[to | from] _mongo方法中,@ translations引用了一个类变量,而不是你期望的实例变量。所以发生的事情是,每次调用from_mongo时,它都会覆盖该值。

固定版本会是这样的:

class LocalizedString
  attr_accessor :translations

  def initialize( translations = {} ) 
    @translations = translations
  end 

  def self.from_mongo(value)
    if value.is_a?(Hash)
      LocalizedString.new(value)
    elsif value.nil?
      LocalizedString.new()
    else
      LocalizedString.new( { I18n.locale.to_s => value })
    end
  end

  def self.to_mongo(value)
    value.translations if value.present?
  end

end

答案 1 :(得分:1)

我发现jared的回复对我不起作用 - 我会在EmbeddedDocument中使用LocalizedString时找不到翻译。

我会在rick的解决方案上遇到类似的问题,其中使用嵌入式文档时翻译为零。为了获得一个有效的解决方案,我采用了Rick的解决方案,将转换变量更改为实例变量,因此不会为使用LocalizedString的每个新字段覆盖它,然后添加一个检查以确保转换不是nil(和如果是的话,创建一个新的Hash)。

在所有的LocalizedString解决方案中,这是我第一次能够使用EmbeddedDocuments并且没有覆盖问题 - 仍然可能存在其他问题! :)

class LocalizedString
  attr_accessor :translations

    def self.from_mongo(value)

        puts self.inspect
        translations ||= if value.is_a?(Hash)
            value
          elsif value.nil?
            {}
          else
            { I18n.locale.to_s => value }
        end

        translations[I18n.locale.to_s]
      end

      def self.to_mongo(value)
        puts self.inspect
        if value.is_a?(Hash)
          translations = value
        else
          if translations.nil?
            translations = Hash.new()
          end
          translations[I18n.locale.to_s] = value
        end

        translations
      end

    end

答案 2 :(得分:0)

我找到了this post:这非常有帮助。他将HashWithIndifferentAccess扩展为LocalizedString。我唯一不喜欢它的是每次设置它时必须明确指定语言环境 - 我希望它更像字符串。当然,你不能重载=运算符(至少我认为你不能)所以我使用<<,并添加了一个to_s方法,它将输出当前语言环境的字符串....

class LocalizedString < HashWithIndifferentAccess
  def self.from_mongo(value)
    LocalizedString.new(value || {})
  end

  def available_locales
    symbolize_keys.keys
  end

  def to_s
    self[I18n.locale]
  end

  def in_current_locale=(value)
    self[I18n.locale] = value
  end

   def << (value)
    self[I18n.locale] = value
   end

然后我有一个类:

class SimpleModel
  include MongoMapper::Document

  key :test, LocalizedString
end

可以做像

这样的事情
 I18n.locale = :en
  a = SimpleModel.new
  a.test << "English"
  I18n.locale = :de
  a.test << "German"
  puts a.test # access the translation for the current locale
  I18n.locale = :en
  puts a.test # access the translation for the current locale
  puts a.test[:de] # access a translation explicitly 
  puts a.test[:en]
  puts a.test.inspect

并获取

German
English
German
English
{"en"=>"English", "de"=>"German"}

所以我们去了 - 这个似乎对我有用。评论欢迎,并希望这有助于某人!