简体   繁体   中英

Rails migration won't create NOT NULL constraints

I have this db migration for my Rails 3.2 plugin:

class CreateIssueChangeApprovements < ActiveRecord::Migration
  def change
    create_table :issue_change_approvements do |t|
      t.timestamps
      t.references :issue, :null => false
      t.references :user, :null => false
      t.string :field_type, :limit => 30
      t.string :old_value
      t.string :value
      t.integer :approved_by_id
      t.boolean :is_closed, :default => 0
      t.string :status, :default => '', :limit => 30
    end
    add_index :issue_change_approvements, :issue_id
    add_index :issue_change_approvements, :user_id
  end
end

Once I run it against a MySQL database, I see no NOT NULL constraints on issue_id and user_id fields as well as no foreign keys.

Can anyone tell me what is the right way to do this?

UPD:

The weird thing here is that when I go to MySQL Workbench and generate a script for my newly created table, i get this:

CREATE TABLE `issue_change_approvements` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `created_at` datetime NOT NULL,
  `updated_at` datetime NOT NULL,
  `issue_id` int(11) NOT NULL,
  `user_id` int(11) NOT NULL,
  `field_type` varchar(30) DEFAULT NULL,
  `old_value` varchar(255) DEFAULT NULL,
  `value` varchar(255) DEFAULT NULL,
  `approved_by_id` int(11) DEFAULT NULL,
  `is_closed` tinyint(1) DEFAULT '0',
  `status` varchar(30) DEFAULT '',
  PRIMARY KEY (`id`),
  KEY `index_issue_change_approvements_on_issue_id` (`issue_id`),
  KEY `index_issue_change_approvements_on_user_id` (`user_id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;

However when I run a statement like this:

insert into issue_change_approvements(value) values('hello')

it executes successfully and adds a row with lots of NULL values.

UPD 2: This is what describe issue_change_approvements shows:

+----------------+--------------+------+-----+---------+----------------+
| Field          | Type         | Null | Key | Default | Extra          |
+----------------+--------------+------+-----+---------+----------------+
| id             | int(11)      | NO   | PRI | NULL    | auto_increment |
| created_at     | datetime     | NO   |     | NULL    |                |
| updated_at     | datetime     | NO   |     | NULL    |                |
| issue_id       | int(11)      | NO   | MUL | NULL    |                |
| user_id        | int(11)      | NO   | MUL | NULL    |                |
| field_type     | varchar(30)  | YES  |     | NULL    |                |
| old_value      | varchar(255) | YES  |     | NULL    |                |
| value          | varchar(255) | YES  |     | NULL    |                |
| approved_by_id | int(11)      | YES  |     | NULL    |                |
| is_closed      | tinyint(1)   | YES  |     | 0       |                |
| status         | varchar(30)  | YES  |     |         |                |
+----------------+--------------+------+-----+---------+----------------+

Rails does not create any constraints by default. The null: false option will just not allow null values for this sql field, but it will not add a constraint. Instead of foreign_key constraints in rails you usually just set the desired option on model relationship, eg has_many :issues, dependent: :destroy I guess this strategy was chosen for faster schema migrations with less downtime.

However there is an option to use constraints on db level by explicitly specifying them. You can use the foreigner gem prior to rails 4.2 and with rails 4.2 the dsl for them is included by default.

See Have Some (Referential) Integrity with Foreign Keys

2.5 Foreign Key Support

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM