Polymorphic Associations in Rails - ruby-on-rails

How do polymorphic associations work in Rails? What are their advantages? Is there a way to add belongs_to method just by running a migration?

Ryan has a railscast about this that is pretty good.
Belongs_to isn't something you add to a migration, you add it to the model. In the migration, you have to add the foreign key column. For example if you have a post model that belongs to a user, you'd add the user_id column to the post activerecord in a migration. Then you add
belongs_to :user
in the post model separately. Then rails will do its magic in the background to give you the proxy collections in the user model.

Related

Rails - both model are has_many

Sorry, I am not very advanced in mapping out databases
I have a model similar to this: A teacher can have many students, and a student can have many teachers. So How would I make this? If a student could have only one teacher I know I would set an attribute like: teacher_id: integer, then when I want to create a student it would be similar to this
Student.create(:teacher_id => id)
or query similar to this:
Student.where(teacher_id: id)
Teacher.find(student.teacher_id)
But I am unsure of how to accomplish this if both are has_many relationships
You can use rails has_and_belongs_to_many relationship for your requirement. check this link for reference: http://guides.rubyonrails.org/association_basics.html#has-and-belongs-to-many-association-reference
you need to use this relationship like this:
teacher.rb
has_and_belongs_to_many :students
student.rb
has_and_belongs_to_many :teachers
then you need to add a migration to create a join table containing teacher_id and student_id
you should create name of your migration in alphabetical order like this:
rails g migration create_join_table_for_students_teachers student_id:integer teacher_id:integer
and then rake db:migrate
then you can access students of a single teacher like teacher.students etc.,
Hope this might help you in some way please go through the reference link once
You're describing a has-and-belongs-to-many (HABTM) relation, which Rails supports in two ways: has_and_belongs_to_many or has_many :through. You can read about them in the Active Record Associations Rails Guide, which also gives you tips and how to choose which one is appropriate for your application.
Better use has_many:through relation.

Rails generate has_many association

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.

Update database struct when Rails association changes

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 :)

How to set up a typical users HABTM roles relationship

I'm quite new to this and I'm using cancan + devise for my user auth. However I'm not really sure what it means to set up a typical users HABTM roles relationship nor do I really understand what a HABTM relationship is.
Can anyone explain it really well or point me to a good tutorial or example?
HABTM means has and belongs to many. You basically need a table as a middle man to track multiple id's (called a through table). When referenced as a typical users HABTM roles relationship, they really mean there would be a User model, Role model, users table, roles table, and a roles_users table. Don't forget to add the the HABTM -- roles_users -- table. A typical setup follows:
class User < ActiveRecord::Base
has_and_belongs_to_many :roles
end
class Role < ActiveRecord::Base
has_and_belongs_to_many :users
end
You can then use the associations like normal saying User.first.roles and Role.first.users.
There are also a couple Railscasts on your issues.
The Ruby on Rails Guides are a good starting point here also this tutorial is exactly what you want

Declaring associations in Ruby on Rails

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 :)

Resources