acts-as-taggable-on icon indicating copy to clipboard operation
acts-as-taggable-on copied to clipboard

another problem with multibyte tags

Open nir0 opened this issue 11 years ago • 19 comments

gem version is 3.0.1 error: Tag cannot be empty

2.0.0p195 :001 > post = NewsPost.new(id: 277423, 
2.0.0p195 :002 >           name: "В торговом центре 52-летний мужчина в туалете свел счеты с жизнью", 
2.0.0p195 :003 >           markdown: "В Тюмени проводится проверка по факту обнаружения в одном из торговых центров тела мужчины. Как сообщили \"Вслух.ру\" в пресс-службе регионального управления СК РФ, накануне, 19 января, около 21.30 в закрытой туалетной кабине на первом этаже в одном из торговых центров Тюмени обнаружено тело 52-летнего мужчины, покончившего жизнь самоубийством - воткнувшего нож себе в грудь. Проводится доследственная проверка.
2.0.0p195 :004"> 
2.0.0p195 :005"> Установлено, что дверь кабины была заперта изнутри. О случившемся сообщили посетители торгового центра, которые в тот момент находились в этом же помещении и услышали странный хрип. Следствие проводит комплекс необходимых мероприятий, направленных на установление всех обстоятельств произошедшего. Опрашиваются очевидцы и родственники погибшего. По результатам проверки будет принято решение.", 
2.0.0p195 :006 >           text: "<p>В Тюмени проводится проверка по&#160;факту обнаружения в&#160;одном из&#160;торговых центров тела мужчины. Как&#160;сообщили &#171;Вслух.ру&#187; в&#160;<span class=\"nobr\">пресс-службе</span> регионального управления СК&#160;РФ, накануне, 19&#160;января, около 21.30 в&#160;закрытой туалетной кабине на&#160;первом этаже в&#160;одном из&#160;торговых центров Тюмени обнаружено тело <span class=\"nobr\">52-летнего</span> мужчины, покончившего жизнь самоубийством &#8211; воткнувшего нож&#160;себе в&#160;грудь. Проводится доследственная проверка.</p>
2.0.0p195 :007"> 
2.0.0p195 :008"> <p>Установлено, что&#160;дверь кабины была заперта изнутри. О&#160;случившемся сообщили посетители торгового центра, которые в&#160;тот момент находились в&#160;этом же&#160;помещении и&#160;услышали странный хрип. Следствие проводит комплекс необходимых мероприятий, направленных на&#160;установление всех обстоятельств произошедшего. Опрашиваются очевидцы и&#160;родственники погибшего. По&#160;результатам проверки будет принято решение.</p>", 
2.0.0p195 :009 >           creator_id: 467, 
2.0.0p195 :010 >           rubric_id: 31, 
2.0.0p195 :011 >           genre: "lenta", 
2.0.0p195 :012 >           published_at: "2014-01-20 18:38:00 +0600", 
2.0.0p195 :013 >           annotation: "Накануне, 19 января, около 21.30 в закрытой туалетной кабине на первом этаже в одном из торговых центров Тюмени обнаружено тело мужчины 1961 года рождения, покончившего жизнь самоубийством.", 
2.0.0p195 :014 >           source: "Вслух.ру", 
2.0.0p195 :015 >           source_url: "http://www.vsluh.ru", 
2.0.0p195 :016 >           author_name: "",
2.0.0p195 :017 >           author_email: "",
2.0.0p195 :018 >           tag_list: "СК РФ, следствие, проверка, самоубийство, суицид",
2.0.0p195 :019 >           exclude_from_rss: false,
2.0.0p195 :020 >           main_in_rubric_from: "",
2.0.0p195 :021 >           commentable: true,
2.0.0p195 :022 >           views_count: 90,
2.0.0p195 :023 >           created_at: "2014-01-20 18:36:14 +0600",
2.0.0p195 :024 >           updated_at: "2014-01-20 20:23:31 +0600",
2.0.0p195 :025 >           creator_id: 467,
2.0.0p195 :026 >           updater_id: 467,
2.0.0p195 :027 >           visibility: true,
2.0.0p195 :028 >           author_id: false,
2.0.0p195 :029 >           hide_banner: false,
2.0.0p195 :030 >           redirect_url: "",
2.0.0p195 :031 >           likes_count: 0,
2.0.0p195 :032 >           shares_count: 0,
2.0.0p195 :033 >           rating: 0
2.0.0p195 :034?>         )
 => #<NewsPost id: 277423, rubric_id: 31, name: "В торговом центре 52-летний мужчина в туалете свел ...", genre: "lenta", published_at: "2014-01-20 12:38:00", annotation: "Накануне, 19 января, около 21.30 в закрытой туалетн...", text: "<p>В Тюмени проводится проверка по&#160;факту обнар...", exclude_from_rss: false, main_in_rubric_from: nil, main_on_site_from: nil, views_count: 90, creator_id: 467, updater_id: 467, locker_id: nil, visibility: true, type: "NewsPost", author_id: 0, markdown: "В Тюмени проводится проверка по факту обнаружения в...", likes_count: 0, shares_count: 0, rating: 0, storage: {"source"=>"Вслух.ру", "source_url"=>"http://www.vsluh.ru", "author_name"=>"", "author_email"=>"", "redirect_url"=>""}, created_at: "2014-01-20 12:36:14", updated_at: "2014-01-20 14:23:31", hide_banner: false, commentable: true, delta: true, published_messages_count: 0> 
