Ruby on Rails 4 - Using Rake on Heroku - ruby-on-rails

I was moving my app from Nitrous.io which uses SQLite to Heroku for production which uses Postgres, and I got the following error. 2 things, I don't get why it won't do change_column, and I definitely don't understand their "hint". How can I go about implementing properly?
-- change_column(:messages, :sender, :integer)
PG::DatatypeMismatch: ERROR: column "sender" cannot be cast automatically to type integer
HINT: Specify a USING expression to perform the conversion.
: ALTER TABLE "messages" ALTER COLUMN "sender" TYPE integer
The attributes were strings, and I wanted to change to integers so I could reference them.
Any help?
Below is my db migration that it is referencing:
class ChangeSenderReceiverToInteger < ActiveRecord::Migration
def change
change_column(:messages, :sender, :integer)
change_column(:messages, :receiver, :integer)
end
end

Try:
change_column(:messages, :sender, 'integer USING CAST(sender AS integer)')
Ref: http://makandracards.com/makandra/18691-postgresql-vs-rails-migration-how-to-change-columns-from-string-to-integer

Related

How can I resolve "invalid input sequence for type bytea" in a Rails migration of a pg column from text to binary (bytea)?

I have a Rails application with a pg database, and the type of the 'input' column in one of my tables is text. I have discovered that some of my input files aren't any particular text encoding, so they need to be treated as binary data.
Thus, I created a migration:
class ChangeProgramsColumnsInputOutputToBinary < ActiveRecord::Migration[6.0]
def change
change_column :programs, :input, 'bytea USING input::bytea'
end
end
However, when I run this migration, I get:
-- change_column(:programs, :input, "bytea USING input::bytea")
rails aborted!
StandardError: An error has occurred, this and all later migrations canceled:
PG::InvalidTextRepresentation: ERROR: invalid input syntax for type bytea
It seems that PostgreSQL doesn't like the type-cast from the text column to bytea. But why is this? Isn't bytea general enough to represent anything contained in a text column? Why is the cast failing?
I suppose there might be some specific syntax to coax pg into performing this cast but I haven't been able to find this in the pg documentation.
-------- Update -----------
I tried this, but it is truncating the binary files:
change_column :programs, :input, 'bytea USING convert_to(input,\'UTF8\')'

How to migrate string data type to hstore

