On my migration file I have a number of new fields creation.
create_table :mytable do |t|
t.string :my_field, null: false
.........
And I am getting the following
Metrics/AbcSize: Assignment Branch Condition size for change is too high. [<1, 17, 0> 17.03/17]
What is the proper way to avoid that?
It's a common practice to exclude the db folder in your .rubocop.yml.
AllCops:
Exclude:
- 'db/**/*'
Most of the time we Ignore ./db folder in rubocp.yml file. Other than that we can disable cops for a specific block of code. Here is the answer Rubocop, how to Disable/Enable cops on blocks of code
Related
I have been using papertrail on a project for about a year with no issues. Right now I'm using it on the latest available version (10.3.1), with ruby 2.4.9 and rails 5.1.7. But recently when I ran rake db:migrate the versions table was altered automatically on my schema, removing the rails default id as primary key and adding a bigint field also called id:
create_table "versions", id: false, force: :cascade do |t|
t.bigint "id", null: false
t.string "item_type", null: false
t.integer "item_id", null: false
t.string "event", null: false
t.string "whodunnit"
t.text "object"
t.datetime "created_at"
t.text "object_changes"
t.index ["item_type", "item_id"], name: "index_versions_on_item_type_and_item_id"
end
This change made rails start complaining about ActiveRecord::IrreversibleOrderError, as no primary key was defined for the versions table. Now I'm wondering, what happened? Does this have something to do with rails 5.1 changing ids to bigint? It makes no sense to me as i've been on the same rails versions (5.1.7) since the start, and this change was made about 4 years ago.
Thanks.
Ok, so I'm still a bit confused, mostly as to why the schema was changed and versions had no primary key. But I think the issue with ActiveRecord::IrreversibleOrderError was caused by a bump on rails_admin (upgraded from 1.4.3 to 2.0.2). For some reason rails_admin now displays the versions table by default on the left menu, inside a PaperTrail group. That combined with the fact that ActiveRecord wasn't being able to order the versions table (as there was no primary key or ordering configured), made ActiveRecord start to raise the IrreversibleOrderError exception.
To fix this I added the following line to rails_admin initializer (config/initializers/rails_admin.rb):
RailsAdmin.config do |config|
...
config.excluded_models = [PaperTrail::Version]
...
end
I also executed a SQL instruction to add id as primary key on versions again (allowing to keep the versions section on rails_admin, even though I removed it):
ALTER TABLE versions ADD PRIMARY KEY (id);
You could add this to a migration (execute("SQL GOES HERE")), but it's kind of weird, cause if you reset your DB and run the migrations from scracth it will complain of the primary key being defined twice on the same table (at least, that was what happened in my experience).
I still don't think this is the final solution, as I don't understand the source of the error, so I won't accept it as the solution for now. If anyone can shed any light, will be greatly appreciated!
I recently looked at my schema.rb file and was alarmed to find that certain columns that do exist in my database do not appear, and some tables are missing entirely. The missing columns were added to the database through "def change add_column" migrations, though some columns that were added in that way do appear as expected in schema.rb.
On closer inspection, I realized that schema.rb has not been updated since I created the Users table.
20151019205241_create_users.rb:
class CreateUsers < ActiveRecord::Migration
def change
create_table :users do |t|
t.string :name
t.string :email
t.timestamps null: false
end
end
end
This has not caused an issue for me in practice, but I thought schema.rb was supposed to be kept automatically updated, and that it would be important to have it updated in order to recreate the database. Can anyone help me figure out why it would not be updating?
One possibility is that it stopped being updated when I switched my database from sqlite3 to postgresql. I don't remember exactly, but I think the timing makes sense.
You can use rake db:schema:dump to re-create the file from the current database structure.
Schema file is independent from the driver so migrating from sqlite3 to PostgreSQL shouldn't matter. Make sure that version for definition in the file is not greater than current the current date. You can also add the whole file to the question's snippet.
My Rails 5 schema.rb file has an options: section for each create_table that I do not want. What I have is:
create_table "accounts", id: false, force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|
but what I want is:
create_table "accounts", id: false, force: :cascade do |t|
Since this is a generate file, I don't want to edit it manually.
The reason I don't want the options section is because for a fast TDD loop, I want to use SQLite in memory when RAILS_ENV=test but MySQL in development and production.
How do I prevent DB adapter specific options from being generated and put into the schema?
Rails 5 broke the Schema dump format
In Rails 5 the core team decided to change the schema dump format and there were basically two issues with the new schema format:
1) the create_table statements now have options which are specific for the adapter, e.g. MySQL as in the OP's example.
2) the dumped columns do not show :limit statements if the value is the default value for the column type.
Why is that bad?
1) ActiveRecord is supposed to be DB agnostic, and some people use the schema files to load them into a different kind of database, e.g. load the schema file into a SQLite DB for faster testing.
SQLite does not understand the MySQL specific options, and breaks miserably.
2) Limits between different versions of the same kind of database could change over time, and limits could definitely change when you go from one DB to another DB.
Therefore it is not a good idea to just not show the actual value of the "default" limit.
Work Around
It is a terrible idea to monkey patch ActiveRecord. I hate having to do this, but that was the easiest way to get our schema files back to a DB-agnostic state, so we could do testing with SQLite.
If you are dumping your schema FROM MySQL on Rails 5.0,
then you can fix it by adding these two files to your Rails 5.0 project:
config/initializers/active_record/schema_dumper.rb
config/initializers/active_record/connection_adapters/abstract/schema_dumper.rb
These two files contain the original code form the 5-0-stable branch of Rails, slightly modified to not do (1) and (2).
It's not pretty, but it will keep you generating the same dump format as before.
Hopefully the core team will fix the issue soon.
If you have a better solution, which allows cross-DB usage of schema files, please comment or post a better solution.
I'm really not a big fan of monkey-patching :-(
The Rails core team is aware of this and locked the thread down because they were tired of hearing about it. I wouldn't look for a fix any time soon. While I agree that testing in the same db as you're prod environment as a rule of thumb, this is not always a good idea.
Forcing it is a really, really bad idea.
https://github.com/rails/rails/issues/26209
Let's say I have a migration that creates a table 'pages' , this is my migration:
class CreatePages < ActiveRecord::Migration
def up
create_table :pages do |t|
t.string "name" , :limit => 50
t.integer "permalink"
t.integer "position"
t.timestamps
end
end
def down
drop_table :pages
end
end
and that I've created the appropriate migration file X_create_pages.rb and ran it(the table is created in the database).
Now after a few days I realize the structure isn't complete and I need to add another column to my pages table .
What is the best practice , do I create a new migration file with add_column method or do I just change the current migration file's up method -e.g just add my columns to the up method (and then move down a version and then up again - so to run the up method?)
The practice should be you create a new migration to add the new column. This becomes the simplest and risk free path. Of course, we can talk about unseen circumstances!
Updating original migration files should not be used after application is released to production; at least this is what the practice should be. But, this also depends on applications, if you don't have a table that is referenced elsewhere then backing up the data, adding the column and restoring the data is also a possibility which is enabled by this approach of directly modifying the original migration file and rolling down that version and migrating up that version again.
While you are on development, the choice I guess is yours. You could choose either!
Once a migration has been checked into source control it shouldn't be changed.
Modifying a migration on your development environment providing it hasn't been checked into source control is perfectly fine.
Once a migration has been checked in it may have been run by your team mates on their development environment or even been deployed and run in production.
Changing previously committed migrations is going to make you very unpopular in your team very quickly as team mates struggle to understand why their database schema is different from yours but all the migrations have been run.
Now in rails we can use
t.string instead of t.column
using t.string is easy.But
t.column is a deprecated feature?
any other advantage of using t.datatype other than easiness.
Is there any way to convert all current migrations to new style easily.
t.column is not deprecated. You can use it without losing any sleep. The t.string syntax is just a "sugar" on top of the good old t.column.
1) sed. :)
2) Do you need to convert them? If you have schema.rb checked in as advised (or even a local copy somewhere), that should represent the current state of the database, right? If you do a "rake db:schema:dump" that should set you up with all the migrations up to that point in one schema.rb file, then you can go from there.