I have a migration AddAuthenticableToUser. (rake db:migrate:up VERSION=..) works fine, but when I'm trying to rollback a migration (rake db:migrate:down VERSION=..) it doesn't works. Any errors or warnings. Could you help me with this ?
def self.up
change_table :users do |t|
t.token_authenticatable
end
add_index :users, :authentication_token, :unique => true
end
def self.down
remove_index :users, :authentication_token
remove_column :users, :authentication_token
end
This should be the trick. I think you named your table token_authenticatable and then tried to remove authentication_token.
def self.up
create_table :reviews do |t|
t.column :authentication_token
end
add_index :users, :authentication_token, :unique => true
end
def self.down
remove_index :users, :authentication_token
remove_column :users, :authentication_token
end
Related
I have a migration that give me an error:
class DeviseTokenAuthCreateUsers < ActiveRecord::Migration
def change
unless column_exists? :users, :provider
add_column :users, :provider, :null => false
end
unless column_exists? :users, :uid
add_column :users, :uid, :null => false, :default => "email"
end
unless column_exists? :users, :tokens
add_column :users, :tokens, :text
end
User.reset_column_information
User.all.each{|u| u.save! }
add_index :users, [:uid, :provider], :unique => true
end
end
The error is:
undefined method `to_sym' for {:null=>false}:Hash/Users/scrivoaroby/.rvm/gems/ruby-2.0.0-p481/gems/activerecord-4.1.9/lib/active_record/connection_adapters/abstract/schema_definitions.rb:311:in `add_column'
My rails version is 4.1.9
Any idea?
The third argument for add_column should be the datatype. Instead of something like:
add_column :users, :provider, :null => false
You'll want something like this, with whatever datatype is appropriate for your columns:
add_column :users, :provider, :string, :null => false
This will also need to be done for the :uid column.
I'm complete noob at PostgreSQL, Ruby on Rails..
I'm trying to follow this tutorial (WITHOUT rubymine) http://www.codeproject.com/Articles/575551/User-Authentication-in-Ruby-on-Rails#InstallingRubyMine4
I have as such this to migrate (001_create_user_model.rb):
class CreateUserModel < ActiveRecord::Migration
def self.up
create_table :users do |t|
t.column :username, :string
t.column :email, :string
t.column :password_hash, :string
t.column :password_salt, :string
end
end
def self.down
drop_table :users
end
end
The error I'm getting goes like this:
syntax error, unexpected ':', expecting ';' or '\n'
t.column...sers do |t|
...
C:131071:in 'disable_dll_transaction'
Task:TOP => db:migrate
What about this:
class CreateUserModel < ActiveRecord::Migration
def self.up
create_table :users do |t|
t.string :username, :null => false
t.string :email,:null => false
t.string :password_hash, :null => false
t.string :password_salt, :null => false
t.timestamps
end
end
def self.down
drop_table :users
end
end
I'm in the process of adding Devise to an existing Rails app, with a Users table already defined. The devise generator pushed out the following migration:
class AddDeviseToUsers < ActiveRecord::Migration
def self.up
change_table(:users) do |t|
## Database authenticatable
t.string :email, :null => false, :default => ""
t.string :encrypted_password, :null => false, :default => ""
## Recoverable
t.string :reset_password_token
t.datetime :reset_password_sent_at
## Rememberable
t.datetime :remember_created_at
## Trackable
t.integer :sign_in_count, :default => 0
blah blah blah....
end
add_index :users, :email, :unique => true
add_index :users, :reset_password_token, :unique => true
end
The downward migration isn't generated, and I'm having a heck of a time removing those indexes. I'm seeing different suggested notation in the documentation, and different suggestions online, but none of them seem to be working for me. For example...
def self.down
change_table(:users) do |t|
t.remove :email
t.remove :encrypted_password
t.remove :reset_password_token
blah blah blah...
end
remove_index :users, :email
remove_index :users, :reset_password_token
end
results in...
An error has occurred, this and all later migrations canceled:
Index name 'index_users_on_email' on table 'users' does not exist
which is odd, because if I check the database, sure enough, 'index_users_on_email' is right there...
I've tried other variations, including
remove_index :users, :column => :email
remove_index :users, 'email'
or:
change_table(:users) do |t|
t.remove_index :email
end
...but no dice. I'm running Rails 3.1.0, Ruby 1.9.2, rake 0.9.2.2, with Postgres.
The command that's letting me down is:
bundle exec rake db:rollback STEP=1
after successfully apply the migration up. Any advice?
For the record, the way to remove an index by name is
remove_index(:table_name, :name => 'index_name')
so in your case
remove_index(:users, :name => 'index_users_on_email')
You can also remove the index specifying the columns, which from my point of view is less error prone than writing the name
remove_index :actions, :column => [:user_id, :action_name]
Depending on the database type, you don't need to worry about removing the indexes in the self.down method since the index will automatically be removed from the database when you drop the column.
You can also use this syntax in your self.down method:
def self.down
remove_column :users, :email
remove_column :users, :encrypted_password
remove_column :users, :reset_password_token
end
I'd like to expand on #iWasRobbed's answer. If you have index on just single column then worrying about remove_index doesn't make sense since (just an assumtion!) the DB should be smart enough to cleanup the resources used by that index. But in case you have multiple columns index removing the column will reduce index to still existing columns, which is totally sensible thing to do, but kind of shows where you might want to use remove_index explicitely.
Just for illustration - migration below has that flaw that after being applied up and down it will leave the unique index on email (meaning the down part is not doing its job properly)
class AddIndexes < ActiveRecord::Migration
def up
add_column :users, :action_name, :string
add_index :users, [:email, :action_name], unique: true
end
def down
remove_column :users, :action_name
end
end
Changing the down block to
def down
remove_index :users, [:email, :action_name]
remove_column :users, :action_name
end
will fix that flaw and allow the migration to correctly return DB to the previous state with rake db:rollback
To alter a table and/or its indeces use #change_table inside #change action of a migration. Then you be able to create reversable index removal as follows:
def change
change_table :users do |t|
t.index :email, :unique => true
t.index :reset_password_token, :unique => true
end
end
When you have to drop a table with its index of course with reversable action you can use #drop_table method for SchemaStatements with the #index method of Table class for ConnectionAdapter:
def change
drop_table :users do |t|
t.index :email, :unique => true
t.index :reset_password_token, :unique => true
end
end
In case you have need exactly the #up/down pair in a migration. Use just a #change_table method along with #remove_index method of Table class for ConnectionAdapter:
def up
change_table :users do |t|
t.index :email, :unique => true
t.index :reset_password_token, :unique => true
end
end
def down
change_table :users do |t|
t.remove_index :email, :unique => true
t.remove_index :reset_password_token, :unique => true
end
end
All of the methods are available in Rails version of 2.1.0 or of earlier ones.
Here is my full run of this(in Rails 5):
I have team_id as an index in table vendors. I no longer need this relation. To get rid of it. Did the following:
1) create the migration.
$ rails generate migration RemoveTeam_idFromVendor team_id:integer
2) Running the migration, give me this error. And that is because vendor table has rows whose foreign key references the primary key value of the team table
== 20170727202815 RemoveTeamIdFromVendor: migrating ===========================
-- remove_column(:vendors, :team_id, :integer)
rake aborted!
StandardError: An error has occurred, this and all later migrations canceled:
SQLite3::ConstraintException: FOREIGN KEY constraint failed: DROP TABLE "vendors"
3) To solve this and get the migration running, I did the following(Note: i am in dev):
$ rake db:drop
Dropped database 'db/development.sqlite3'
Dropped database 'db/test.sqlite3'
$ rake db:create
Created database 'db/development.sqlite3'
Created database 'db/test.sqlite3'
$ rake db:migrate
~
~
~
== 20170727202815 RemoveTeamIdFromVendor: migrating ===========================
-- remove_column(:vendors, :team_id, :integer)
-> 0.0185s
== 20170727202815 RemoveTeamIdFromVendor: migrated (0.0185s) ==================
rails generate devise User I got this=>
class DeviseCreateUsers < ActiveRecord::Migration
def self.up
create_table(:users) do |t|
t.database_authenticatable :null => false
t.recoverable
t.rememberable
t.trackable
# t.encryptable
# t.confirmable
# t.lockable :lock_strategy => :failed_attempts, :unlock_strategy => :both
# t.token_authenticatable
t.timestamps
end
add_index :users, :email, :unique => true
add_index :users, :reset_password_token, :unique => true
# add_index :users, :confirmation_token, :unique => true
# add_index :users, :unlock_token, :unique => true
# add_index :users, :authentication_token, :unique => true
end
def self.down
drop_table :users
end
end
But i want to create a users table with username, email, password, role, group, mark, created_at, modified_at columns.
How can i do this ?
Is this structure correct to have username, password, email, group, role, mark ?
class DeviseCreateUsers < ActiveRecord::Migration
def self.up
create_table(:users) do |t|
t.database_authenticatable :null => false
t.recoverable
t.rememberable
t.trackable
# t.encryptable
# t.confirmable
# t.lockable :lock_strategy => :failed_attempts, :unlock_strategy => :both
# t.token_authenticatable
t.string :username
t.string :password
t.string :email
t.string :group
t.string :role
t.integer :mark
t.timestamps
end
add_index :users, :email, :unique => true
add_index :users, :reset_password_token, :unique => true
# add_index :users, :confirmation_token, :unique => true
# add_index :users, :unlock_token, :unique => true
# add_index :users, :authentication_token, :unique => true
end
def self.down
drop_table :users
end
end
What are these?
t.database_authenticatable :null => false
t.recoverable
t.rememberable
t.trackable
You can perform a migration to add some fields to the user table.
For example:
rails g add_fields_to_users username:string # as well as other fields you need
Then, in order to add columns to your table run:
rake db:migrate
Devise has already generated some columns you need like: email, password, created_at, updated_at...
For adding roles to your user model you should watch the cancan screencast: railscasts and also read the doc in order to see some updates.
EDIT:
If you want to add fields manually you could add them in your self.up method before running your migration:
def self.up
create_table(:users) do |t|
#...
t.rememberable
t.trackable
t.string :username
#... your other attributes here
end
I created the following with the devise rails plugin. How do I go about adding a username string and unique user_id integer to the users table? Also is it necessary to create a users_controller when using devise? Or is that not necessary?
class DeviseCreateUsers < ActiveRecord::Migration
def self.up
create_table(:users) do |t|
t.database_authenticatable :null => false
t.recoverable
t.rememberable
t.trackable
# t.encryptable
# t.confirmable
# t.lockable :lock_strategy => :failed_attempts, :unlock_strategy => :both
# t.token_authenticatable
t.timestamps
end
add_index :users, :email, :unique => true
add_index :users, :reset_password_token, :unique => true
# add_index :users, :confirmation_token, :unique => true
# add_index :users, :unlock_token, :unique => true
# add_index :users, :authentication_token, :unique => true
end
def self.down
drop_table :users
end
end
The guide linked to in the comments will provide good reading on migrations, which you will come to use very frequently. In short, however, you can generate the migration needed by doing:
rails g migration add_username_to_users username:string
Once the migration is created, you can actually add the column by doing:
rake db:migrate
To answer to your last question, no, you don't need to create a controller to use devise
Although you could do if you wanted to have an index or show page for your users. In which case you would need to modify your routes a little