Как заказать запрос в переводе с использованием globalize

Я пытаюсь заказать запрос, используя поле, которое переводится с помощью globalize2. Проблема в том, что, поскольку она хранится в базе данных и в ассоциации, у меня много проблем.

  • Выполнение перевода и упорядочения с помощью category_translations.name не работает.
  • Я попробовал default_scope, но поскольку он не позволяет использовать лямбда или блок для условий, я не могу заставить его работать, если я не использую этот патч для ActiveRecord http://gist.github.com/81187
  • Я пробовал с with_translations, определенным в globalize2, однако я получаю сообщение об ошибке, и я не мог заставить его работать даже без упорядочения.

У меня что-то вроде этого

class Category < ActiveRecord::Base
  validates_presence_of :name
  validates_uniqueness_of :name
  has_many :products, :dependent => :destroy

  translates :name
end

Вопрос в том, как я могу заказать переведенное имя?

Ответы

Ответ 1

Метод with_translations, по-видимому, подходит:

Category.with_translations(I18n.locale).order('category_translations.name')

Кроме того, если вы используете PostgreSQL, вы можете добавить к нему регистр, нечувствительный к этому:

Category.with_translations(I18n.locale).order("LOWER(category_translations.name) ASC")

Подробнее об этом здесь: https://github.com/globalize/globalize#scoping-objects-by-those-with-translations

Ответ 2

Я тестировал это с помощью sqlite3, и он работает.

class Category < ActiveRecord::Base
  ...
  named_scope :ordered, lambda {|locale|
    {
      #:select => "categories.*, categories.name sort_name",
      # For MySQL
      #:select => "categories.*, IF(category_translations.name IS NULL, categories.name, category_translations.name) sort_name",
      # For sqlite3
      :select => "categories.*, (CASE WHEN category_translations.name IS NULL THEN categories.name ELSE category_translations.name END) sort_name",
      :joins => ActiveRecord::Base.sanitize_sql_array([
        "LEFT JOIN category_translations on category_translations.category_id = categories.id AND category_translations.locale = ?", locale]),
      :order => "sort_name"
    }
  }
  ...
end

Category.ordered(some_locale).all # Returns all records, sorted by translated name

Ответ 3

Я предполагаю, что любая модель под названием Category будет иметь не более сотни записей, если не меньше. Возможно, вы можете рассмотреть возможность сортировки результатов в памяти после их загрузки.

@categories = Category.all # or whatever else to retrieve what you want
@categories.sort! { |a,b| a.name <=> b.name }

Остерегайтесь. Это станет плохой идеей, если таблица categories содержит более тысячи записей.