default value to column - ruby-on-rails

I run:
rails generate migration AddHidemsgColumnToPublishers hide_msg:boolean
and the next file was created:
class AddHidemsgColumnToPublishers < ActiveRecord::Migration
def change
add_column :publishers, :hide_msg, :boolean
end
end
I want to set a default value into hide_msg by false.
so I tried:
rails generate migration add_default_value_to_hide_msg
class AddDefaultValueToHideMsg < ActiveRecord::Migration
def up
change_column :publishers, :hide_msg, :boolean, :default => false
end
def down
change_column :publishers, :hide_msg, :boolean, :default => nil
end
end
but I got errors:
rake db:migrate
== AddHidemsgColumnToPublishers: migrating ===================================
-- add_column(:publishers, :hide_msg, :boolean, {:default=>false})
rake aborted!
An error has occurred, this and all later migrations canceled:
PG::Error: ERROR: column "hide_msg" of relation "publishers" already exists
: ALTER TABLE "publishers" ADD COLUMN "hide_msg" boolean DEFAULT 'f'

Just a suggestion.... do not set the default value in the database, as you might face some problems if you want to change it latter on.
I think it is better if you set it in your model.
before_save :set_default_high_msg
def set_default_high_msg
self.high_msg ||= false
end
or even in your controller:
def new
#publisher = Publisher.new
#publisher.high_msg ||= false
...
end

rake db:migrate
== AddHidemsgColumnToPublishers: migrating ===================================
-- add_column(:publishers, :hide_msg, :boolean, {:default=>false})
Above thing means its trying to create colimn which already exist. If you check the class name AddHidemsgColumnToPublishers . This means it trying to execute your first migration in which you don't have default value. This clearly indicates you are doing something wrong.
publishers already has column hide_msg. So check the table description in db console. If you don't have any values in hide_msg then you can manually drop the column and re-run the rake db:migrate. Or you can keep that column as it is and just create migration to add default value.
change_column_default :publishers, :hide_msg, false
Doc: http://apidock.com/rails/ActiveRecord/ConnectionAdapters/SchemaStatements/change_column_default

Related

Modifying migration column not loaded in migration rails

