Rails migration: Add two references to one table - ruby-on-rails

I am having a hard time extending an existing model to include two references to a single table.
My current model is called Order and I need two references (payment_state and delivery_state) to the State table.
It is my understanding that I should run the following command:
rails g migration AddStatesToOrder payment_state:references delivery_state:references
However, the following line comes up in my schema.rb after running rake db:migrate:
# Could not dump table "orders" because of following NoMethodError
# undefined method `[]' for nil:NilClass
Any help would be greatly appreciated. Thanks!

You should do like this:
rails g migration AddStatesToOrder payment_state_id:integer delivery_state_id:integer
And define the relation like this in the model:
belongs_to :payment_state, class_name: State.model_name
belongs_to :delivery_state, class_name: State.model_name
Why using :integer instead of :references? Because the thing you want to do is not "conventional", it is a customized double-relation to the same model, and Rails cannot guess it for you.

Related

Join table error on running migration

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

rails associations between two tables

I've got two tables in my Postgres database: categories and products.
I have a one to many relationship defined, one category can have many products.
After I've defined these in the two models in Rails, is there something else I need to do to the tables? I still have only the primary key that Rails defined when I set up each model separately.
You can run a migration generator with the right parameters to set up the foreign key.
bin/rails generate migration AddCategoryRefToProducts category:references
This assumes you have a Product model and Category model with these associations:
#product.rb
belongs_to :category
#category.rb
has_many :products
Run rake db:migrate to complete the process
When you look at your db/migrate directory you will see a file that contains an add_reference line within a def change block. Here's the reference for that method: Rails API. The syntax for the standalone generator is from the Rails Guides

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

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