Join table error on running migration - ruby-on-rails

I have two models in rails 5.1
class Category < ActiveRecord::Base
has_and_belongs_to_many :sub_categories, join_table: "categories_join_table"
end
class SubCategory < ActiveRecord::Base
has_and_belongs_to_many :categories, join_table: "categories_join_table"
end
I have added multiple migrations the problem is when I try to run migration I get the error ERROR: relation "comfort_factor_sub_categories" does not exist because in the migration to create table comfort_factor_sub_categories will run in later migrations. How can I handle this?
Note: I can't change the name of join_table as it is just an example I have long names.

This question is over three years old at the time of this writing, but I just ran into the same problem so I thought I'd share my solution here.
In my case, I was running Rails 6.1, so my error message looked a bit different:
StandardError: An error has occurred, this and all later migrations canceled:
Could not find table 'officers_users'
The officers_users table is a join table that is created in a later migration, but the migration in question doesn't make any use of it, so why was I getting this error?
At first, I thought it might be a Rails bug as my migration was using update_columns to modify the users table, which shouldn't run any callbacks, but then I noticed that the values that I was updating them with were dependent on a computed attribute, which in turn was dependent on the officers_users join table. So Rails was right and I was wrong (once again, hah)! The solution was simply to make the failing migration self-sufficient without needing that computed attribute. Once I did that, everything was good again.
So if you run into the same problem, I would suggest checking your migration with a fine toothed comb and look for any hidden dependencies that might be using the later migration's join table.

If I understood your problem correctly, you have added several migrations and you cannot run them because some relationship is not found.
In that case, you should duplicate the classes in migrations:
class CreateCategories < ActiveRecord::Migration[5.1]
class Category < ActiveRecord::Base
# without declaring the relationship with the table which does not exist yet
end
def up
create_table :categories do |t|
# t.something
end
end
def down
drop_table :categories
end
end
You should then do the same thing for SubCategory.
For creating a proper join_table, you can refer to Rails official documentation

Related

Migrations from scratch breaking as column in model doesn't exist yet

I have following models and association.
class Stock < ApplicationRecord
has_many :stock_components, -> {order(:position)}
...
before_save :set_default_values
def set_default_values
self.material_cost = 0.0 if self.material_cost.nil?
end
...
end
When I run migrations from scratch, a migration that inserts a record in this table, breaks at line self.material_cost = 0.0 if self.material_cost.nil? with following -
Caused by:
ActiveRecord::StatementInvalid: Mysql2::Error: Unknown column 'stock_components.position' in 'order clause': SELECT `stocks`.* FROM `stocks` INNER JOIN `stock_components` ON `stocks`
.`id` = `stock_components`.`component_id` WHERE `stock_components`.`stock_id` = 1 ORDER BY `stock_components`.`position` ASC
This is because migration for adding position hasn't run yet.
What could be solution for this?
That's really unfortunate, but it's a common issue which is almost never addressed.
When a data migration on a model is written, either to change or set values, or to add data, typically one relies on the application model (with all the corresponding callbacks etc).
But then at a later time, more callbacks are added, and previous migrations are broken. Even worse, a later migration might rename or remove a column, and the inserted data is not valid anymore.
The solution is that you should NEVER use application models in a migration, but rather some local model that uses whatever is in the database at the time:
class PopulateStock < ActiveRecord::Migration
class Stock < ActiveRecord::Model
self.table_name = 'stocks'
end
def up
Stock.create(...)
end
end
Now the Stock model that is referenced in the migration is completely defined by the status of the table at the time of migration (no extra columns, no callbacks etc) instead of depending on all the application model.
Unfortunately this means that you have to go through all your app's migrations and create local models for them until migrations can be run.

has_many method does not work after renaming model and table

I had modelA, which has_many modelBs and modelB belongs_to modelA. I tried to change the name of a modelB to modelC without really knowing what I'm doing. Before I could call #modelA.modelBs just fine and get a list of objects, but now I can't call #modelA.modelCs. I get a NoMethodError. These are the things I did to try to make the switch:
I renamed the table with a sqlite3 migration:
def change
rename :modelBs, :modelCs
end
Then I change modelA so that it has_many :modelCs and I renamed and edited modelB.rb (now modelC.rb)and changed the class name so that it's class ModelC < ActiveRecord::Base. It still belongs_to :modelA
Rails can't find a bars method to call on an instance of ModelA. I get a NoMethodError when I do #modelA.modelCs. I ran the migration, I restarted the server. What am I missing? Did I do a bad thing?
did the migration run successfully and did your table actually get renamed? I have always used rename_table for this:
def change
rename_table :modelBs, :modelCs
end
Inside your class, you can also tell rails which table the model should be associated with, just to test whether it's looking at the right table
class modelC < ActiveRecord::Base
table_name "modelCs"
end
hope that helps
What happens if you do a $rake db:reset? db:reset is supposed to rebuild the database with all of the seed data (without the migrations); maybe check this and see what the dependencies are like at this point, then you can run your $rake db:migrate to run the migrations and see what your left with there. Can you include more information about your backend? Is it Sqlite3? PostgreSQL?
db:migrate runs (single) migrations that have not been run yet.
db:reset does db:drop, db:setup

