I am struggling with rails and db:migrate. I have a migration with this code
class SetDefaultInstallmentsForLicenses < ActiveRecord::Migration
def up
License.where(code: 'LEADER').each do |leader|
puts "Modifying license #{leader.id} with code #{leader.code}"
leader.installment_available = true
leader.installment_number = 5
leader.save
puts "After save #{leader.installment_available} #{leader.installment_number}"
leader = License.find(leader.id)
puts "After save #{leader.installment_available} #{leader.installment_number}"
end
end
def down
end
end
After running the migration there is this output
== SetDefaultInstallmentsForLicenses: migrating ==============================
Modifying license 3 with code LEADER
After save true 5
After save f
== SetDefaultInstallmentsForLicenses: migrated (0.0037s) =====================
It's clearly visible that the migration was executed, record was found, changed and saved, but after reloading the record, the changes are not there. What's wrong?
When you run db:migrate, rails will check a special table in the database which contains the timestamp of the last migration applied to the database. It will then apply all of the migrations with timestamps after that date and update the database table with the timestamp of the last migration.
DB migration is moving data from one or more source platforms to another target database. There are several reasons for migrating from one database to another. For example, a business might want to save resources by switching to a cloud-based database.
5 Changing Existing Migrations You must rollback the migration (for example with bin/rails db:rollback ), edit your migration, and then run bin/rails db:migrate to run the corrected version.
db:reset: Resets your database using your migrations for the current environment. It does this by running the db:drop , db:create , db:migrate tasks. db:rollback: Rolls the schema back to the previous version, undoing the migration that you just ran. If you want to undo previous n migrations, pass STEP=n to this task.
leader.save
puts "After save #{leader.installment_available} #{leader.installment_number}"
==> After save true 5
Above is only showing the value of installment_available
and installment_number
fields from local variable leader
, it is NOT pulling the value from database. This does not mean that the fields were successfully saved in database.
leader = License.find(leader.id)
puts "After save #{leader.installment_available} #{leader.installment_number}"
BUT the above is fetching the record from database and clearly shows that the updates were not saved in the database.
Instead of leader.save
, use leader.save!
. This way if record was not saved then you will know exactly why it was not saved because of the raised exception .
UPDATE
As per OP's answer given on this question
I tried to put
License.reset_column_information
before the code and it seems to be working now. I don't have clue why this is needed here. All my other migrations seem to be working properly.
I did little bit of research what exactly License.reset_column_information
did. I found Using Models in Your Migrations which says:
When using a local model, it's a good idea to call Product.reset_column_information to refresh the Active Record cache for the Product model prior to updating data in the database.
Hope this helps you to understand why License.reset_column_information
was required.
I tried to put
License.reset_column_information
before the code and it seems to be working now. I don't have clue why this is needed here. All my other migrations seem to be working properly.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With