I have the following Rails migration:
class AddTextToReference < ActiveRecord::Migration
def change
add_column :references, :source_text, :text
end
end
I now realise that :source_text also needs to be set to :limit => nil.
How can I add :source_text to my schema without losing the data stored in my :source_text column?
I am using PostgreSQL locally and for production on Heroku.
try change_column method
def change
change_column :references, :source_text, :text, :limit => nil
end
Related
I have a migration file called [timestamp]_create_posts.rb.
I found that I made the column with a wrong data type. I need to make t.text :content instead of t.string :content.
I include the code from the above file:
class CreatePosts < ActiveRecord::Migration
def change
create_table :posts do |t|
t.string :title
t.string :content
t.timestamps null: false
end
end
end
I kinda know that I should not directly change the file but rollback migration and change the schema and do the migration again. But I wasn't sure whether that's a right way to do it. It would be really nice if someone can guide me through this. I'm not really familiar with Rails.
You should not rollback anything. You should create a new migration, that will change a column with following content:
class UpdatePostsChangeContentColumn < ActiveRecord::Migration
def change
change_column :posts, :content, :text, limit: 60000 # or whatever
end
end
or, even better, to supply the reasonable rollback of this migration:
class UpdatePostsChangeContentColumn < ActiveRecord::Migration
def up
change_column :posts, :content, :text, limit: 60000 # or whatever
end
# back to previous version
def down
change_column :posts, :content, :string
end
end
The other option if you are just in the development is just to Drop you database and recreate it. Then you can modify that file, but THIS IS NOT ADVISED. I have done this again in development where i didn't care about recreating my database
rake db:drop
rake db:create
rake db:migrate
There are two ways to change the column in table:
You can use rake db:rollback VERSION=file_version and then after that you can change datatype manually.
Generate another migration file. e.g rails g migration RemoveColumnToPost and the you can add following codes:
def up
change_column :posts, :content, :text
end
def down
change_column :posts, :content, :string
end
And then use rake db:migrate
i get the error
PGError: ERROR: type modifier is not allowed for type "text"
LINE 1: ...ng(255), "desc" character varying(255), "content" text(255),...
when i do a heroku run rake db:reset
i understand that postgresql needs an unlimited type for 'text' and in my latest migration file i have...
class ChangeLessonsTable < ActiveRecord::Migration
def change
change_table :lessons do |t|
t.change :content, :text, :limit => nil
end
end
end
i still keep getting the error though. any ideas why? i ran rake db:reset, rake db:migrate, and git push to make sure my local db changed. then i ran git heroku push and heroku run rake db:reset but i keep getting that error. am i missing something? thanks
You should be able to leave off the :limit entirely:
class ChangeLessonsTable < ActiveRecord::Migration
def change
change_table :lessons do |t|
t.change :content, :text
end
end
end
If that doesn't work then you could try separate up and down actions:
def up
change_column :lessons, :content, :text
end
def down
change_column :lessons, :content, :string
end
As an aside, if you're targeting PostgreSQL you should just use :text and forget about the :string (AKA varchar) column type, PostgreSQL treats them all the same internally. The only time you should bother with varchar/:string is when your data integrity requires a specific upper limit on the string size.
I am looking for ways to write migrations in rails that can be executed against the database many times without failing.
For instance let say I have this migration:
class AddUrlToProfile < ActiveRecord::Migration
def self.up
add_column :profile, :url, :string
end
def self.down
remove_column :profile, :url
end
end
If the url column already exists in the Profile table (if the schema.rb has been modified unexpectedly for instance), my migration will fail saying that it's a duplicate!
So how to execute this migration only if it has to?
Thanks
You can do something like this:
class AddUrlToProfile < ActiveRecord::Migration
def self.up
Profile.reset_column_information
add_column(:profile, :url, :string) unless Profile.column_names.include?('url')
end
def self.down
Profile.reset_column_information
remove_column(:profile, :url) if Profile.column_names.include?('url')
end
end
This will reset the column information before it begins - making sure that the Profile model has the up-to-date column information from the actual table. It will then only add the column if it doesn't exist. The same thing happens for the down function, but it only removes the column if it exists.
If you have multiple use cases for this you could factor the code out into a function and re-use that in your migrations.
For Rails 3.X, there's the column_exists?(:table_name, :column_name) method.
For Rails 2.X, you can check the existence of columns with the following:
columns("<table name>").index {|col| col.name == "<column name>"}
...or if you're not in a migration file:
ActiveRecord::Base.connection.columns("<table name>").index {|col| col.name == "<column name>"}
If it returns nil, no such column exists. If it returns a Fixnum, then the column does exist. Naturally, you can put more selective parameters between the {...} if you want to identify a column by more than just its name, for example:
{ |col| col.name == "foo" and col.sql_type == "tinyint(1)" and col.primary == nil }
This should work
def self.table_exists?(name)
ActiveRecord::Base.connection.tables.include?(name)
end
if table_exists?(:profile) && !Profile.column_names.include?("url")
add_column :profile, :url, :string
end
Wrapping my migration in a conditional worked for me.
Rails 4.X
class AddUrlToProfile < ActiveRecord::Migration
unless Profile.column_names.include?("url")
def self.up
add_column :profile, :url, :string
end
def self.down
remove_column :profile, :url
end
end
end
I'm a beginner at Ruby On Rails and am trying to get a migration to work with the name Priorities
So, here is the code I use in my migration:
class Priorities < ActiveRecord::Migration
def self.up
create_table :priorities do |t|
t.column :name, :string, :null => false, :limit => 32
end
Priority.create :name => "Critical"
Priority.create :name => "Major"
Priority.create :name => "Minor"
end
def self.down
drop_table :priorities
end
end
This results in the following error though:
NOTICE: CREATE TABLE will create implicit sequence "priorities_id_seq" for serial column "priorities.id"
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "priorities_pkey" for table "priorities"
rake aborted!
An error has occurred, this and all later migrations canceled:
uninitialized constant Priorities::Priority
Is this some problem with turning ies to y for converting something plural to singular?
Also, the full --trace log is here: http://pastebin.com/w6usBSng
Using the following command, I was able to get the same error:
script/generate migration priorities
This is happening because you don't have a Priority class. You probably intended on running this command:
script/generate model Priority name:string
This fixes the problem
EDIT
Apparently you don't want a Priority model. In this situation, I have no idea why, but you can circumvent this by using execute in your migration methods.
Try something like this:
class CreatePriorities < ActiveRecord::Migration
def self.up
create_table :priorities do |t|
t.column :name, :string, :null => false, :limit => 32
end
execute "insert into priorities (name) values ('Critical');"
execute "insert into priorities (name) values ('Major');"
execute "insert into priorities (name) values ('Minor');"
end
def self.down
drop_table :priorities
end
en
d
Yes. Your table name is Priorities and Model name also (i guess) Priorities. So it get crashed at "Priority.create :name => "Critical".
This should be
class Priorities < ActiveRecord::Migration
def self.up
create_table :priorities do |t|
t.column :name, :string, :null => false, :limit => 32
end
Priorities.create :name => "Critical" #Where "Priorities" is your Model Name
Priorities.create :name => "Major"
Priorities.create :name => "Minor"
end
def self.down
drop_table :priorities
end
end
The Redmine plugin tutorials explain how to wrap core models but what I need is to add another column to the journals table.
I need a boolean field inserted in the journals model. Creating another model with a 'belongs_to :journal' relation seems like an overkill.
Can this be done with a plugin?
I should note that I am a rails newbie.
You just have to create the appropriate migration.
In your plugin's directory, create the file db/migrate/update_journal.rb with the following :
class UpdateJournal < ActiveRecord::Migration
def self.up
change_table :journal do |t|
t.column :my_bool, :boolean
end
end
def self.down
change_table :journal do |t|
t.remove :my_bool
end
end
end
Then you can execute the task rake db:migrate_plugins RAILS_ENV=production to update your database with the new field.
After executing the migration, your journal database will have the my_bool field that you'll be able to call like every other field.
I was able to extend the existing user model using the following code:
class UpdateUsers < ActiveRecord::Migration
def up
add_column :users, :your_new_column, :string, :default => ''
add_column :users, :your_other_new_column, :string, :default => ''
end
def down
remove_column :users, :your_new_column
remove_column :users, :your_other_new_column
end
end
Also I needed to name the migration file in way that it began with a number eg. myplugin/db/migrate/001_update_user.rb