I'm attempting to change the nil possibility of a boolean attribute on the existing column :access_titles on the :profiles table. That column exists because of this migration:
class AddAccessItemsToProfiles < ActiveRecord::Migration
def self.up
add_column :profiles, :access_items, :boolean, :default => true
end
def self.down
remove_column :profiles, :access_items, :boolean, :default => nil
end
end
To change nil, I tried generating a migration as I always have:
rails g migration ChangeColumnNull :profiles :access_items :null => false
But that did nothing, so I did a standalone migration:
rails g migration AddChangeColumnNullToAccessItems
And within that I added:
class AddChangeColumnNullToAccessItems < ActiveRecord::Migration
def self.up
change_column_null :profiles, :access_items, :boolean, false
end
def self.down
change_column_null :profiles, :access_items, :boolean, true
end
end
I then ran rake db:migrate, restarted my server and saw no changes. So I tried:
class AddChangeColumnNullToAccessItems < ActiveRecord::Migration
def self.up
change_column_null :profiles, :access_items, false
end
def self.down
change_column_null :profiles, :access_items, true
end
end
Then did the same thing: rake db:migrate, restarted the server, and nothing changed.
What am I doing wrong? I was hoping to only have the boolean value of :access_items be true and false without having to dump the database.
UPDATE: Trying change_column_null :profiles, :access_items, false I got an error:
-- change_column_null(:profiles, :access_items, false)
rake aborted!
An error has occurred, this and all later migrations canceled:
PGError: ERROR: column "access_items" contains null values
: ALTER TABLE "profiles" ALTER "access_items" SET NOT NULL
So, per the advice below I had to insert change_column_null :profiles, :access_items, false, true into my migration.
You can use:
change_column_null :profiles, :access_items, false, 1
The fourth parameter is optional and allows you to set the default value for the column. This is required when you have nulls in a column and you're setting the null value to false.
Related
I am trying to add user:references onto my already existing model. This is what I originally wrote:
rails g model Post title:string description:text
I do this to add the user:references by running rails generate migration add_user_to_posts user:references, I am receiving this error upon running rake db:migrate:
-- create_table(:users)
rake aborted!
StandardError: An error has occurred, this and all later migrations canceled:
SQLite3::SQLException: table "users" already exists
I am reading the error and I understand I already have a User model, however, I want to add this attribute to the Post model, not the User model.
Db file:
Posts:
class CreatePosts < ActiveRecord::Migration[5.0]
def change
create_table :posts do |t|
t.string :title
t.text :description
t.timestamps
end
end
end
Trying to add the user to posts:
class AddUserToPosts < ActiveRecord::Migration[5.0]
def change
add_reference :posts, :user, foreign_key: true
end
end
Users:
class CreateUsers < ActiveRecord::Migration[5.0]
def change
create_table :users do |t|
t.string :name
t.string :uid
t.string :avatar_url
t.timestamps
end
add_index :users, :uid
end
end
However, rake db:migrate gives me the error above.
I installed Devise, raked, and then realized afterwards, that I want to add :confirmable.
Can I go back to the same initial migration and just uncomment out the helper that I want and then rake db:migrate again?
I tried it and it didn't seem to work. But I haven't seen an example of how to create a follow-on migration.
Thanks!
This is what I tried:
1 class AddConfirmableToUsers < ActiveRecord::Migration
2 def self.up
3 change_table :users do |t|
4 t.confirmable
5 end
6 add_index :users, :confirmation_token, :unique => true
7 end
8
9 def self.down
10 remove_column :users, :confirmation_token
11 end
12
13 end
You can add the proper columns yourself like so:
class AddConfirmableToUsers < ActiveRecord::Migration
def self.up
change_table :users do |t|
t.string :confirmation_token
t.datetime :confirmed_at
t.datetime :confirmation_sent_at
end
add_index :users, :confirmation_token, :unique => true
end
def self.down
change_table :users do |t|
t.remove :confirmation_token, :confirmed_at, :confirmation_sent_at
end
remove_index :users, :confirmation_token
end
end
Your migration should work. Did you check your User model to make sure :confirmable is enabled? It's commented out by default.
If you don't mind losing your data you can just do
> rake db:drop
Otherwise you can just edit the initial migration and do a rollback.
# get the current migration version
> rake db:version
> Current version: ****************41
> rake db:rollback ****************40
Make your changes
> rake db:migrate
I've got a migration file which does the following:
class ChangeLoginToUsername < ActiveRecord::Migration
def self.up
remove_column :users, :login, :string
add_column :users, :username, :string
end
def self.down
remove_column :users, :username, :string
add_column :users, :login, :string
end
end
This ran in fine on my local dev but I've now noticed the third parameter for the filed type on remove_column is erroring when I try and run this migration on Heroku. Is there a way to write/run specific migrations just for Heroku? There are 2 further migrations after this one that I need to run...
Any help hugely appreciated as always
It doesn't make sense for remove_column to have a data type:
class ChangeLoginToUsername < ActiveRecord::Migration
def self.up
remove_column :users, :login
....
end
def self.down
remove_column :users, :username
...
end
end
This is probably in another question, but I cannot find it.
I am a relative noobie to Rails. I am trying to add a new column to a table that already has data in it. This column is not going to allow nulls. What is the easiest way to update all the existing records to have a value in this new column? I know it is probably in the up block of my migration, but I don't know what the syntax would be.
def self.up
change_table :reminders do |t|
t.boolean :active
end
#model name is Reminder - how to update data with a value?
end
What you can do is add the column, update all records in the table with the desired value, then change it to not allow nulls.
def self.up
add_column :reminders, :active, :boolean, :default => true
Reminder.update_all( "active = ?", true )
change_column :reminders, :active, :boolean, :default => true, :null => :false
end
Try this:
def self.up
change_table :reminders do |t|
t.boolean :active, :default => true #or your value
end
#model name is Reminder - how to update data with a value?
end
I'm trying to run the following migration
def self.up
add_column :users, :perishable_token, :string
User.all.each { |u| u.reset_perishable_token! }
change_column :users, :perishable_token, :string, :null => false
add_index :users, :perishable_token
end
and the u.reset_perishable_token! code behaves strangely (no return value, doesn't change the database field). Consequently change_column ..., :null => false fails with
users.perishable_token may not be NULL
Even separating the migration into two doesn't do the trick either if I run them with just one rake command.
Part One
def self.up
add_column :users, :perishable_token, :string
add_index :users, :perishable_token
end
Part Two
def self.up
User.all.each { |u| u.reset_perishable_token! }
change_column :users, :perishable_token, :string, :null => false
end
Only if I run the first and second migration in separate rake processes everything runs fine.
What could possibly be the reason and how can I fix it?
I think you need to add...
User.reset_column_information
...after you have added the perishable_token to the users_table, otherwise the User model is out of sync with the database.
I think the User model would only be loaded once per 'rake db:migrate', so it wouldn't help to split the migration in two.