diff --git a/README.md b/README.md index da0c092..5aaa1d9 100644 --- a/README.md +++ b/README.md @@ -73,6 +73,15 @@ Post.with_title_translation("This database rocks!") # => # # ``` +To order records using translations without constructing JSON queries by hand: + +```ruby +Post.order_by_title_translation # => # +Post.order_by_title_translation(:asc) # => # +Post.order_by_title_translation(:desc) # => # +Post.order_by_title_translation(:desc, :he) # => # +``` + In order to make this work, you'll need to define an JSON or JSONB column for each of your translated attributes, using the suffix "_translations": diff --git a/lib/json_translate/translates.rb b/lib/json_translate/translates.rb index ecf138c..5c538d0 100644 --- a/lib/json_translate/translates.rb +++ b/lib/json_translate/translates.rb @@ -48,6 +48,16 @@ def translates(*attrs) where("#{quoted_translation_store} @> :translation::jsonb", translation: translation_hash.to_json) end end + + define_singleton_method "order_by_#{attr_name}_translation" do |direction = :asc, locale = I18n.locale| + quoted_translation_store = connection.quote_column_name("#{attr_name}#{SUFFIX}") + + if MYSQL_ADAPTERS.include?(connection.adapter_name) + order(Arel.sql("JSON_EXTRACT(#{quoted_translation_store}, '$.\"#{locale}\"') #{direction}")) + else + order(Arel.sql("#{quoted_translation_store} ->> '#{locale}' #{direction}")) + end + end end end diff --git a/test/translates_test.rb b/test/translates_test.rb index 2fbdb68..7ef6c08 100644 --- a/test/translates_test.rb +++ b/test/translates_test.rb @@ -206,6 +206,17 @@ def test_with_translation_relation end end + def test_order_by_translation + p = Post.create!(:title_translations => { "en" => "Alice in Wonderland", "fr" => "Alice au pays des merveilles" }, :body_1_translations => { "en" => "English Body", "fr" => "Corps anglais" }) + p2 = Post.create!(:title_translations => { "en" => "Zoolander", "fr" => "Zoolandia" }, :body_1_translations => { "en" => "English Body", "fr" => "Corps anglais" }) + I18n.with_locale(:en) do + assert_equal p.title_en, Post.order_by_title_translation.first.try(:title) + assert_equal p.title_en, Post.order_by_title_translation(:asc).first.try(:title) + assert_equal p2.title_en, Post.order_by_title_translation(:desc).first.try(:title) + assert_equal p2.title_en, Post.order_by_title_translation(:desc, :fr).first.try(:title) + end + end + def test_with_interpolation_arguments p = Post.create!(:title_translations => { "en" => "Alice in %{where}" }) I18n.with_locale(:en) do