I've been using the tutorial by Michael Hartl and I am trying to create a new model called "Recipe" to allow users to post recipes. The model is essentially the same as the micropost model, in that a user should be able to post many recipes and all recipes should be linked to one user. I therefore used the same command and migration as for the micropost:
class CreateMicroposts < ActiveRecord::Migration
def change
create_table :microposts do |t|
t.string :content
t.integer :user_id
t.timestamps
end
add_index :microposts, [:user_id, :created_at]
end
end
Created using the command: rails generate model Micropost content:string user_id:integer
The issue I am having though is that the primary key in both tables is the user_id. Will this work, or when I go to try to enter a recipe will it try to pull from the microposts table instead? Thanks in advance
when I go to try to enter a recipe will it try to pull from the microposts table instead?
No. The Recipe model in your application by default will interact with a recipes table in your database. Similarly, a Micropost model will interact with a microposts table in your database by default.
As long as you work with the Recipe model, an instance of Recipe will not pull from the microposts table.
It sounds like you may have a fundamental misunderstanding about what a table's primary key is for, and perhaps how database tables work; but for now that's outside of the scope of this question.
As an aside, you probably should have done
rails generate model MicroPost content:string user_id:integer
(notice the uppercase P in MicroPost). This is a better name for the clase and will create a micro_posts table in your database.
The primary key is not the user_id in any of the two tables. Each model generates a table with an implicit numeric autoincremented id column that is used as the PK.
What the add_index does is add an index on the user_id column. An index is not a PK.
Anyway, you should change your add_index statement in your recipes migration to:
add_index :recipes, [:user_id, :created_at]
Related
I have an old rails project using Rails 2 . There is already model class Student. In database, there is a table students. Now, I need to implement that each student can have multiple courses. Which means I need to have a new table in database that's courses table & have one-to-many relationship from student to course.
How to create migration file to make this?
Rails 2 didn't have an option to create associations via the migration generator, so you have to take a more manual approach.
You can create the migration thusly: https://www.tutorialspoint.com/ruby-on-rails-2.1/rails-migrations.htm
You'll need to add the column student_id to your courses table with a column type of integer
Then add the following to your Student model:
has_many :courses
This shouldn't be too difficult if you are actually using Rails 2.3
And TBH if you aren't AT LEAST on 2.3, then you should probably just recreate this project entirely...
1.) Use ruby script/generate model Course name:string description:text student_id:bigint to generate your migration, which should look something like this:
class CreateCourses < ActiveRecord::Migration
def self.up
create_table :courses do |t|
t.string :name
t.text :description
t.bigint :student_id
t.timestamps
end
end
def self.down
drop_table :courses
end
end
2.) Find the newly created MODEL in your project directory with name course and add the association to the file:
belongs_to :student
3.) Find the STUDENT model in your project folder and add the has_many association to that:
has_many :students
4.) In your terminal, cd into your project folder and run rake db:migrate
You should be good to go after that! Here's the reference for Rails 2.3 associations: https://guides.rubyonrails.org/v2.3/association_basics.html
I'm very new to Rails, and currently for our class, we have to create an application with databases.
I have a bunch of tables that have foreign keys to other tables, and I've defined these associations in the migration files (using execute("ALTER TABLE...")), but not in my models (I only have self.primary_key defined in my models).
My question is, since I've set these associations in my migrations, do I also have to set the associations in my models (i.e. has_may, belongs_to, validates_uniqueness_of, etc)?
I'll be creating an app that would allow user input, and these input would be inserted to the database.
Hoping that my confusion can be cleared up. Thank you!
Example
Migration file:
class CreateSchools < ActiveRecord::Migration[5.0]
def up
create_table :schools, {:id => false} do |t|
t.integer :school_id
t.string :school_name
t.string :contact_number
t.integer :a_id
t.timestamps
end
execute "ALTER TABLE schools ADD PRIMARY KEY(school_id);"
execute "ALTER TABLE schools ADD CONSTRAINT a_id UNIQUE(a_id);"
execute "ALTER TABLE schools ADD CONSTRAINT school_references_location FOREIGN KEY (a_id) REFERENCES locations(a_id) ON DELETE CASCADE ON UPDATE CASCADE;"
change_column_null :schools, :school_name, false
change_column_null :schools, :a_id, false
end
def down
execute "ALTER TABLE schools DROP PRIMARY KEY;"
execute "ALTER TABLE schools DROP FOREIGN KEY school_references_location;"
execute "ALTER TABLE schools DROP INDEX a_id;"
drop_table :schools
end
end
Model:
class School < ApplicationRecord
self.primary_key = :school_id
end
Yes you'll need to define the associations in Model as well.
For all the rails applications,
Migrating and changing db according to associations is the first step.
Then add association statements in the models so that the associations from db can be accessed using simple methods. Like user.posts etc.
Adding association statements in Models provide you methods that generates queries according to the method called to retrieve data from db easily. You can also query db using join and select statements if you don't want to include association statements in Models.
So, in short, designing schema to manage associations is necessary where as mentioning them in Model is not. But we do it to make our life and code simpler.
I'm totally stuck here! I want to add a unique index so that no two records in an association table can have the same combination of user_id and course_id.
I have created the following migration file in rails:
class CreateSignups < ActiveRecord::Migration
def change
create_table :signups do |t|
t.integer :course_id
t.integer :user_id
t.timestamps null: false
end
add_index :signups, :course_id
add_index :signups, :user_id
add_index :signups, [:course_id, :user_id], unique: true
end
end
...but for some reason, the unique 'course_id & user_id' is not being represented in the schema.rb and using the rails console the system lets me manually create a multiple records where the course_id and the user_id are exactly the same.
The signups table is managed by the Signup model and has an integer primary key called 'id'. The course and user Model & database table follow standard rails naming convention.
Can anyone see why it's the unique criteria is not being understood in this migration?
Thanks in advance!
Did you already run your migration once (to create table) and then add the index? You can check it by doing following:
bundle exec rails dbconsole
select * from schema_migrations;
If your migration version is already recorded in the schema_migrations table, and doing rake db:migrate won't run it again.
To add indexes, you have 2 options:
Rollback the migration for CreateSignups. This will drop the current table and then doing rake db:migrate will re-create the table with indexes.
If you don't want to loose the data in previous step, then you'll have to explicitly create indexes in MySQL from rails dbconsole.
I have two models: User and Club and I have a many-to-may relationship like:
user has_and_belongs_to_many clubs
club has_and_belongs_to_many users
Now, I will have a third table with the result of this relationship:
user_clubs(user_id, club_id)
When generating scaffold, for example, rails generate scaffold User name:string birth_date:date
gender:string login_id:integer, how can I generate that relationship? In the same way?
Thank you
You need to use generate migration
rails g migration create_club_users user_id:integer club_id:integer
It will create the following migration:
class CreateClubUsers < ActiveRecord::Migration
def change
create_table :club_users do |t|
t.integer :user_id
t.integer :club_id
end
end
end
Then you should set id to false as in Create an ActiveRecord database table with no :id column?
I suggest that you read WHY YOU DON’T NEED HAS_AND_BELONGS_TO_MANY RELATIONSHIPS.
You can try this:
rails g migration CreateClubsUsersJoinTable club_id:integer user_id:integer
You should follow alphabetical order of models when creating join table of has_and_belongs_to_many association in rails
Please refer this link for further assistance
http://apidock.com/rails/ActiveRecord/Associations/ClassMethods/has_and_belongs_to_many
I'm wondering how I can add associations to my models. Suppose, I generate two models
rails generate model User
rails generate model Car
Now I want to add an associations so that the models acquire the form
class User < ActiveRecord::Base
has_many :cars
end
class Car < ActiveRecord::Base
belongs_to :user
end
The question is: how to apply this modification by migrations in order to obtain cars_users table in the database? I'm planning to use that table in my code.
belongs_to association expect an association_id column in its corresponding table. Since cars belongs_to user, the cars table should have a user_id column. This can be accomplished 2 ways.
first, you can generate the column when you create the model
rails g model car user_id:references
or just add the user_id after you create the model like Richard Brown's answer. Be careful that if you use integer instead of references, you'd have to create the index yourself.
rails g migration add_user_id_to_cars user_id:integer
then in the generated migration, add
add_index :cars, :user_id
UPDATE:
As Joseph has mentioned in the comments, the need to add the index manually has already been addressed in the current version of Rails. I think it was introduced in Rails 4. You can read more of it in the official Rails guide for migrations. The gist of it is running the following generator
bin/rails g migration add_user_to_cars user:references
will create a migration with a line similar to
add_reference :cars, :user, index: true
This will add a user_id column to the cars table and it will also mark that column to be indexed.
Following #jvnill's explanation in rails 4 (and maybe in rails 3.2 too) you can do it like this too (avoiding the id parts and remembering the exact convetions):
rails g migration AddUserToCar user:references
Which will create the following migration, taking care of both adding the column and index with all correct conventions:
class AddUserToCar < ActiveRecord::Migration
def change
add_reference :cars, :user, index: true
end
end
At the end as always run the migration:
rake db:migrate
View your schema.rb to view the new index and user_id column.
Generate a migration to create the association:
rails g migration AddUserIdToCars user_id:integer
rake db:migrate
Migration file:
class Createuser < ActiveRecord::Migration[5.0]
def change
create_table :users do |t|
t.string :name
end
create_table :cars do |t|
t.belongs_to :user, index: true
t.varchar(255) :model
t.varchar(255) :color
end
end
end