Using STI fails to migrate database - ruby-on-rails

Been working on this particular issue for a while and thought it was time to ask for help. I've had a look at the following links but no luck
PG undefinedtable error relation users does not exist
https://github.com/rails/rails/issues/3279
And my issue is somewhat similar to this https://github.com/rails/rails/issues/6470 but not exactly.
I have a class called type_tables which is the base class for the STI here is the schema for STI
create_table "type_tables", force: :cascade do |t|
t.string "title"
t.string "desc"
t.string "type"
t.string "uom"
t.index ["title"], name: "index_type_tables_on_title"
t.index ["type"], name: "index_type_tables_on_type"
end
Now, this type table is only a base class in my project and other types such as device_type, certificate_type etc inherit from it.
The model for type_table
class TypeTable < ApplicationRecord
validates :title, presence: true, uniqueness: true
end
The other device_type model
class DeviceType < TypeTable
has_many :certificates
#this is where the error originates
GARMIN_ID = find_by(title: "Garmin").id
#when i use some constant value rails successfully executes the
db:create task in my rake file
GARMIN_ID = 22
end
Now, here's the interesting bit, it only shows this behaviour the first time i,e when there is no existing table in my Postgres database. When I successfully create and migrate my application schema and when the tables are present this line will work everytime.
GARMIN_ID = find_by(title: "Garmin").id
My idea is that since it tries to find the column in the type_tables relation and the relation doesn't exist it throws a no relation exists error. Although the error you see on the console is
2018-08-07 02:24:49.281 UTC [69] FATAL: database "myappdb" does not
exist
mlcot_api | /usr/local/bundle/gems/activerecord-5.1.3/lib/active_record/connection_adapters/postgresql_adapter.rb:699:in
`rescue in connect': FATAL: database "myappdb" does not exist
(ActiveRecord::NoDatabaseError)
When I create the db manually using
docker-compose run api rake db:create
And then run docker-compose up I get
ERROR: relation "type_tables" does not exist at character 566
/usr/local/bundle/gems/activerecord- `async_exec': PG::UndefinedTable:
ERROR: relation "type_tables" does not exist
(ActiveRecord::StatementInvalid)
WHERE a.attrelid = '"type_tables"'::regclass
NOTE: I know the work around and have my app working but I have a dependancy on a particular branch which has all of the commented code
required to build my db for the first time which I want to remove.
Any help appreciated and thanks in advance.

It's a very bad idea to access your database while loading model definitions. Don't do that.
Instead, consider using a class method that only retrieves the value the first time it's needed:
def self.garmin_id
#garmin_id ||= find_by(title: "Garmin").id
end
Personally I'd strongly discourage even that much persistence -- better to spend one query retrieving it fresh for each request that needs it -- but that's more a matter of design judgement.

Related

Ahoy gem created mutually exclusive migration?

I tried to learn new stuff and use Ahoy gem for my private project. While doing research online, I encountered one repo with Rails 4.2 and Ahoy 1.6 and one thing struck me. Then I started googling and it seems like it's not a single repo issue only.
class CreateVisits < ActiveRecord::Migration
def change
create_table :visits, id: false do |t|
t.uuid :id, default: nil, primary_key: true
(...)
rest of code omitted for readability
Am I missing something, or are those mutually exclusive lines? (not to mention primary key being nil by default?)
I ran almost the same migration locally (without Ahoy gem, with changed table name), and I got nicely-looking db/schema.rb (at first glance - no errors yet), but of course when I try create new object, I hit ActiveRecord::NotNullViolation: PG::NotNullViolation: ERROR: null value in column "id" violates not-null constraint error
In my opinion, I'd have write something like this to make it work, or am I missing something really important here that blocks me from persisting an object in DB?
class CreateVisits < ActiveRecord::Migration
def change
create_table :visits do |t|
t.uuid :id, primary_key: true
(...)
Seems like this thing was not related to this Gem, but to other Dev running migration outside Rails migrations and not letting anyone know. This created some confusion between environments.

Cannot Rollback migration due to wrong data type

I have created a new migration in order to add a new Paperclip attachment to a current model already owning a Paperclip attachment.
Though made an error and defined the data type as attachment instead of add_attachment :
class AddDetailsToProfilepics < ActiveRecord::Migration[5.0]
def change
add_column :profilepics, :finalimage, :attachment
end
end
Then i noticed no extra column was created by paperclip (*_file_name *_content_type) and realise I made a mistake.
Though now no Rollback is possible as it triggers an error. I created a new migration (to remove this column with wrong data type) and got a similar error:
undefined method 'to_sym' for nil:NilClass
When looking at shema.rb the data type is not entered:
...
t.integer "y"
t.integer "width"
t.integer "height"
t. "finalimage"
t.index ["professionnel_id"], name: "index_profilepics_on_professionnel_id"
I tried to change it to string and re-run the new "remove_column" migration but same error.
Ok I found solution. Kill both development.sqlite3 and schema.rb. Delete reference to the wrong column in the last migration. Do a rails db:migrate
Everything will be reconstructed.
The DB is empty though

