Пользовательские типы данных mongo_mapper для локализации - PullRequest
0 голосов
/ 17 февраля 2011

Я создал пользовательский тип данных 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 ]

1 голос
/ 06 апреля 2011

Я обнаружил, что ответ Джареда не работает для меня - я получу, что переводы не были найдены при использовании LocalizedString во EmbeddedDocument.

Я бы получил аналогичную проблему с решением Рика, когда при использовании встроенных документов переводы были равны нулю. Чтобы получить работающее решение, я взял решение Рика, изменил переменную перевода на переменную экземпляра, чтобы она не перезаписывалась для каждого нового поля, использующего LocalizedString, а затем добавил проверку, чтобы убедиться, что переводы не равны нулю (и создайте новый хэш, если он был).

Из всех решений 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
1 голос
/ 18 февраля 2011

Проблема в том, что в ваших методах _mongo [to | from], @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
0 голосов
/ 06 апреля 2011

Я нашел это сообщение : это было очень полезно.Он расширил HashWithIndifferentAccess для работы в качестве LocalizedString.Единственное, что мне не понравилось в этом, - это необходимость явно указывать локаль при каждой установке - я хотел, чтобы она работала больше как строка.конечно, вы не можете перегрузить оператор = (по крайней мере, я так не думаю), поэтому я использовал << и добавил метод to_s, который выводил бы строку текущей локали .... </p>

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

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"}

Итак, мы идем - этот, похоже, действительно работает для меня.Комментарии приветствуются, и надеюсь, что это кому-то поможет!

...