2.0.0p195 :035 > post.save!(validate: false)
   (0.4ms)  BEGIN
  SQL (103.2ms)  INSERT INTO "posts" ("annotation", "commentable", "created_at", "creator_id", "genre", "hide_banner", "id", "likes_count", "markdown", "name", "published_at", "rubric_id", "shares_count", "storage", "text", "type", "updated_at", "updater_id", "views_count", "visibility") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20) RETURNING "id"  [["annotation", "Накануне, 19 января, около 21.30 в закрытой туалетной кабине на первом этаже в одном из торговых центров Тюмени обнаружено тело мужчины 1961 года рождения, покончившего жизнь самоубийством."], ["commentable", true], ["created_at", Mon, 20 Jan 2014 18:36:14 YEKT +06:00], ["creator_id", 467], ["genre", "lenta"], ["hide_banner", false], ["id", 277423], ["likes_count", 0], ["markdown", "В Тюмени проводится проверка по факту обнаружения в одном из торговых центров тела мужчины. Как сообщили \"Вслух.ру\" в пресс-службе регионального управления СК РФ, накануне, 19 января, около 21.30 в закрытой туалетной кабине на первом этаже в одном из торговых центров Тюмени обнаружено тело 52-летнего мужчины, покончившего жизнь самоубийством - воткнувшего нож себе в грудь. Проводится доследственная проверка.\n\nУстановлено, что дверь кабины была заперта изнутри. О случившемся сообщили посетители торгового центра, которые в тот момент находились в этом же помещении и услышали странный хрип. Следствие проводит комплекс необходимых мероприятий, направленных на установление всех обстоятельств произошедшего. Опрашиваются очевидцы и родственники погибшего. По результатам проверки будет принято решение."], ["name", "В торговом центре 52-летний мужчина в туалете свел счеты с жизнью"], ["published_at", Mon, 20 Jan 2014 18:38:00 YEKT +06:00], ["rubric_id", 31], ["shares_count", 0], ["storage", "{\"source\":\"Вслух.ру\",\"source_url\":\"http://www.vsluh.ru\",\"author_name\":\"\",\"author_email\":\"\",\"redirect_url\":\"\"}"], ["text", "<p>В Тюмени проводится проверка по&#160;факту обнаружения в&#160;одном из&#160;торговых центров тела мужчины. Как&#160;сообщили &#171;Вслух.ру&#187; в&#160;<span class=\"nobr\">пресс-службе</span> регионального управления СК&#160;РФ, накануне, 19&#160;января, около 21.30 в&#160;закрытой туалетной кабине на&#160;первом этаже в&#160;одном из&#160;торговых центров Тюмени обнаружено тело <span class=\"nobr\">52-летнего</span> мужчины, покончившего жизнь самоубийством &#8211; воткнувшего нож&#160;себе в&#160;грудь. Проводится доследственная проверка.</p>\n\n<p>Установлено, что&#160;дверь кабины была заперта изнутри. О&#160;случившемся сообщили посетители торгового центра, которые в&#160;тот момент находились в&#160;этом же&#160;помещении и&#160;услышали странный хрип. Следствие проводит комплекс необходимых мероприятий, направленных на&#160;установление всех обстоятельств произошедшего. Опрашиваются очевидцы и&#160;родственники погибшего. По&#160;результатам проверки будет принято решение.</p>"], ["type", "NewsPost"], ["updated_at", Mon, 20 Jan 2014 20:23:31 YEKT +06:00], ["updater_id", 467], ["views_count", 90], ["visibility", true]]
  ActsAsTaggableOn::Tag Load (1.8ms)  SELECT "tags".* FROM "tags" WHERE (lower(name) = 'СК РФ' OR lower(name) = 'следствие' OR lower(name) = 'проверка' OR lower(name) = 'самоубийство' OR lower(name) = 'суицид')
  ActsAsTaggableOn::Tag Exists (6.6ms)  SELECT 1 AS one FROM "tags" WHERE "tags"."name" = 'СК РФ' LIMIT 1
  ActsAsTaggableOn::Tag Exists (1.1ms)  SELECT 1 AS one FROM "tags" WHERE "tags"."name" = 'проверка' LIMIT 1
  SQL (35.9ms)  INSERT INTO "tags" ("name") VALUES ($1) RETURNING "id"  [["name", "проверка"]]
  ActsAsTaggableOn::Tag Exists (0.6ms)  SELECT 1 AS one FROM "tags" WHERE "tags"."name" = 'самоубийство' LIMIT 1
  SQL (0.6ms)  INSERT INTO "tags" ("name") VALUES ($1) RETURNING "id"  [["name", "самоубийство"]]
  ActsAsTaggableOn::Tag Exists (0.6ms)  SELECT 1 AS one FROM "tags" WHERE "tags"."name" = 'суицид' LIMIT 1
  SQL (0.6ms)  INSERT INTO "tags" ("name") VALUES ($1) RETURNING "id"  [["name", "суицид"]]
  ActsAsTaggableOn::Tag Load (2.1ms)  SELECT "tags".* FROM "tags" INNER JOIN "taggings" ON "tags"."id" = "taggings"."tag_id" WHERE "taggings"."taggable_id" = $1 AND "taggings"."taggable_type" = $2 AND (taggings.context = 'tags' AND taggings.tagger_id IS NULL)  [["taggable_id", 277423], ["taggable_type", "Post"]]
  ActsAsTaggableOn::Tagging Exists (16.5ms)  SELECT 1 AS one FROM "taggings" WHERE ("taggings"."tag_id" IS NULL AND "taggings"."taggable_type" = 'Post' AND "taggings"."taggable_id" = 277423 AND "taggings"."context" = 'tags' AND "taggings"."tagger_id" IS NULL AND "taggings"."tagger_type" IS NULL) LIMIT 1
   (0.3ms)  ROLLBACK