Rails migration assumes a relationship where there is none

I have a Rails 3.1 app with a User model and a Venue model. These two models have a HABTM relationship - A user may manage many venues and a venue may be managed by many users.
I'd like users to be able to select a default venue so I'm trying to add a default_venue_id attribute to User with the following migration:
class AddDefaultVenueIdToUser < ActiveRecord::Migration
def self.up
add_column :users, :default_venue_id, :integer
end
def self.down
remove_column :users, :default_venue_id
end
end
The problem is that when I run that migration against my PostgreSQL database, it's assuming that default_venue_id is the foreign key for a relationship with the non-existent default_venues table and throws the following error:
PGError: ERROR: relation "default_venues" does not exist
: ALTER TABLE "users" ADD FOREIGN KEY ("default_venue_id") REFERENCES "default_venues" ("id")
Should I be doing something to tell the database that I'm not trying to create a relationship or am I going about this the wrong way?
Edit: I've just realised that another developer who worked on the project added the schema_plus gem which automatically defines constraints for columns ending in _id
That explains why I've never run into this behaviour before!
It would be helpful to see the Models as well to diagnose this problem.
However with that being said, I think that if you are using HABTM associations here it might be a good idea to take a look at a has many through relationship. example: VenueManagement which would have your user_id and venue_id. That way you could handle extra attributes on the association where it makes sense, like a default flag.
Hope that helps.
Since Rails seems to pick up on the _id part of the tag and tries linking it to a table, the easy solution to this is to try name it differently as convention says a field with _id links to a table.
An example of which could be
:default_id_for_venue, or just :defualt_venue

Ruby on Rails database: how to mention foreign key relation by changing app/model/table.rb file how to know they implemented

I am new to RoR. I used "rails generate model ServiceConfigs" command to generate a table.
so may commands are as below
rails generate model ServiceConfigs configs:string
rake db:migrate
-- can see app/db/service_config.rb created.
Now edited service_config.rb file to add 2 columns and which has a foreign key relation to service table. So here is code
class ServiceConfigs < ActiveRecord::Base
belongs_to :service, :dependent => :destroy
validates_presence_of :configs
end
Now when I login to underline database, and look at the table I don't see foreign key relation in table schema. Whats wrong/more I need to do?
highly appreciate your time and help
Krishna
So a few notes for you as you're getting started here: Firstly, I'd name your model in the singular form, as though you are describing a single instance of it: ServiceConfig and in the case where it belongs to a service, you may want to think of a different name all together.
Secondly validates_presence_of suggests that you have that field, so firstly, I'd remove the validation until you know that your DB has that column and that the migration worked. You can make sure by looking at your migration file and confirming that the column is being created.
You can define the relationship the "rails way" in your migration too:
http://guides.rubyonrails.org/association_basics.html
create_table :service_configs do |t|
t.string :configs
t.references :service
t.timestamps
end
Update
If you want to rerun a particular migration run:
rake db:migrate:redo VERSION=20100421175455
You can take a look in your schema to see what migration you are currently at as well. And you can also take a look at the schema to see what your DB is expected to look like as well.

How to reflect in the database a new belongs_to and has_many relationship in Ruby on Rails

I am new to rails (usually a python guy) and have just been trying to build a simple task manager application for fun. I am using Devise for authentication and have a single Task object I am trying to relate to a user. I have added the following to the Task model:
class Task < ActiveRecord::Base
belongs_to :user
end
and I have added the following in my User model for Devise:
class User < ActiveRecord::Base
has_many :tasks
<<normal Devise stuff>>
end
Whenever I added this information I then ran: rake db:migrate. It then gave me an error that the database field did not exist for user_id when I tried to do anything with it.
I am sure it is something rather simple that I am missing. Thanks for the help.
Adding a belongs_to (or any other) relationship to your model only tells active record that models are linked logically. This gives you access to methods like task.user. For this to actually work, the instances must be linked via database fields.
This is the step you're missing: you need to create a migration that will add a column to the Task table indicating which user it belongs to.
rails g migration AddUserIdToTasks user_id:integer
Note AddUserIdToTasks can be whatever name you want. It makes no difference. You can then open db/migrations/add_user_to_tasks and see what it does. Usually self.up will modify the database how you want it and self.down will do the opposite (so, in this case, remove the used_id).
Then to actually execute the SQL commands to alter the database table and schema, run
rake db:migrate
You need to generate a migration to add the foreign key first:
rails g migration AddUserIdToTasks user_id:integer
Then run db:migrate
And if you want the user to be able to reference the association as user.dreams, you need to add :class_name => 'Task' to the has_many line in the User model.
Your user class seems to be too dreamy to take care of it's tasks.
has_many :dreams // should be probably
has_many :tasks
Assuming that you tasks model has a user_id field, that is.

Resources