I am upgrading my rails 3 application to rails 4. And according to the guide I removed this line from my model
serialize :my_serialized_column, ActiveRecord::Coders::Hstore.new({})
but now I am getting the error while looping over :my_serialized_column which was previously hash
undefined method `each' for "":String
Now my question is how do I change the data_type of my column without losing the data I already have
So you can just change the data type of the column from string to hstore.
One thing to keep in mind is you need to cast the data to hstore or you will get the following error
PG::DatatypeMismatch: ERROR: column "my_serialized_column" cannot be cast automatically to type hstore
HINT: You might need to specify "USING my_serialized_column::hstore".
To avoid the error you can specify the casting
class ChangeMySerializedColumnTypeToHstore < ActiveRecord::Migration
def up
change_column_null :my_table, :my_serialized_column, ''
change_column :my_table, :my_serialized_column, "hstore USING my_serialized_column::hstore"
end
def down
change_column :my_table, :my_serialized_column, :string, default: ''
end
end

Issue with Running Rails Migration in Heroku

I created a migration in my development to change the column type from integer to date in my client table.
Migration:
class UpdateGradToDate < ActiveRecord::Migration
def change
change_column :clients, :grad_id, :date
end
end
Which worked fine in development. However, once I push it to Heroku, I got the following error message.
PG::DatatypeMismatch: ERROR: column "grad_id" cannot be cast automatically to type date
HINT: You might need to specify "USING grad_id::date".
: ALTER TABLE "clients" ALTER COLUMN "grad_id" TYPE date
I'm not sure how to correct this problem. I'm thinking perhaps using rails console and changing the column type there but I'm not sure if that's the best solution.
I also tried creating a new migration using using this syntax as well
class ChangeDateFormatInMyTable < ActiveRecord::Migration
def up
change_column :clients, :grad_id, :integer
end
def down
change_column :clients, :grad_id, :date
end
end
I'm not really sure what to do at this point.
The issue here is clearly explained by the PostgreSQL error:
column "grad_id" cannot be cast automatically to type date
You are trying to convert a field that stores an integer, into a Date. The field could contain anything, including a value such as 10, 0 or -200. How those value could ever be converted into a Date?
What PostgreSQL is telling you is that you need to help him with the conversion.
Your best way is:
rename grad_id into grad_id_legacy
create a new grad_id Date field
run a script that reads each value from grad_id_legacy and stores the corresponding, converted Date value into grad_id

heroku: PG::InvalidTextRepresentation: ERROR: invalid input syntax for integer: “”

I have a currency(ccy) column on my event model and it's currently a string, I'd like to change it to a integer.
Although it works on my local environment, the following error was displayed when I try heroku run rake db:migrate to heroku.
rake aborted!
StandardError: An error has occurred, this and all later migrations canceled:
PG::InvalidTextRepresentation: ERROR: invalid input syntax for integer: ""
: ALTER TABLE "events" ALTER COLUMN "ccy" TYPE integer USING CAST(ccy AS integer)
The migration file as below.
class ChangeCcyToEvents < ActiveRecord::Migration
def change
change_column :events, :ccy, 'integer USING CAST(ccy AS integer)'
end
end
I found the similar question PG::InvalidTextRepresentation: ERROR: invalid input syntax for integer: "M", so I changed migration file as below. But the result is the same.
class ChangeCcyToEvents < ActiveRecord::Migration
def change
Event.where(ccy: '').update_all(ccy: '')
change_column :events, :ccy, 'integer USING CAST(ccy AS integer)'
end
end
There is no value in all ccy column so far.
It would be appreciated if you could give me any advice.
Your migration is trying to convert a "" into an integer, which postgres complais about it (and it should, because it's not a valid conversion).
You should update your content for invalid cases before changing the column type:
class ChangeCcyToEvents < ActiveRecord::Migration
def up
Event.where("ccy IS NULL OR ccy = ''").update_all({ccy: '0'})
change_column :events, :ccy, 'integer USING CAST(ccy AS integer)'
end
def down
raise ActiveRecord::IrreversibleMigration
end
end
Perhaps is not complaining in development (localhost) because you're using a different version of postgreSQL than Heroku.
Next time, try using default values in migrations for this kind of columns.

Altered my database structure in development, so tried to reset Heroku deployed database. Erased it but now I can't migrate my db over

so my app was working fine. I created a new model and some associaitons, rendering all the old seed data in my heroku app useless. so I tried to reset it and populate it again. but I can't even migrate my db to heroku with the heroku rake db:migrate command. I'm using SQLite, but it seems my error is related to Postgres. I don't know what that means, if anything
Here is the error:
rake aborted!
An error has occurred, this and all later migrations canceled:
PGError: ERROR: column "to" cannot be cast to type "pg_catalog.int4"
: ALTER TABLE "emails" ALTER COLUMN "to" TYPE integer
Tasks: TOP => db:migrate
My migration:
class ChangeDataTypeForEmailUsers < ActiveRecord::Migration
def self.up
change_column :emails, :to, :integer
change_column :emails, :from, :integer
end
def self.down
change_column :to, :string
change_column :from, :string
end
end
What is the problem? My deployed app was working fine. I added a new model and figured I should reset the deployed database. So I ran heroku pg:reset then pushed my code to heroku. then tried to migrate the db, but it doesn't work! What have I done? I have been trying to figure this out for the last 4 hours. I can't think straight anymore. Any help would be greatly appreciated
Further to Hishalv's answer. If you can't use "change_column" then you can go the roundabout way:
def self.up
rename_column :emails, :to, :old_to
add_column :emails, :to, :integer
Email.reset_column_information
Email.all.each {|e| e.update_attribute(:to, e.old_to.to_i) }
remove_column :emails, :old_to
end
It's roundabout, and the Email.all.each might be slow - but it'll work and correctly cast for you.
If you're only going to use it on prod, then you might be able to replace the ruby-updates with a SQL UPDATE command that does the same thing in-database using a POSTGRES-specific cast method.
As per heroku docs here
Cause: PostgreSQL doesn’t know how to cast all the rows in that table to the specified type. Most likely it means you have an integer or a string in that column.
Solution: Inspect your records and make sure they can be converted to the new type. Sometimes it’s easier to just avoid using change_column, renaming/creating a new column instead.
I also was in this position before and i did not find a solution so i had to create a new column, postgresql seems to be sensitive when i comes to this issues. Hope it helps

Resources