ActiveRecord::RecordInvalid: Возникли ошибки: Tag не может быть пустым
    from /home/nir0/.rvm/gems/ruby-2.0.0-p195@vsluh4dev/gems/activerecord-4.0.0/lib/active_record/validations.rb:57:in `save!'
    from /home/nir0/.rvm/gems/ruby-2.0.0-p195@vsluh4dev/gems/activerecord-4.0.0/lib/active_record/attribute_methods/dirty.rb:41:in `save!'
    from /home/nir0/.rvm/gems/ruby-2.0.0-p195@vsluh4dev/gems/activerecord-4.0.0/lib/active_record/transactions.rb:275:in `block in save!'
    from /home/nir0/.rvm/gems/ruby-2.0.0-p195@vsluh4dev/gems/activerecord-4.0.0/lib/active_record/transactions.rb:326:in `block in with_transaction_returning_status'
    from /home/nir0/.rvm/gems/ruby-2.0.0-p195@vsluh4dev/gems/activerecord-4.0.0/lib/active_record/connection_adapters/abstract/database_statements.rb:200:in `transaction'
    from /home/nir0/.rvm/gems/ruby-2.0.0-p195@vsluh4dev/gems/activerecord-4.0.0/lib/active_record/transactions.rb:209:in `transaction'
    from /home/nir0/.rvm/gems/ruby-2.0.0-p195@vsluh4dev/gems/activerecord-4.0.0/lib/active_record/transactions.rb:323:in `with_transaction_returning_status'
    from /home/nir0/.rvm/gems/ruby-2.0.0-p195@vsluh4dev/gems/activerecord-4.0.0/lib/active_record/transactions.rb:275:in `save!'
    from /home/nir0/.rvm/gems/ruby-2.0.0-p195@vsluh4dev/gems/activerecord-4.0.0/lib/active_record/associations/has_many_association.rb:37:in `insert_record'
    from /home/nir0/.rvm/gems/ruby-2.0.0-p195@vsluh4dev/gems/activerecord-4.0.0/lib/active_record/associations/collection_association.rb:463:in `block (2 levels) in create_record'
    from /home/nir0/.rvm/gems/ruby-2.0.0-p195@vsluh4dev/gems/activerecord-4.0.0/lib/active_record/associations/collection_association.rb:367:in `add_to_target'
    from /home/nir0/.rvm/gems/ruby-2.0.0-p195@vsluh4dev/gems/activerecord-4.0.0/lib/active_record/associations/collection_association.rb:461:in `block in create_record'
    from /home/nir0/.rvm/gems/ruby-2.0.0-p195@vsluh4dev/gems/activerecord-4.0.0/lib/active_record/associations/collection_association.rb:152:in `block in transaction'
    from /home/nir0/.rvm/gems/ruby-2.0.0-p195@vsluh4dev/gems/activerecord-4.0.0/lib/active_record/connection_adapters/abstract/database_statements.rb:200:in `transaction'
    from /home/nir0/.rvm/gems/ruby-2.0.0-p195@vsluh4dev/gems/activerecord-4.0.0/lib/active_record/transactions.rb:209:in `transaction'
    from /home/nir0/.rvm/gems/ruby-2.0.0-p195@vsluh4dev/gems/activerecord-4.0.0/lib/active_record/associations/collection_association.rb:151:in `transaction'
