I have this inside create_table:
t.string 'email', :default => '', :null => false
And then in another migration have this:
change_column('admin_users', 'email', :string, :limit => 100)
After I run everything, in schema.rb I get this:
t.string "email", limit: 100, default: "", null: false
Wasn't change_column supposed to overwrite everything in the previous definition? Why did :default and null were left? I was watching a tutorial where it said change_column overwrites everything. Was there some recent Rails version when this was changed?
Not necessarily, change_column does not erase previously-set details. Let's say you were changing the column so you could simply add a NULL constraint. It wouldn't make sense to have to add in all the other previously-set contraints as well.
If you want to change the default or null settings, just do so in the change_column method.
change_column('admin_users', 'email', :string, :limit => 100, :default => "", :null => true)
Otherwise, to erase everything, do remove_column then add_column:
remove_column('admin_users', 'email')
add_column('admin_users', 'email', :string, :limit => 100)
change_column doesn't overwrite everything, it just makes the changes you specify. So it added the limit to the column, but that's all.
Related
So I mistakenly created a table with fields which should have been NOT NULL.
I need to create a migration to change the fields from NULLABLE to NOT NULL, but some rows exist which are already NULL.
Hoe can I update these rows and change the fields? I tried this:
def change
change_column :countries, :effective_date, :date, :null => false, :default => Time.now
change_column :countries, :expiry_date, :date, :null => false, :default => Time.new(9999,12,31)
end
But this failed with an error:
Mysql2::Error: Invalid use of NULL value: ALTER TABLE
Any ideas? Needs to work on both mysql and sql server..
First ensure there are no NULLs and then change the constraint.
Option 1:
Country.where(effective_date: nil).update_all(effective_date: Time.now)
Country.where(expiry_date: nil).update_all(expiry_date: Time.new(9999,12,31))
change_column :countries, :effective_date, :date, :null => false
change_column :countries, :expiry_date, :date, :null => false
Option 2:
change_column_null :countries, :effective_date, false, Time.now
change_column_null :countries, :expiry_date, false, Time.new(9999,12,31)
You can set the default value for all NULL columns before adding the constraint, for example:
execute "UPDATE study_sites SET patients_recruited = 0 WHERE patients_recruited IS NULL"
change_column :study_sites, :patients_recruited, :integer, default: 0, null: false
I am new to Ruby on Rails. I have a migration called create user
class CreateUsers < ActiveRecord::Migration
def change
create_table :users do |t|
t.column :username, :string, :limit => 25, :default => "", :null => false
t.column :hashed_password, :string, :limit => 40, :default => "", :null => false
t.column :first_name, :string, :limit => 25, :default => "", :null => false
t.column :last_name, :string, :limit => 40, :default => "", :null => false
t.column :email, :string, :limit => 50, :default => "", :null => false
t.column :display_name, :string, :limit => 25, :default => "", :null => false
t.column :user_level, :integer, :limit => 3, :default => 0, :null => false
end
User.create(:username=>'test',:hashed_password=>'test',:first_name=>'test',:last_name=>'test',:email=>'test#test.com',:display_name=> 'test',:user_level=>9)
end
end
When I run rake db:migrate the table is created with the columns as mentioned above but the test data are not there
mysql>select * from users;
Empty set (0.00 sec)
EDIT I just dropped the whole database and restarted the migration and now it is showing the following error.
rake aborted!
An error has occurred, all later migrations canceled:
Can't mass-assign protected attributes: username, hashed_password, first_name, last_name, email, display_name, user_level
What am I doing wrong please help?
Thank you.
add
attr_accessible :username, :hashed_password, :first_name, :last_name, :email, :display_name, :user_level
to your user.rb
That's Rails way of prohibiting users to create or update objects via a param hash. You need to specify your User attributes as attr_accessible in your model:
example :
class User
attr_accessible :username, :firstname (etc)
end
Read more about Mass Assignment here.
just to complete the answer about testing environment. You can run rake db:test:prepare to check the migrations and load schema !
I'm using rails 3.2 with the following migration and created_at/updated_at both get generated. I was under the impression that adding t.timestamps was what caused those columns to get generated.
class CreateContactsCountries < ActiveRecord::Migration
def change
create_table :contacts_countries do |t|
t.string :name, :official_name, :null => false
t.string :alpha_2_code, :null => false, :limit => 2
t.string :alpha_3_code, :null => false, :limit => 3
end
add_index :contacts_countries, :alpha_2_code
end
end
Please delete the table and check again becuase
By default, the generated migration will include t.timestamps (which creates
the updated_at and created_at columns that are automatically populated
by Active Record).
Ref this
I'm using Rails 3.0.3 (don't ask) and when I run a migration for table with decimal column and set :default => 0 it's re-setting the column's scale and precision to (10,0).
def self.up
create_table :courses do |t|
t.integer :user_id
t.string :name
t.decimal :distance, :precision => 5, :scale => 2, :default => 0
t.text :notes
t.timestamps
end
end
When I remove the :default=>0 option from the migration the column's scaled and precision are correct: (5,2)
I tried running a change_column migration with only :default =>: 0 set, but the column's scale and precision were re-set to (10,0)
change_column :courses, :distance, :decimal, :default => 0.0
I know I can go into MySQL and correct the precision and scale of the column, but wondering if I'm doing something wrong or if this is a bug?
Google reveals no information so I think I'm doing something wrong.
Try this one: t.decimal :distance, :precision => 5, :scale => 2, :default => 0.00
I was also stuck on this one, and i cant find a solution to it. Eventually i had to go into mysql and change the required precision, scale and default value, i used this from here with a few modifications
mysql> ALTER TABLE question ADD (price INTEGER);
mysql> ALTER TABLE question DROP price;
mysql> ALTER TABLE question ADD (frig DECIMAL(5,2));
mysql> ALTER TABLE question CHANGE frig price DECIMAL(5,2);
mysql> ALTER TABLE question ALTER status SET DEFAULT '0';
mysql> ALTER TABLE question MODIFY price INTEGER;
Also try :default => 0.0 #note the 0.0 as the default value must be in the data type specified i.e. decimal
Hope it helps.
You can also do
def change
change_column :courses , :distance, :decimal, :precision => 5, :scale => 2, :null => false, :default => '0'
end
I am just trying this right now and seems to work.
Active Records Migrations
class ChangeVisitratioFormatInCampaigns < ActiveRecord::Migration[5.0]
def change
reversible do |dir|
change_table :campaigns do |t|
dir.up { t.change :visitratio, :decimal, :precision => 5, :scale => 4, :default => 1 }
dir.down { t.change :visitratio, :integer }
end
end
end
end
Is the following correct?
change_column :tablename, :fieldname, :limit => null
If you previously specified a limit in a migration and want to just remove the limit, you can just do this:
change_column :users, :column, :string, :limit => 255
255 is the standard length for a string column, and rails will just wipe out the limit that you previously specified.
Updated:
While this works in a number of Rails versions, you would probably be better suited to use nil like in Giuseppe's answer.
change_column :users, :column, :string, :limit => nil
That means the only thing you were doing wrong was using null instead of nil.
Here's what happened to me.
I realized that a string field I had in a table was not sufficient to hold its content, so I generated a migration that contained:
def self.up
change_column :articles, :author_list, :text
end
After running the migration, however, the schema had:
create_table "articles", :force => true do |t|
t.string "title"
t.text "author_list", :limit => 255
end
Which was not OK. So then I "redid" the migration as follows:
def self.up
# careful, it's "nil", not "null"
change_column :articles, :author_list, :text, :limit => nil
end
This time, the limit was gone in schema.rb:
create_table "articles", :force => true do |t|
t.string "title"
t.text "author_list"
end
Change the column type to :text. It does not have a limit.
change_column :tablename, :fieldname, :text, :limit => nil
Strings without limit is not something most databases support: you have to specify size in varchar(SIZE) definition.
Although you could try, I would personally go with :limit => BIG_ENOUGH_NUMBER. You may also consider using CLOB type for very big texts.
To make it db-driver-independent one should write smth like this:
add_column :tablename, :fieldname_tmp, :text
Tablename.reset_column_information
Tablename.update_all("fieldname_tmp = fieldname")
remove_column :tablename, :fieldname
rename_column :tablename, :fieldname_tmp, :fieldname
I was the same boat today, trying to remove a limit I'd added to a text field and it wouldn't take. Tried several migrations.
Rails 4.2.7.1
Ruby 2.3.1p112
In the end, the only thing that worked was specifying a limit of 255. Trying to adjust to anything else wouldn't work for me.