I'm learning the basics of ruby on rails and I want to make some simple queries but I have a doubt:
I will have these models:
class Client < ActiveRecord::Base
has_one :address
has_many :orders
has_and_belongs_to_many :roles
end
class Address < ActiveRecord::Base
belongs_to :client
end
class Order < ActiveRecord::Base
belongs_to :client, counter_cache: true
end
class Role < ActiveRecord::Base
has_and_belongs_to_many :clients
end
Now, I will use scaffold to generate all the things, and I want to know if I have to directly put the foreign keys in the scaffols, like:
rails generate scaffold Adress street:string number:integer client_id:integer
Or when I make those associations and then migrate my db they will be implicit?
I don't know if I explain myself in the best way.
Thanks
Yep, there is no reference. You need to either pass the client_id or a reference to Client model, e.g:
rails generate scaffold Address street:string number:integer client_id:integer:index
or
rails generate scaffold Address street:string number:integer client:references
Either, in rails 4 you can use belongs_to this way:
Assume that you have a user model in your application
rails g scaffold comment belongs_to:user text:string
it generates that class in your migrate folder:
class CreateComments < ActiveRecord::Migration
def change
create_table :comments do |t|
t.string :text
t.belongs_to :user, index: true, foreign_key: true
t.timestamps null: false
end
end
end
you should execute rake db:migrate then, this command create user_id properties as a index column in your database table.
Related
I have code like this
class Author < ApplicationRecord
has_many :books, dependent: :destroy
end
class Book < ApplicationRecord
belongs_to :author
end
While creating generate migration, I didn't use any keyword to generate foreign key associations. But I see alter sql statement with respect to adding foreign key in structure.sql . How and Why?
Merely setting up the associations in your model DOES NOT alter the schema in any way and this code will just give an undefined column error unless you actually create the books.author_id column through a migration.
Running the model generator with author:belongs_to or author:references (which are aliases) does add a foreign key column to the migration as well as a belongs_to :author association in the model.
# rails g model book title:string author:belongs_to
class CreateBooks < ActiveRecord::Migration[6.0]
def change
create_table :books do |t|
t.string :title
t.belongs_to :author, null: false, foreign_key: true
t.timestamps
end
end
end
But a association does not actually have to have a foreign key constraint. If you ran the generator with author_id:bigint the association will work but you will have no foreign key constraint to guarantee referential integrity.
Using books:has_many on the other hand in a generator will generate a bad migration since a has_many association is not a database column.
I have created 2 table students and issued_books. but forgot to add t.belongs_to :students in migration, while creating issued_books table.
Now I have modified the corresponding model as:
class Student < ActiveRecord::Base
has_many :issued_book
end
class IssuedBook < ActiveRecord::Base
belongs_to :student
end
How would I do it now through migration in rails?
$ bin/rails generate migration AddUserRefToProducts user:references
generates
will generate the following:
class AddUserRefToProducts < ActiveRecord::Migration[5.0]
def change
add_reference :products, :user, index: true, foreign_key: true
end
end
source: http://edgeguides.rubyonrails.org/active_record_migrations.html
So in your case it would be:
$ bin/rails generate migration AddStudentRefToIssuedBooks student:references
You just have to populate the foreign_key in your belongs_to model:
$rails g migration AddForeignKeyToIssuedBook
#db/migrate.rb
class AddForeignKeyToIssuedBook < ActiveRecord::Migration
def change
change_table :issued_books do |t|
t.belongs_to :student #-> student_id
end
end
end
$rake db:migrate
This will create the appropriate column in the issued_books db, which should allow you to reference its associated Student with it.
Ref for t.belongs_to
--
You should also consider looking up about has_many/belongs_to associations for scope on the table structure:
I've got a user table with all my users
Now I want to introduce user-groups
So I need a second table for the groups and a relation between those groups.
It should be possible to set a user in different groups. so I need a n:m relation
It read about that rails can generate most things I need and also generate the migration file? is that true? How does it works?
Migrations
class CreateUserGroups < ActiveRecord::Migration
def up
create_table :user_groups do |t|
t.string :name
t.integer :size
t.timestamps
end
end
def self.down
drop_table :user_groups
end
end
class CreateUserGroupUsers < ActiveRecord::Migration
def self.up
create_table :user_group_users do |t|
t.user_id:integer
t.user_groups_id:integer
t.timestamps
end
end
def self.down
drop_table :user_group_users
end
end
Create your User and UserGroup model and migration from terminal
rails g model User email:string password:string
rails g model UserGroup name:string size:integer
You'll also want to create a UserGroup and User relationship managing table called UserGroupManager
rails g model UserGroupManager user_id:integer user_group_id:integer
Update your database by running this command in terminal
rake db:migrate
Set up the relationships within app/models/
# app/models/user.rb
class User < ActiveRecord::Base
has_many :user_group_managers
has_many :user_groups, through: :user_group_managers
end
# app/models/user_group.rb
class UserGroup < ActiveRecord::Base
has_many :user_group_managers
has_many :users, through: :user_group_managers
end
# app/models/user_group_manager.rb
class UserGroupManager < ActiveRecord::Base
belongs_to :user_group
belongs_to :user
end
I'm a little befuddled on how to create a joined table in ROR.
Let's say there are 2 tables:
User
Book
In order to create a joined table user_book, my initial impression was that you did this:
rails g migration user_book
But I've been told that to create an actual joined table, I generate an actual model:
rails g model user_book
Is that correct?
And if the second one is correct, then once I've created it, I open it and add both the book_id, and user_id to the migrated file, and then run rake db:migrate command. Is this correct?
EDIT:
Just wanted to added that
User model would have this: has_many :books, through: :user_book
Book model would have this: has_many :users, through: :user_book
If you want to use has_many through:, you need a table to handle that. As well as a model object to represent that table.
How you go about creating it (rails g model or rails g migration) doesn't ultimately matter. All those commands do is create either a model AND a migration file, or just a migration file. Personally, I would do the rails g model, since you need both.
You'd just add a user_books table with 2 IDs, user_id and book_id.
Migration would look something like this:
class CreateUserBooks < ActiveRecord::Migration
def change
create_table :user_books do |t|
t.references :user, index: true, foreign_key: true, null: false
t.references :book, index: true, foreign_key: true, null: false
t.timestamps null: false
end
end
end
Models would look like this:
class User < ActiveRecord::Base
has_many :user_books
has_many :books, through: :user_books
end
class Book < ActiveRecord::Base
has_many :user_books
has_many :users, through: :user_books
end
class UserBook < ActiveRecord::Base
belongs_to :user
belongs_to :book
end
I created a join table for a HABTM association in my Rails app. It created the table in the schema, but it never generated a model file in the app. Will it still work? Why did it not generate a file?
Here is my migration:
class CreateBooksAuthorsJoinTable < ActiveRecord::Migration
def change
create_table :books_authors, id: false do |t|
t.integer :book_id
t.integer :author_id
t.timestamps
end
end
end
Models
class Book < ActiveRecord::Base
has_and_belongs_to_many :feeds
end
class Author < ActiveRecord::Base
has_and_belongs_to_many :posts
end
You would have to explicitly generate a model; it doesn't happen as a by-product of creating a join table.
A has_and_belongs_to_many association doesn't actually need a model class representing the association. It is supposed to be just a join table so what you've set up is exactly right.
The other option for such associations is a has_many through: association which uses an intermediate, or join, class. This is discussed in more details in the rails guide for associations. You would have to generate that joining model yourself though.