ActiveRecord changes my binary column to a string column, for some reason, on migration - ruby-on-rails

Using Ruby on Rails 3 and ActiveRecord 3.2.18. I have a binary column in my database. It holds binary stuff, and actually I have a bunch of records in production with that column filled. So in my db/schema.rb file I had...
...
t.binary "tin"
...
Now, after running a migration that touches this table but doesn't change that column, my schema says...
...
t.string "tin"
...
Well... I know that a string might be binary, and binary might be a string, depending on how it's stored in the database, and maybe these equate to the same column type in the end, but why is this happening and what can I do to fix it? Is it safe to deploy this change to production or will it hose my binary columns?

When you run a rake command such as rake db:migrate, Rails will recreate the schema.rb file from the schema in your own personal database. So it sounds like your database has the tin field setup as a varchar field. If your migrations set up your database this way and your production server has the same database then I wouldn't count on the production server to do the right thing. So you may need to look into how to really set a binary field.
On the other hand, if your database is setup properly and it's just the schema file that's not then it may be because... schema can't interpret every database-specific column type. In these cases, you can switch your schema to dump to schema_dump.sql instead of to schema.rb. So check this Stack Overflow post for more on that.

Related

Make a new column (migration) between two other columns?

Is there a quick/easy way to make a migration that adds a new column between two existing columns?
Note: I googled and couldn't find an obvious answer. But I also am curious if it's even good practice (since if for some reason other column/s were removed, then the migration may fail?)
If you haven't commited your changes to production you can reorder migrations by rolling them back and then changing the timestamps in the file name.
If thats not an alternative you can actually re-order the columns on some databases directly with SQL even if its not part of the migrations DSL. Migrations are after all really just a DSL to create SQL strings and run them in a repeatable way across environments.
If you can't generate the SQL you want with the DSL you can always use execute to execute a raw DSL string.
# MySQL example
class ReorderYourTableName < ActiveRecord::Migration[5.2]
def change
execute "alter table yourTableName change column yourColumnName yourColumnName dataType after yourSpecificColumnName;"
end
end
However on some DBs you can't actually reorder the columns without extensive steps of creating new columns and shuffling the data around.

Why is my ActiveRecord updated_at timstamp column defaulting to negative Infinity?

I recently migrated my database from Postgres to MySQL, as well as upgrading from Rails 2 to Rails 5.
The documentation says that the default for both created_on and updated_on columns should be the current time, when created. For some reason, my updated_on column is now defaulting to -Infinity which is making some of my code freak out. What could be causing this?
It turns out the problem was caused by the migration tool I used to migrate the MySQL database to Postgres, called NMIG. NMIG migrates not just the data, but the schema as well, and there's no way to stop it from overwriting the schema even if you already have one setup. Well, for whatever reason, the mapping it uses for the updated_on column (and presumably updated_at columns too?) defines the default as -Infinity!
In order to get around this, I created a fresh PG database by updating my database.yml with a new database name, running db:create and db:schema:load and then used pg_dump to dump the postgres data, and pg_restore -a to restore just the data, without overwriting the schema. Tada! :)

Is it safe to reorder columns in schema.rb for Rails 4/Postgres?

Running Rails 4 with Postgres 9.4 in development and production. I've got a large table that has grown by migrations over time. Because of the many different columns on the table, I want to reorder things so that the columns are grouped more logically. In other words, some column elements naturally group together based on what information they capture.
I found a discussion on using after: in a migration to reorder columns (using ALTER TABLE in SQL), at this stack overflow discussion. I then went ahead and set up a migration to do that. After running the migration I notice that my schema.rb file hasn't changed. Looking at the columns in the database (postgres on development), nothing has changed there either.
Further research led me to the Postgres wiki, which states there is currently no support for altering column position in Postgres.
This isn't mission critical, but it would make life easier. My question is:
If I simply move lines in the schema.rb file up or down in order to position them as desired, will that cause any problems? Since I expect to provision any new database with rake db:schema:load, it wouldn't seem like that should break anything. Further, since the previous migrations aren't materially changed (just the order of columns they output to schema.rb) everything should be internally consistent, no?
If that's a bad idea, can I simply go back into the earlier migrations, add the syntax for after: :some_column to each column element so they correctly set up the schema.rb file?
My assumption is that when I rebuild my production database from scratch with seed data, it will use the schema structure to correctly create the table in the desired order. Right now it's not a real, deployed database with end users, so it doesn't seem like an issue. Using option #1 above seems like the easiest solution, as long as it doesn't break anything.
Many people new to postgresql often ask if it has support for altering
column positions within a table. Currently it does not; if you want to
change column positions, you must either recreate the table, or add
new columns and move data. The idea of allowing re-ordering of column
position is not one the postgresql developers are against, it is more
a case where no one has stepped forward to do the work.
ref
If I simply move lines in the schema.rb file up or down in order to
position them as desired, will that cause any problems?
no. It does nothing with column order in PG.
If that's a bad idea, can I simply go back into the earlier migrations, add the syntax for after: :some_column to each column element so they correctly set up the schema.rb file?
after: :some_column option does nothing with column order if you use PG
The order of your columns does not matter to Ruby or Rails.
As to whether it matters to any code you wrote, only you and your tests can answer that. If you're only using ActiveRecord and not doing any straight SQL that references column number, you should be fine.
As a workaround, you can use annotate to document your models in the code and then reorder the created comment there.
Of course, that will probably be overwritten by annotate once you run it again. And it will only make your life easier if you look at the table structure, but it won't help if you manually run SQL queries with SELECT * in your db.

schema fields ordering on a rails migration

it is possible to tell rails to keep id columns at the top of the schema and timepstamps at the bottom, when adding some fields to a table through a migration?
What I want is to have always this fields in the same position when playing with rails on the console, I know it's possible to reorder them in schema.rb and reload it but I'm looking for a cleaner approach suitable for production environments too.
thank you
You can something like this (probably currently in Mysql only) from Rails 2.3.6+:
add_column :table_name, :column_name, :column_type, after: :other_column_name
or
change_table :the_table do |t|
t.column_type :column_name, after: :other_column_name
end
Sources:
- In a Rails Migration (MySQL), can you specify what position a new column should be?
- https://rails.lighthouseapp.com/projects/8994/tickets/3286-patch-add-support-for-mysql-column-positioning-to-migrations
You may be interested in the fix-db-schema-conflicts gem which automatically sorts columns alphabetically while generating the db/schema.rb file.
Timestamps would not necessarily be last in the list, but the schema will not rely on the order in which columns were added (by migrations).

return model with lowercase columns

I have a rails program that is accessing a legacy database with UPPERCASE table columns.
I want to be able to type user.firstname rather than user.FIRSTNAME
How do I make ActiveRecord retrieve the lowercase version of these column names to allow me to use lowercase attributes in the model?
It might be easier to change the column names with migrations. Otherwise you will have to change the gems that you are using and then pack them in vendor/gems to keep as they degrade.
script/generate migration down_case_table_names_and_columns
write the migration
rake db:migrate
For each table:
rename_table :OLD_NAME, :new_name
For each column:
rename_column :COLUMN_NAME, :column_name
problems
You might not have to change the name of the tables, fyi - you might get an error about changing the table names. I have never changed a table name so I don't know if this will work. In therms of changing column names there will be no problem.
This is probably the best way to deal with this if changing column names isn't feasible: https://github.com/reidmix/legacy_mappings

Resources