... 12 levels...
    from /home/nir0/.rvm/gems/ruby-2.0.0-p195@vsluh4dev/gems/activerecord-4.0.0/lib/active_record/validations.rb:57:in `save!'
    from /home/nir0/.rvm/gems/ruby-2.0.0-p195@vsluh4dev/gems/activerecord-4.0.0/lib/active_record/attribute_methods/dirty.rb:41:in `save!'
    from /home/nir0/.rvm/gems/ruby-2.0.0-p195@vsluh4dev/gems/activerecord-4.0.0/lib/active_record/transactions.rb:275:in `block in save!'
    from /home/nir0/.rvm/gems/ruby-2.0.0-p195@vsluh4dev/gems/activerecord-4.0.0/lib/active_record/transactions.rb:326:in `block in with_transaction_returning_status'
    from /home/nir0/.rvm/gems/ruby-2.0.0-p195@vsluh4dev/gems/activerecord-4.0.0/lib/active_record/connection_adapters/abstract/database_statements.rb:202:in `block in transaction'
    from /home/nir0/.rvm/gems/ruby-2.0.0-p195@vsluh4dev/gems/activerecord-4.0.0/lib/active_record/connection_adapters/abstract/database_statements.rb:210:in `within_new_transaction'
    from /home/nir0/.rvm/gems/ruby-2.0.0-p195@vsluh4dev/gems/activerecord-4.0.0/lib/active_record/connection_adapters/abstract/database_statements.rb:202:in `transaction'
    from /home/nir0/.rvm/gems/ruby-2.0.0-p195@vsluh4dev/gems/activerecord-4.0.0/lib/active_record/transactions.rb:209:in `transaction'
    from /home/nir0/.rvm/gems/ruby-2.0.0-p195@vsluh4dev/gems/activerecord-4.0.0/lib/active_record/transactions.rb:323:in `with_transaction_returning_status'
    from /home/nir0/.rvm/gems/ruby-2.0.0-p195@vsluh4dev/gems/activerecord-4.0.0/lib/active_record/transactions.rb:275:in `save!'
    from (irb):35
    from /home/nir0/.rvm/gems/ruby-2.0.0-p195@vsluh4dev/gems/railties-4.0.0/lib/rails/commands/console.rb:90:in `start'
    from /home/nir0/.rvm/gems/ruby-2.0.0-p195@vsluh4dev/gems/railties-4.0.0/lib/rails/commands/console.rb:9:in `start'
    from /home/nir0/.rvm/gems/ruby-2.0.0-p195@vsluh4dev/gems/railties-4.0.0/lib/rails/commands.rb:64:in `<top (required)>'
    from bin/rails:4:in `require'
    from bin/rails:4:in `<main>'2.0.0p195 :036 >

nir0 avatar Jan 21 '14 05:01 nir0

rolling back to 2.4.1 fixed this, but as far as i remember, there were some index migrations on v3.0 that may impact performance.

nir0 avatar Jan 21 '14 07:01 nir0

@nir0 The migrations in 3.0 should be compatible with 2.4.1 (which I originally wrote them against).

If you set the tags as an array, tag_list: [СК РФ, следствие, проверка, самоубийство, суицид] or set parse: true, does that make a difference? A breaking test for this would be great!

bf4 avatar Jan 23 '14 16:01 bf4

i tried it in https://gist.github.com/nir0/8592186 i don't know where to set parse: true seems like you can reproduce this bug: tag something with "СК РФ" tag another object with same tag i use postgres if it is important.

nir0 avatar Jan 24 '14 04:01 nir0

alright, i wrote a test:

# coding: utf-8
require 'spec_helper'

describe "Unicode" do
  before(:each) do
    clean_database!
  end

  it "saves english tags good" do
    @johny = TaggableModel.new(name: 'Johny', tag_list: 'English')
    @johny.save!
    @peter = TaggableModel.new(name: 'Peter', tag_list: 'English')
    @peter.save!
    TaggableModel.count.should == 2
  end
  it "saves russian tags good" do
    @boris = TaggableModel.new(name: 'Борис', tag_list: 'Русский')
    @boris.save!
    @dmitry = TaggableModel.new(name: 'Дмитрий', tag_list: 'Русский')
    @dmitry.save!
    TaggableModel.count.should == 2
  end
end
[nir0@spear ~/.rvm/gems/ruby-2.0.0-p195@vsluh4dev/gems/acts-as-taggable-on-3.0.1]$ rspec spec/acts_as_taggable_on/utf_spec.rb 
fatal: Not a git repository (or any of the parent directories): .git
.log writing failed. "\xD0" from ASCII-8BIT to UTF-8
log writing failed. "\xD0" from ASCII-8BIT to UTF-8
.

Finished in 1.59 seconds
2 examples, 0 failures
[nir0@spear ~/.rvm/gems/ruby-2.0.0-p195@vsluh4dev/gems/acts-as-taggable-on-3.0.1]$ DB='postgresql' rspec spec/acts_as_taggable_on/utf_spec.rb 
fatal: Not a git repository (or any of the parent directories): .git
.F

Failures:

  1) Unicode saves russian tags good
     Failure/Error: @dmitry.save!
     ActiveRecord::RecordInvalid:
       Validation failed: Tag can't be blank
     # /home/nir0/.rvm/gems/ruby-1.9.3-p286/gems/activerecord-4.0.2/lib/active_record/validations.rb:57:in `save!'
     # /home/nir0/.rvm/gems/ruby-1.9.3-p286/gems/activerecord-4.0.2/lib/active_record/attribute_methods/dirty.rb:41:in `save!'
     # /home/nir0/.rvm/gems/ruby-1.9.3-p286/gems/activerecord-4.0.2/lib/active_record/transactions.rb:275:in `block in save!'
     # /home/nir0/.rvm/gems/ruby-1.9.3-p286/gems/activerecord-4.0.2/lib/active_record/transactions.rb:326:in `block in with_transaction_returning_status'
     # /home/nir0/.rvm/gems/ruby-1.9.3-p286/gems/activerecord-4.0.2/lib/active_record/connection_adapters/abstract/database_statements.rb:200:in `transaction'
     # /home/nir0/.rvm/gems/ruby-1.9.3-p286/gems/activerecord-4.0.2/lib/active_record/transactions.rb:209:in `transaction'
     # /home/nir0/.rvm/gems/ruby-1.9.3-p286/gems/activerecord-4.0.2/lib/active_record/transactions.rb:323:in `with_transaction_returning_status'
     # /home/nir0/.rvm/gems/ruby-1.9.3-p286/gems/activerecord-4.0.2/lib/active_record/transactions.rb:275:in `save!'
     # /home/nir0/.rvm/gems/ruby-1.9.3-p286/gems/activerecord-4.0.2/lib/active_record/associations/has_many_association.rb:38:in `insert_record'
     # /home/nir0/.rvm/gems/ruby-1.9.3-p286/gems/activerecord-4.0.2/lib/active_record/associations/collection_association.rb:463:in `block (2 levels) in create_record'
     # /home/nir0/.rvm/gems/ruby-1.9.3-p286/gems/activerecord-4.0.2/lib/active_record/associations/collection_association.rb:367:in `add_to_target'
     # /home/nir0/.rvm/gems/ruby-1.9.3-p286/gems/activerecord-4.0.2/lib/active_record/associations/collection_association.rb:461:in `block in create_record'
     # /home/nir0/.rvm/gems/ruby-1.9.3-p286/gems/activerecord-4.0.2/lib/active_record/associations/collection_association.rb:152:in `block in transaction'
     # /home/nir0/.rvm/gems/ruby-1.9.3-p286/gems/activerecord-4.0.2/lib/active_record/connection_adapters/abstract/database_statements.rb:200:in `transaction'
     # /home/nir0/.rvm/gems/ruby-1.9.3-p286/gems/activerecord-4.0.2/lib/active_record/transactions.rb:209:in `transaction'
     # /home/nir0/.rvm/gems/ruby-1.9.3-p286/gems/activerecord-4.0.2/lib/active_record/associations/collection_association.rb:151:in `transaction'
     # /home/nir0/.rvm/gems/ruby-1.9.3-p286/gems/activerecord-4.0.2/lib/active_record/associations/collection_association.rb:460:in `create_record'
     # /home/nir0/.rvm/gems/ruby-1.9.3-p286/gems/activerecord-4.0.2/lib/active_record/associations/collection_association.rb:125:in `create!'
     # /home/nir0/.rvm/gems/ruby-1.9.3-p286/gems/activerecord-4.0.2/lib/active_record/associations/collection_proxy.rb:276:in `create!'
     # ./lib/acts_as_taggable_on/acts_as_taggable_on/core.rb:386:in `block (2 levels) in save_tags'
     # ./lib/acts_as_taggable_on/acts_as_taggable_on/core.rb:385:in `each'
     # ./lib/acts_as_taggable_on/acts_as_taggable_on/core.rb:385:in `block in save_tags'
     # ./lib/acts_as_taggable_on/acts_as_taggable_on/core.rb:339:in `each'
     # ./lib/acts_as_taggable_on/acts_as_taggable_on/core.rb:339:in `save_tags'
     # /home/nir0/.rvm/gems/ruby-1.9.3-p286/gems/activesupport-4.0.2/lib/active_support/callbacks.rb:386:in `_run__2713624286722651819__save__callbacks'
     # /home/nir0/.rvm/gems/ruby-1.9.3-p286/gems/activesupport-4.0.2/lib/active_support/callbacks.rb:80:in `run_callbacks'
     # /home/nir0/.rvm/gems/ruby-1.9.3-p286/gems/activerecord-4.0.2/lib/active_record/callbacks.rb:302:in `create_or_update'
     # /home/nir0/.rvm/gems/ruby-1.9.3-p286/gems/activerecord-4.0.2/lib/active_record/persistence.rb:128:in `save!'
     # /home/nir0/.rvm/gems/ruby-1.9.3-p286/gems/activerecord-4.0.2/lib/active_record/validations.rb:57:in `save!'
     # /home/nir0/.rvm/gems/ruby-1.9.3-p286/gems/activerecord-4.0.2/lib/active_record/attribute_methods/dirty.rb:41:in `save!'
     # /home/nir0/.rvm/gems/ruby-1.9.3-p286/gems/activerecord-4.0.2/lib/active_record/transactions.rb:275:in `block in save!'
     # /home/nir0/.rvm/gems/ruby-1.9.3-p286/gems/activerecord-4.0.2/lib/active_record/transactions.rb:326:in `block in with_transaction_returning_status'
     # /home/nir0/.rvm/gems/ruby-1.9.3-p286/gems/activerecord-4.0.2/lib/active_record/connection_adapters/abstract/database_statements.rb:202:in `block in transaction'
     # /home/nir0/.rvm/gems/ruby-1.9.3-p286/gems/activerecord-4.0.2/lib/active_record/connection_adapters/abstract/database_statements.rb:210:in `within_new_transaction'
     # /home/nir0/.rvm/gems/ruby-1.9.3-p286/gems/activerecord-4.0.2/lib/active_record/connection_adapters/abstract/database_statements.rb:202:in `transaction'
     # /home/nir0/.rvm/gems/ruby-1.9.3-p286/gems/activerecord-4.0.2/lib/active_record/transactions.rb:209:in `transaction'
     # /home/nir0/.rvm/gems/ruby-1.9.3-p286/gems/activerecord-4.0.2/lib/active_record/transactions.rb:323:in `with_transaction_returning_status'
     # /home/nir0/.rvm/gems/ruby-1.9.3-p286/gems/activerecord-4.0.2/lib/active_record/transactions.rb:275:in `save!'
     # ./spec/acts_as_taggable_on/utf_spec.rb:20:in `block (2 levels) in <top (required)>'
     # /home/nir0/.rvm/gems/ruby-1.9.3-p286/gems/rspec-core-2.13.1/lib/rspec/core/example.rb:114:in `instance_eval'
     # /home/nir0/.rvm/gems/ruby-1.9.3-p286/gems/rspec-core-2.13.1/lib/rspec/core/example.rb:114:in `block in run'
     # /home/nir0/.rvm/gems/ruby-1.9.3-p286/gems/rspec-core-2.13.1/lib/rspec/core/example.rb:254:in `with_around_each_hooks'
     # /home/nir0/.rvm/gems/ruby-1.9.3-p286/gems/rspec-core-2.13.1/lib/rspec/core/example.rb:111:in `run'
     # /home/nir0/.rvm/gems/ruby-1.9.3-p286/gems/rspec-core-2.13.1/lib/rspec/core/example_group.rb:390:in `block in run_examples'
     # /home/nir0/.rvm/gems/ruby-1.9.3-p286/gems/rspec-core-2.13.1/lib/rspec/core/example_group.rb:386:in `map'
     # /home/nir0/.rvm/gems/ruby-1.9.3-p286/gems/rspec-core-2.13.1/lib/rspec/core/example_group.rb:386:in `run_examples'
     # /home/nir0/.rvm/gems/ruby-1.9.3-p286/gems/rspec-core-2.13.1/lib/rspec/core/example_group.rb:371:in `run'
     # /home/nir0/.rvm/gems/ruby-1.9.3-p286/gems/rspec-core-2.13.1/lib/rspec/core/command_line.rb:28:in `block (2 levels) in run'
     # /home/nir0/.rvm/gems/ruby-1.9.3-p286/gems/rspec-core-2.13.1/lib/rspec/core/command_line.rb:28:in `map'
     # /home/nir0/.rvm/gems/ruby-1.9.3-p286/gems/rspec-core-2.13.1/lib/rspec/core/command_line.rb:28:in `block in run'
     # /home/nir0/.rvm/gems/ruby-1.9.3-p286/gems/rspec-core-2.13.1/lib/rspec/core/reporter.rb:34:in `report'
     # /home/nir0/.rvm/gems/ruby-1.9.3-p286/gems/rspec-core-2.13.1/lib/rspec/core/command_line.rb:25:in `run'
     # /home/nir0/.rvm/gems/ruby-1.9.3-p286/gems/rspec-core-2.13.1/lib/rspec/core/runner.rb:80:in `run'
     # /home/nir0/.rvm/gems/ruby-1.9.3-p286/gems/rspec-core-2.13.1/lib/rspec/core/runner.rb:17:in `block in autorun'

