I'm still fairly new to Ruby on Rails and I'm working with associations, such as if a table has_many :facts, or belongs_to :list,
do we deal with users as well? for Users model:
has_many :lists
and then the list model should have
belongs_to :user
Now does this mean I need to create a new column in the table? Right now I only have email and password_digest. Do I need to add a new migration to add a new column list_id. I already did rake db:migrate. Can I just simply add a column in the migration file?
Thanks
Yes, you must create a new column and if you already run the migration you must create a new one.
However, it's the list that must have the user_id.
Related
Sorry maybe for the stupid question but I'm new. When I create tables using this command rails g model Post title:string description:text. How can I further make a connection between another table by?
Or will have enough in the models table select belongs_to? And thus the connection will be already established and you will not need to install anything in the migration.
If you want to "connect" the posts table (Post model), with whatever you already have, like a users table, to make an one-to-many association you can use the references as a kind of type, which will generate an entry on the migration file for creating a foreign key column on your (posts) table.
create_table :posts do |t|
t.references :user
...
end
So the command could be:
$ rails generate model Post title:string description:text user:references
There I'm using user as an example, it can be any other.
The model generated will already have the belongs_to association specified, like:
class Post < ApplicationRecord
belongs_to :user
...
What you need then is to add the has_many association in the User model:
class User < ApplicationRecord
has_many :posts
...
I have 2 models:
Account
Profile
creating these models created 2 tables in the database:
accounts
profiles
now I want to add a relationship:
each account can have many profiles
each profile belongs to one account
I ran the following command:
rails g migration AddAccountToProfiles account:references
which created the following migration:
class AddAccountToProfiles < ActiveRecord::Migration
def change
add_reference :profiles, :account, index: true, foreign_key: true
end
end
now I'm a little confused:
why does the migration say :profiles and :account? Shouldn't it be :accounts (plural)?
also, after (or before) creating this migration, I have to add belongs_to and has_many in the appropriate model class right?
as a side question, is there a way to add belongs_to and has_many in the models, and from that information have rails generate the appropriate migration without me manually creating a migration with the 'rails g migration ...' command?
As per rails documentation, the command
rails g migration AddAccountToProfiles account:references
will generate the migration file below
class AddAccountToProfiles < ActiveRecord::Migration
def change
add_reference :profiles, :account, index: true, foreign_key: true
end
end
Since you specified account:references, then it assumes to create account_id on profiles table, but you still need to add the relationships in the corresponding model files.
When we use :accounts in migration file, it's referring to the table in the database, :account is used as the name of the foreign key to be added onto the table along with suffix _id
Also relevant information here
The migration is correct, because a profile only belongs to one account. It should not be 'accounts'. The migration will place a account_id column onto the profiles table in order to make that connection.
After the migration, you still need to add has_many and belongs_to. In Rails, when defining a relationship, there are generally two steps 1) create the database migration 2) define the relation on the model class itself. You need to have both. In this case, Rails is looking for the account_id column on a profile (the default foreign key) to make the relationship between the two models.
And as for your last question, no, there is not a way to generate migrations after defining a has_many. You can use Rails generators to create the model itself rails generate model ModelName and define the relationship in that model; that will add the correct belongs_to and has_many into the generated model along with the migration. But in practice, it's generally better to create the migration and manually add belongs_to and has_many as needed so there's less of a chance of missing something.
Is there a way to generate has_many association for a column using Rails generate scaffold command in the console?
I know belongs_to is available and there are use cases of references but not sure of has_many
There is no column for a has_many relationship. A belongs_to is backed by a column which holds a foreign key.
So if you generate a scaffold: rails g scaffold Post
And then you generate another scaffold: rails g scaffold Comment post:references
Then rails will create a migration that adds a column named post_id to the Comment table and creates an index on it. For both tables, it creates foreign key constraints between comments(post_id) and posts(id). Rails will also add belongs_to :post in the Comment model.
At anytime you can add a has_many to a model as long as another model belongs_to the first model and has a migration with the foreign key column.
Which is the best way to do database migration when association changes?
For example:
Add has_one/ has_many/ & belongs_to association to 2 models have no association.
Add has_many_and_belongs_to association to 2 models have no association.
Add has_one/ has_many/ & belongs_to association to 2 models that one model have association with other model, another model is newly created.
When your association changes, is it not just that you have to change the foreign keys in the db scheme and create specific migrations for that?
For example if you want to add a has_many relationship to store which has many books. You could easily create a migration with the generate command.
rails g migration addStoreIdToBooks store_id:integer
Then in your model/store.rb
has_many :books
And in the model/book.rb
belongs_to :store
Otherwise I didn't understand your question :)
Hopefully I don't get flamed for this one too bad - I've tried my very hardest to find an answer to no avail.
I was wondering if someone could help me figure out how to properly declare associations in Ruby on Rails (3). At the moment, I have 3 models:
#room.rb
class Room < ActiveRecord::Base
has_many :check_ins
end
#check_in.rb
class CheckIn < ActiveRecord::Base
belongs_to :user
belongs_to :room
end
#user.rb
class User < ActiveRecord::Base
has_one :check_in
end
So far, I haven't done any migrations to add foreign_key columns to any of my tables (does Rails do this for you?).
I'm confused about why the command CheckIn.first.user returns nil whereas the command User.first.check_in returns SQLite3::SQLException: no such column. The same happens with respect to CheckIn.first.room and Room.first.check_ins, respectively. What would I need to do in order to have User.first.check_in return the CheckIn object associated with the first user and Room.first.check_ins return the set of CheckIns associated with the first Room?
Any help would be GREATLY appreciated.
Charlie
How did you originally generate these models? Did you just make the model files, or did you use rails' model generator (which also generates a migration for you)?
#room.rb
class Room < ActiveRecord::Base
has_many :check_ins
end
#check_in.rb
class CheckIn < ActiveRecord::Base
belongs_to :user
belongs_to :room
end
#user.rb
class User < ActiveRecord::Base
has_one :check_in
has_one :room, :through => :check_in
end
In db/migrations/34612525162_something_something.rb You need to make sure you have migrations that set these tables up for you. The easiest way for you to do it would be to run this command in a console, modify the commands to use the fields you want, the *_id fields are required for your associations to work:
rails generate model user name:string email:string otherfield:integer
rails generate model check_in user_id:integer room_id:integer
rails generate model room number:integer
Note that these will also generate model files for you, since you already have these 3 model files it'll ask you if you want to overwrite them, or skip the files. You can skip them and it should be just fine. If you already had the migrations for part of the data in these models then you can just add the user_id and room_id fields to the check_in model by running this generator instead:
rails generate migration AddIdsToCheckIn user_id:integer room_id:integer
For rails 2.3.x replace rails generate with script/generate. Next you can inspect your migration(s) by opening the files up in db/migrate.rb and modify them there if you need to. Finally, run the migrations:
rake db:migrate
And it should work out for you. Note that I added a has_one, :through => relationship to User - this is so that you can do #user.room without having to make 3 chains: #user.check_in.room
You need to add the migrations yourself (or if you aren't live, you can modify an existing migration). Basically, you need to give the belongs_to side of the relationship a foreign key.
There is absolutely no reason to get flamed don't worry :) It seems here that you are trying to do a one to many association, but you're actually doing a many to many one.
If a user has one check in, it means that he/she has one room. So, you could just have :
user has_one room
room belongs to user
and room has a user_id.
Hope that helps :)