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, e.g 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.