Rails migration fails creating table in Postgres

As described in the title, I have a migration in my Rails app which creates a table. We have a Postgres database. When I run the migration in development, it fails:
ActiveRecord::StatementInvalid: PG::Error: ERROR: current transaction is aborted, commands ignored until end of transaction block
: CREATE TABLE "feedback_questions" ("id" serial primary key, "survey_id" integer, "question_text" text, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL)
The migration is long, but the table creation is the first thing that happens. It looks like this:
def up
create_table :feedback_questions do |t|
t.integer :survey_id
t.text :question_text
t.timestamps
end
# ...
end
It looks to me like this isn't an issue with the migration, but with the database (the error is coming from PG). The error message is similar to this question, but it's not saying anything about what's wrong - just that there's an error. (Also, the table doesn't exist yet; I've checked.)
How can I get more data to debug this?
The error message was a red herring. The issue was not with the table creation; the issue was with the format of the migration itself. I was defining a few models in the migration which used tables created in the #up method. When rake tried to start the migration, it looked for tables for those rows, and flipped when it couldn't find them. The create statement just happened to be the first command not run after the error.

rails test error:"table projectname_test.destroys doesn't exist"

I just started to learn Ruby on Rails. And when I used the rails to do the test, an error occurred as:
UserTest#test_the_truth:
ActiveRecord::StatementInvalid: Mysql2::Error: Table 'eula_test.destroys' doesn't exist: SHOW FULL FIELDS FROM destroys
I don't know what is eula_test.destroys and how should I solve this problem.
check your migration files. on db/migrate.rb and db/shema.rb you can check out if you have that table.
Seems no-one has been able to answer this, but best guess based on the error you are getting it looks like you need a join table because you most likely have a "has_and_belongs_to_many" directive in both your models eula.rb and test.rb
So you need to create a migration: rails g migration CreateEulaTest
then edit the migration to include an index that tells the db to look in eula_test table for the data to join with.
you need edit your migration with the following:
def up
create_table :eula_test, :id => false do |t|
t.integer :eula_id
t.integer :test_id
end
add_index(:eula_test, [:eula_id, :test_id]
end
def down
drop_table :eula_test
end
end
Note: this table does not require it's own ID hence the :id => false
Also, the add_index portion are your foreign keys between the 2 models that allows the database to know that you are going through the table to establish your directive, such as create and destroy etc.
run rails db:migrate for rails 5 or greater, rake db:migrate <5
You may need to check your models to ensure you have the correct has_to_and_belongs_to_many settings.
It is likely you missed this part of the tutorial. Some tutorials don't explain why things are done, they just show you the code and let you figure it out.
rails db:reset should fix it :)

how i can i check the existence of the table

hy
A lot of time when i run rake db:migrate i get an error because the table user or foor or bar exist.
I try to check the existence of table, but that didn't work and i dont know why .
I use rails 3.2.2
class AddDeviseToUsers < ActiveRecord::Migration
#def self.table_exists?(users)
# ActiveRecord::Base.connection.tables.include?(users)
#end
if !table_exists?("users")
def change
create_table(:users) do |t|
## Database authenticatable
t.string :email, :null => false, :default => ""
t.string :encrypted_password, :null => false, :default => ""
end
end
end
You can check the existence of a table with the following command. This question has already been posted and answered here.
ActiveRecord::Base.connection.table_exists? 'users'
However, your code contains errors. You cannot define a method inside an if block with the syntax you're using. Put the block inside your method, instead.
def change
if !table_exists?("users")
# ...
end
end
Also, you should not be getting this kind of errors often, as you state. Migrations are applied sequentially. Creating your users table in a separate migration before adding Devise to it would take care of that problem. If you run into this problem while migrating an existing project from scratch, consider using rake db:schema:load instead.
In your command terminal type in
sqlite3 db/development.sqlite3
then you can search through your database by SQL command. Use .tables to list all tables in the database and you can see if yours is missing or not.
You can also just look at your schema file to see if the migration worked. The table along with all of it's attributes will be listed there.
You should never have multiple migrations that both try to create the same table. You also should not experience errors like this if you're working with rails migrations correctly.
The way rails migrations work is that every time you run rake db:migrate, for every migration file that runs successfully, it stores the number part of the migration file 123456789_create_users_table.rb (123456789 in this case) in a table in your db called schema_migrations. This way if a migration has already been run, it will never get run again.
It doesn't sound like you're working with rails migrations correctly. I suggest reading this thoroughly: http://guides.rubyonrails.org/migrations.html

Resources