Finished in 0.36067 seconds
2 examples, 1 failure

Failed examples:

rspec ./spec/acts_as_taggable_on/utf_spec.rb:16 # Unicode saves russian tags good

it's postgres specific. i'd remind that 2.4.1 works good. breaks only when capitalized characters are used, if i use 'русский', it works all good as well

nir0 avatar Feb 01 '14 18:02 nir0

managed to fix by replacing

./lib/acts_as_taggable_on/tag.rb:29:        where(["lower(name) = ?", name.downcase])
./lib/acts_as_taggable_on/tag.rb:41:          lowercase_ascii_tag = as_8bit_ascii(tag).downcase
./lib/acts_as_taggable_on/tag.rb:106:          as_8bit_ascii(str).downcase

with

./lib/acts_as_taggable_on/tag.rb:29:        where(["lower(name) = ?", name.mb_chars.downcase])
./lib/acts_as_taggable_on/tag.rb:41:          lowercase_ascii_tag = as_8bit_ascii(tag).mb_chars.downcase
./lib/acts_as_taggable_on/tag.rb:106:          as_8bit_ascii(str).mb_chars.downcase
DB='postgresql' rspec spec/acts_as_taggable_on/utf_spec.rb 
fatal: Not a git repository (or any of the parent directories): .git
..

