What creates the FOREIGN KEY constraint in Ruby on Rails 3? - ruby-on-rails

I understand that by default the id field is created and also: PRIMARY KEY (id).
How about the foreign key ?
I have Shops and Products tables and the following associations:
Shop: has_many :products
Product: belongs_to :shop
In Product I have also:
t.integer "shop_id"
which is meant to be the foreign key, and also:
add_index("products", "shop_id")
However, if I export the database I see only:
KEY `index_products_on_shop_id` (`shop_id`)
What should I do in order to add
FOREIGN KEY (`shop_id`) REFERENCES Shop(`id`)
?

You can use the foreigner gem for adding foreign keys to your application. To get started add the following to your Gemfile
gem "foreigner"
After that you can easily add foreign keys in your migration like so:
add_foreign_key :products, :shops
This would add a foreign from product.shop_id to shop.id. See the documentation for more options like differently named keys or self-referencing tables.

Related

adding relation through migrations in Rails 5

I followed the advice of this SO post. An entree belongs_to a venue. So I expect a foreign key named venue_id on the entrees table. I generated the following:
rails g migration AddEntreeToVenue entree:belongs_to
It created the following migration:
class AddEntreeToVenue < ActiveRecord::Migration[5.0]
def change
add_reference :venues, :entree, foreign_key: true
end
end
But after running db:migrate, I look at the entrees table and no foreign key:
Indexes:
"entrees_pkey" PRIMARY KEY, btree (id)
Referenced by:
TABLE "venues" CONSTRAINT "fk_rails_0cf11999c6" FOREIGN KEY (entree_id) REFERENCES entrees(id)
What it appeared to do was add the foreign key to the venues table, not the entrees table. What did I do wrong?
Your generator command specified that Rails should create a belongs_to column on Venues. What you actually want is the opposite:
rails g migration AddVenueToEntrees venue:belongs_to
This will create a migration that modifies entrees, adding a venue_id column with a foreign key constraint on venues.id.

How to get Rails to insert a Foreign key constraint in DB?

I have a ruby model called MyModelA and MyModelB as shown below
class MyModelA < ActiveRecord::Base
belongs_to :mymodelb
class MyModelB < ActiveRecord::Base
# Blah Blah Blah
When I create the database with rake db:create command, I notice that MYMODELA table doesn't have a foreign key constraint on it. I manually inserted it like this:
ALTER TABLE MYMODELA ADD FOREIGN KEY (MYMODELB_ID) REFERENCES MYMODELB(ID);
How can I define my model such that this DB foreign key constraint is automatically created without me having to manually add it later?
Rails doesn't provide a migration helper to add foreign_key. But you can use foreigner gem
You do do this to add a foreign_key using foreigner gem
create_table :products do |t|
t.string :name
t.integer :factory_id
t.foreign_key :factories
end
generate a migration:
rails g migration AddmymodelbidToMyModelA mymodelb_id:integer
go the the migration file and add
add_index :mymodela, :mymodelb_id
just between the two end clauses
run rake:db:migrate

Associations with ActiveRecords in Ruby on Rails

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.

Difference between foreign key constraint and references in Rails

Is there any difference between using t.references and executing SQL command to create foreign key relationship between products and category table as shown below? In other words, are the two different ways of doing the same thing or am I missing anything here?
class ExampleMigration < ActiveRecord::Migration
def up
create_table :products do |t|
t.references :category
end
#add a foreign key
execute <<-SQL
ALTER TABLE products
ADD CONSTRAINT fk_products_categories
FOREIGN KEY (category_id)
REFERENCES categories(id)
SQL
add_column :users, :home_page_url, :string
rename_column :users, :email, :email_address
end
def down
rename_column :users, :email_address, :email
remove_column :users, :home_page_url
execute <<-SQL
ALTER TABLE products
DROP FOREIGN KEY fk_products_categories
SQL
drop_table :products
end
end
They're not the same thing. Rails by default doesn't enforce foreign keys in the database. Instead, references when creating from the command line also creates a regular index, like this:
add_index :products, :category_id
Update:
Rails 5 actually does exactly the same thing now. So, to answer the original question: Nowadays, both are the same.
I found some thing intresting in this page.
http://railsforum.com/viewtopic.php?id=17318
From a comment :
Rails doesn't use foreign keys to perform his backend tasks. This
because some db like sqlite doesn't allow foreign keys on its tables.
So Rails doesn't provide an helper to build a foreign key
Also there is a gem foreigner for adding foreign keys to database table.
What creates the FOREIGN KEY constraint in Ruby on Rails 3?

foreign key in migration is needed to let has_many belong_to work?

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)

Resources