I am new to RoR. I have a basic doubt with establishing relationship between models. Lets take a simple example of Employee and Manager. Manager manages many employees and an employee belongs to one manager. At the schema level, i will have a managerid foreign key in the employee table.
class Employee < ActiveRecord::Base
attr_accessible :employee_id, :employee_name, :manager_id
belongs_to :manager
end
class Manager < ActiveRecord::Base
attr_accessible :manager_id, :manager_name
has_many :employeees
end
Once i specify such relationships in the model how can i ensure such data integrity is maintained in the database? I ran rake db:migrate command but it doesn't seem to affect anything in the database. What should i do to establish foreign key-primary key relationship between manager and employee table in the database? I am using sql-server 2008.
Thanks in advance.
This isn't provided directly in rails because the implementation must be database specific. The foreigner gem adds a 'add_foreign_key' command for migrations that works for mysql, postgres and sql_lite; the oracle_enhanced adapter supplies it for Oracle.
If you can't find a gem that works for sql server and your adapter doesn't provide it, you can always add a raw sql statement to your migration:
sql = "CREATE FOREIGN KEY ..."
execute(sql)
If you're doing this a lot, you might want to wrap it up in your own add_foreign_key helper, preferably using the same API as the above gems use.
Have you edited the migration files created when you generated the models? In the employee migration you'll need to specify the foreign key like so:
class CreateEmployees < ActiveRecord::Migration
def change
create_table :employees do |t|
t.string :manager_name
t.integer :manager_id
end
end
end
You can find the migration files in the db/migrations folder. You can roll back your migration to the point before creating the employees table and modify the create_table block or you can create a new migration to add the foreign key.
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 have a has_many relation in my app. e.g. department has many users.
I want to covert it to a has_and_belongs_to_many relation.
As part of the migration I need to preserve the current relation between users and departments, meaning I have to move all the data to the new connecting table.
This is the migration I created:
class CreateUserDepartment < ActiveRecord::Migration
def change
create_table :users_departments do |t|
t.belongs_to :user
t.belongs_to :department
end
###############################################
# need to move the data to the new table here #
###############################################
remove_column :users, :sub_department_id
end
end
what is the best way to write the missing line?
If you must, you can use execute "your SQL". See this question:
How do I add some inserts in rails migration?
The main value of the "Don't" answer to that question is in explaining why you would not want to use your models to do this. Also, I'd be surprised if you can or would want to do this using change, you would probably need to use self.up.
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]
do i need to create foreign key in migration to let has_many belong_to work?
Can i don't create any foreign key such as :options => "CONSTRAINT fk_box_storage REFERENCES box(id)" and still have use has_many and belong_to in model?
You don't need to create any such constraint. You just need to create a stand-alone migration to create the join table.
Lets say, you have 2 models with habtm, User and Role.
>> script/generate migration roles_users
In your migration
create_table :roles_users, :id => false do |t|
t.references :user
t.references :role
end
That's it !
No need to, if you are only going to have a web app accesing the database. In case you want to access the db with another app or directly I would recommend you DO create the foreign keys since they will give you a better insight of what is going on there and won't let you insert wrong information or delete by error (in case you set up the on delete option)