Finished in 0.48094 seconds
2 examples, 0 failures

sorry, i don't have experience of making pull requests, hope it helps to fix the problem anyways

nir0 avatar Feb 01 '14 18:02 nir0

hmm now it breaks under sqlite... seems like sqlite behaves encodings wrong

nir0 avatar Feb 01 '14 18:02 nir0

@nir0 Thanks for following up with this.. here's some pointers on making a PR. https://help.github.com/articles/creating-a-pull-request http://www.element84.com/github-pull-requests-made-easy.html I'll walk you through it, if you want.

bf4 avatar Feb 11 '14 01:02 bf4

sqlite only up or downcase ascii chars. unless you load ICU extension (as stated in their docs http://sqlite.org/lang_corefunc.html) I opened a PR related to this issue for non-sqlite databases. The thing was the order of methods (mb_chars, downcase and force_encoding)

leo-souza avatar Mar 15 '14 15:03 leo-souza

I'm also getting the same error: ActiveRecord::RecordInvalid: Validation failed: Tag can't be blank from /Users/DaniG2k/.rvm/gems/ruby-2.1.5/gems/activerecord-4.1.8/lib/active_record/validations.rb:57:in 'save!' when trying to save entries such as "Kenzaburo Ōe, Shinzō Abe". The tags are definitely present so I believe the "tag can't be blank" is a bug in acts_as_taggable_on.

DaniG2k avatar Dec 14 '14 14:12 DaniG2k

@DaniG2k please supply gem and database version

nir0 avatar Dec 14 '14 14:12 nir0

@nir0 sure thing:

  • acts-as-taggable-on (3.4.2)
  • activerecord (4.1.8)
  • pg (0.17.1)

DaniG2k avatar Dec 14 '14 15:12 DaniG2k

@DaniG2k this issue was related to lower() database function and/or ruby #downcase function, but should be fixed already. for example, in pg:

# select lower('Kenzaburo Ōe');
    lower     
--------------
 kenzaburo ōe

in ruby:

'Kenzaburo Ōe'.downcase
 => "kenzaburo Ōe" 
'Kenzaburo Ōe'.mb_chars.downcase.to_s
 => "kenzaburo ōe"

as a result, gem tries to find or create tag with uniq name, fails to create one (already exists), and tries to find it and fails as well, since cannot downcase multibyte name properly.

there's huge monkeypatch, which will save you loads of time when you deal with multibyte chars. example: config/initializers/mb_chars.rb

class String
  def downcase
    self.mb_chars.downcase.to_s
  end
end

also you can provide other methods, like upcase, capitalize, reverse etc. result:

$ rails c
Loading development environment (Rails 4.1.1)
2.0.0-p195 :001 > 'Kenzaburo Ōe'.downcase
 => "kenzaburo ōe"

this approach is not ideal, maybe, it may hit performance someday, but when you need to get around bugs like this quickly it's still possible. hope it helps.

nir0 avatar Dec 14 '14 17:12 nir0

Yes I can see that downcasing that name does not properly set the "Ō" to a lowercase value: 'Kenzaburo Ōe'.downcase => "kenzaburo Ōe"

Was this issue never fixed? Monkeypatching doesn't seem to me like it's the right solution here.

DaniG2k avatar Dec 14 '14 17:12 DaniG2k

@DaniG2k i think it's my fault since i got not enough time or was too lazy to push tests i wrote for this issue. so, feel free to use example of tests i supplied and make a pull request :)

maybe there was already a fix coming... as far as i remember they used

where(["lower(name) = lower(?)", name])

instead of

where(["lower(name) = ?", name.downcase])

but i didn't follow this pull request, so maybe they rejected it.

some databases, like sqlite cannot properly downcase multibyte out of box, so we cannot rely on lower() as well...

nir0 avatar Dec 15 '14 00:12 nir0

Same here acts-as-taggable-on (3.4.3) activerecord (4.2.0) pg (0.18.1)

Plus, I don't see the fixes mentioned above merged

ZenGardenDubai avatar Jan 17 '15 17:01 ZenGardenDubai

Prs welcome. I don't think any of the maintainers use it anymore.

B mobile phone

On Jan 17, 2015, at 11:39 AM, Hesham Amiri [email protected] wrote:

Same here acts-as-taggable-on (3.4.3) activerecord (4.2.0) pg (0.18.1)

— Reply to this email directly or view it on GitHub https://github.com/mbleigh/acts-as-taggable-on/issues/464#issuecomment-70375933 .

bf4 avatar Jan 18 '15 05:01 bf4

Looks like the problem is still here. Thanks to using SQL statements with "lower()" commands, it is highly possible that the gem will not work fine in PostgreSQL (and I just didn`t check others). As I can understand, there are still problems in Postgres with stirng functions like lower() or upper() with multibyte characters when the database created without specifying the needed language (like ru_RU.UTF-8). I created the database by rake db:create, and the encoding is set to unicode in databases.yml, but it created with default "C" locale. And for this locale lower() and upper() functions not works. For sure, if I set the LC_COLLATE to something like "ru_RU.UTF-8", this functions works fine... But for me, in this part this gem too depends on database settings and adapter.

sintro avatar Apr 26 '16 18:04 sintro

problem is still here...

mb_chars not helped :(

chip-and-dail avatar Jul 04 '16 01:07 chip-and-dail

I had the same problem. When I tried to use an existing Cyrillic tag, I was not able to create a record. I've got rollback all the time with the message 'Validation failed: Tag can't be blank'.

You can fix it by adding this to the initializer:

ActsAsTaggableOn.force_lowercase = true

It is not perfect, but at least if fixed my issue with act as taggable and Cyrillic. From now, all your tags will be downcased.

Yakubiv avatar Apr 21 '20 07:04 Yakubiv