I added two migration which in the first one I add a column to a model, and in the second one, I execute a function that stores a value into the column recently added of some rows.
The problem is that when I run rake db:migrate the second migration throws an error because the first migration was loaded but the database hasn't changed yet, so one approach is to run the command twice (it works).
First Migration :
class AddRegisteredReportToSpecialOfferUse < ActiveRecord::Migration
def up
add_column :special_offer_uses, :registered_report, :boolean, default: false
end
def down
remove_column :special_offer_uses, :registered_report
end
end
Second Migration :
class CreateReportsFromMigrations < ActiveRecord::Migration
def change
OneClass.perform
end
end
the OneClass.perform is a method that makes an update of the attribute added previously
def perform
´´´
special_offer_uses.update_attribute(:registered_report, true)
´´´
end
The error thrown :
StandardError: An error has occurred, all later migrations canceled:
undefined method `registered_report=
Note that the method undefined is the name of the attribute added previously.
I wonder if there is a way to avoid running the command twice without throwing any error.
UPDATE:
I found a solution using reset_column_information method that causes the columns to be reloaded on the next request.
Resets all the cached information about columns, which will cause them to be reloaded on the next request.
The most common usage pattern for this method is probably in a migration, when just after creating a table you want to populate it with some default values
Further information : link
Why not do it all in one migration?
class AddRegisteredReportToSpecialOfferUse < ActiveRecord::Migration
def up
add_column :special_offer_uses, :registered_report, :boolean, default: false
OneClass.perform
end
def down
remove_column :special_offer_uses, :registered_report
end
end

heroku run rake db:migrate gives rake aborted

I'm new to ruby on rails, github and heroku. Now i am doing fixed deposit project in that project i am using database sqlite3 in my localhost and postgres in heroku.
I have add a field called int which datatype is string and i changed the datatype from string to integer. Finally, i decided to change it again from integer to float.
In my local host its working perfecly. But, when i'm trying to run in heroku it shows rake aborted.
heroku run rake db:migrate
it shows the following error message
Running `rake db:migrate` attached to terminal... up, run.4356
Connecting to database specified by DATABASE_URL
Migrating to CreateFds (20140505120047)
Migrating to Changedatatypeforfd (20140506065307)
Migrating to AddMdToFds (20140506080333)
Migrating to AddIntToFds (20140506080404)
Migrating to Changedatatypeforint (20140506103001)
== Changedatatypeforint: migrating ======================
-- change_column(:fds, :int, :integer)
rake aborted!
StandardError: An error has occurred, this and all later migrations canceled:
PGError: ERROR: column "int" cannot be cast automatically to type integer
HINT: Specify a USING expression to perform the conversion.
: ALTER TABLE "fds" ALTER COLUMN "int" TYPE integer
my db files are listed below
20140506080404_add_int_to_fds.rb
class AddIntToFds < ActiveRecord::Migration
def change
add_column :fds, :int, :string
end
end
20140506103001_changedatatypeforint.rb
class Changedatatypeforint < ActiveRecord::Migration
def up
change_column :fds, :int, :integer
end
def down
change_column :fds, :int, :string
end
end
20140508105541_rechangedatatypeforint.rb
class Rechangedatatypeforint < ActiveRecord::Migration
def up
change_column :fds, :int, :float
end
def down
change_column :fds, :int, :integer
end
end
Sorry for my blunder.
Please give me the solution.
Thanks in advance.
Heroku uses PostgreSQL. In PostgreSQL int is a reserved word, you cannot use it as a column name.
Use something else for your int name
change_column :fds, :valid_name, :integer
SQL Key Words
If you want to cast from float to integer, one way to do it is:
class MigrationNameHere < ActiveRecord::Migration
def up
execute('ALTER TABLE fds ALTER COLUMN column_name TYPE integer USING round(column_name);')
end
end
This migration will convert all your float numbers to integer ones and it is not reversible so be careful. I advise you to have a backup before doing this.

How to add default value to a column being added through 'rails g migration' command

I know how to add default value in a migration file already created. i.e.,
`rails generate migration AddTestColumnToTesttable test_status:boolean` to create it.
It will generate this migration:
class AddTestColumnToTable < ActiveRecord::Migration
def change
add_column :table, :test_status, :boolean, :default => true
end
end
But, Can we add the default value through rails g migration command itself?
No, it can't be done from the command line, you need to change it in the migration file
add_column :table, :test_status, :boolean, :default => true
Hope that helps!
**Rails 4.X +**
Still now, as there is no option to add new column to a table with default value defined through terminal in rails migration,
The following steps to be followed to add a new column to an existing table with default value true or false.
1. Run the migration from command line to add the new column
$ rails generate migration add_columnname_to_tablename columnname:boolean
The above command will add a new column in your table.
2. Set the new column value to TRUE/FALSE by editing the new migration file created.
class AddColumnnameToTablename < ActiveRecord::Migration
def change
add_column :tablename, :columnname, :boolean, default: false
end
end
**3. To make the changes into your application database table, run the following command in terminal**
$ rake db:migrate

Why I get error "An error has occurred, this and all later migrations canceled:" when run rake db:migrate

I have followed this guide Using Models In Your Migrations. Now I want to add a new column called suspect type boolean into Question table, it will have default value is false, and I want to update records have created too. This is my migration file:
class AddSuspectToQuestions < ActiveRecord::Migration
class Question < ActiveRecord::Base
end
def change
add_column :questions, :suspect, :boolean, default: false
Question.reset_column_information
Question.all.each do |question|
question.update_attributes!(suspect: false)
end
end
end
But when I run rake db:migrate, it has error:
== AddSuspectToQuestions: migrating ==========================================
-- add_column(:questions, :suspect, :boolean, {:default=>false})
-> 0.3782s
rake aborted!
An error has occurred, this and all later migrations canceled:
Can't mass-assign protected attributes: suspect
I think it needs attr_accesible :suspect, so I added it in Question model, but I still has same error when I run migrate again. I have set this in application.rb too:
config.active_record.whitelist_attributes = true
Anyone has met this problem?
it doesnt work, since you are overwriting the Question Class in your migration.
Remove
class Question < ActiveRecord::Base
end
and try it again.

Why doesn't this simple Rails migration update my database?

I've got a very simple migration that adds a single boolean column:
class AddMuteToPreferences < ActiveRecord::Migration
def self.up
add_column :preferences, :mute_audio, :boolean, :default => false
end
def self.down
remove_column :preferences, :mute_audio
end
end
I run the migration:
== 81 AddMuteToPreferences: migrating =========================================
-- add_column(:preferences, :mute_audio, :boolean, {:default=>false})
-> 1.9043s
== 81 AddMuteToPreferences: migrated (1.9047s) ================================
Looks peachy, right? But, for some reason, there's still no mute_audio column in my preferences table.
I can't figure it out. I've executed add_column before with no problems.
Has anyone ever seen this behavior before?
I see no reason for rails to fail the add of the column. You are probably looking in the wrong database.
The best way to debug this is to enter rails console mode:
script/console development
And create a new preference object and give mute_audio a value:
>> p = Preference.new
(...)
>> p.mute_audio = true
After the first command, you should see some output containing info about the newly created object. You should see that it has mute_autio: false. If setting the attribute mute_audio does not output an error, there's no problem and the new added column is there.

Resources