Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to specify a collation for a column when creating a model with rails

Quick question: How to specify a collation for a specific column when creating a model with rails?

I haven't found any option in the rails API doc but I think it's very important to explicit declare a collation for some attributes.

Let's say that the default collation is utf8_unicode_ci. But when creating an Users model the password field's collation should be utf8_bin.

So, when using rails like this

rails g model Users username:string password:string

you can't specify password to use utf8_bin collation.

Any way to do it?

EDIT: The generated SQL should be something like this:

CREATE TABLE `user` (
  `id`               INT(11) UNSIGNED NOT NULL AUTO_INCREMENT  COMMENT 'Unique ID',
  `username`         VARCHAR(32) NOT NULL                      COMMENT 'Nick/username',
  `password`         VARCHAR(32) COLLATE utf8mb4_bin           COMMENT 'Encoded password',

  PRIMARY KEY(`id`),
  INDEX(`username`)
);

I don't care if you can't do it directly via a command and you have to modify the db/timestamp_create_users.rb file. But the point is being able to use the rails migrations.

like image 787
danikaze Avatar asked Aug 10 '14 11:08

danikaze


People also ask

How do you set collation when creating a table?

You can set the collation by adding the T-SQL COLLATE clause to the CREATE TABLE and ALTER TABLE statements. When you use those statements, you define the column and its properties, including any collation settings.

What is table column collation?

The table collation is the same as the database collation, except if left blank, it will use the database as its default, then connection-specific, and then finally the server's collation.

How do I add a reference column in rails?

When you already have users and uploads tables and wish to add a new relationship between them. Then, run the migration using rake db:migrate . This migration will take care of adding a new column named user_id to uploads table (referencing id column in users table), PLUS it will also add an index on the new column.


1 Answers

Sadly it seems that rails does not provide any high level way to set column-level collation so you have to fall back to SQL at least a little. Here's how I did it:

class CreateUsers < ActiveRecord::Migration                                     
  def change                                                                    
    create_table :users do |t|                                                  
      t.string   :password                                                      
    end                                                                         

    reversible do |dir|                                                         
      dir.up {                                                                  
        change_column :users, :password, "VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_bin"
      }                                                            
    end                                                                         
  end                                                                           
end   

The reversible block is there just to enable rollbacks because rails would not know how to revert change_column without the original value.

Then you can check the collation on the mysql cli with:

SHOW TABLE STATUS;

you should see your default collation there - probably utf8_unicode_ci. Then do:

SHOW FULL COLUMNS FROM users;

And there you should see utf8_bin at the password field.

like image 174
Renra Avatar answered Oct 18 '22 21:10

Renra