Skip to content

Tag names case sensitive #42

Description

@rmehner

Hey there,

I have kind of a strange requirement, but it makes sense for the client: tag names have to be case sensitive and a tag named Ruby is not the same as ruby.

So here's what I did:

# config/initializers/gutentag.rb

# don't normalise tag names
Gutentag.normaliser = lambda { |name| name }

# overwrite validations, so uniqueness is not case insensitive as it is the default
class TagValidations
  def self.call(klass)
    new(klass).call
  end

  def initialize(klass)
    @klass = klass
  end

  def call
    klass.validates :name, presence: true, uniqueness: true, length: {maximum: 255}
  end

  private

  attr_reader :klass
end

Gutentag.tag_validations = TagValidations

Which works fine to a certain point, but there's a nuance in MySQL. Depending on the collation of the field (which often is utf8_general_ci, which is a default in many MySQL setups I have seen), the index might be case sensitive or not. If you set a unique index, like we do at

add_index :gutentag_tags, :name, :unique => true
MySQL will treat this index as case insensitive, meaning ruby and Ruby will be the same and therefore will throw an error.

To get it working, you have to change the collation to something that is case sensitive in MySQL (there's a whole bunch of docs about that here https://dev.mysql.com/doc/refman/5.7/en/case-sensitivity.html).

In my case, I wrote this migration:

class ChangeCollationOfGutentagTags < ActiveRecord::Migration[5.2]
  def up
    execute "ALTER TABLE `gutentag_tags` CONVERT TO CHARACTER SET UTF8 COLLATE utf8_bin"
  end

  def down
    execute "ALTER TABLE `gutentag_tags` CONVERT TO CHARACTER SET UTF8 COLLATE utf8_general_ci"
  end
end

and it now works like a charm :)

I don't know if Gutentag can do anything about this (unlikely), but at least this is documented somewhere now :)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions