why doesnt Rails auto-generate foreign-key for associations? - ruby-on-rails

It's not hard to do this thick,also it hides all logic in model,so it also fits the philosophy of rails model.
So I am wondering if there is some good reasons of handtyping foreign-keys inside the migration files.

You don't have to do it by hand. For example:
rails g model post user:references
creates migration adding posts table with user_id column and index on this column.

This issue has been around since Rails 1. There were arguments for and against but at that time, the various db vendors differed substantially in their particular syntax for foreign key constraints and it was non trivial to implement across multiple db vendors. At least that was my understanding at that time

Related

Rails Migrations: Foreign key and indexing column fields

I developed a Ruby on Rails 5 application and deployed it to a production environment, after running rake db:migrate I noticed that I wasn't using foreign_key: true and neither index: true for my general relations between tables. Question is: Will this affect database performance and should I generate new migrations just to add indexes and foreign keys references to my columns? Thanks in advance.
From Ruby on Rails guide:
2.2 Schema Conventions
Active Record uses naming conventions for the columns in database tables, depending on the purpose of these columns.
Foreign keys - These fields should be named following the pattern
singularized_table_name_id (e.g., item_id, order_id). These are the
fields that Active Record will look for when you create associations
between your models.
Primary keys - By default, Active Record will use an integer column
named id as the table's primary key. When using Active Record
Migrations to create your tables, this column will be automatically
created.
You must know more about ActiveRecord Look here how it works here
I suggest you to read about belongs_to and has_many relations
Depends on what you are going to do, if you have relations where the foreign key is needed, you will need to create those migrations, otherwise you wont be able to access them.
When it comes to db performance it doesnt matter really

Turn flat file into relational models

I get flat files once a week that have a few 100k rows. I would like to turn them into a relational model system in Rails since there are about five columns that are fairly static and would make sense for a different model that would then be linked back into the main table as a foreign key.
Is there was a quick way to check if an entry already exists, and if so, look it up and put the foreign key in the main model, and if not, create a new entry in the second model and then reference it in the main model.
I can turn the above paragraph into code but wanted to know if there is a simple 'few lines' Ruby or Rails implementation.
Just for the sake of merging my comment and #anton-z 's.
You can use activerecord-import for doing bulk operations, and ActiveRecord's find_or_create_by to do the checking.

When to assign a foreign key and when to just create an association?

I'm learning about model associations in rails. I've learned how to give the table for a model a column to hold foreign keys of another model like so:
rails generate model User account_id:integer
I would then take the primary key of an account from an Account table and assign it to the account_id for the designated user.
However, I am also told to create the association in User.rb like so:
has_one :account
I understand the difference between these two things. One creates a column in the table (the first line after the migration), and the other generates a series of helpers (the latter).
However, what I am seeing in tutorials is that sometimes both are done, while other times, only the association (has_one :account) is done. How do I go about deciding when to create a column in the table to hold foreign keys, and when to just create the association in the model .rb file?
You will always have to create the column in the Database (1)
It is not mandatory to define the relation(s) inside the models, but it is highly recommended (2)
(1) : The Database needs this column of foreign keys to be able to retrieve the corresponding record. Without the column, the DB cannot find back the related record. You can use a Migration to create this column, not only a scaffold.
(2) : You can skip the relations declaration in the models, but it is highly recommended because:
it generate methods corresponding to the relations (ex: User belongs_to :role, then you can do user.role directly instead of Role.where(id: user.role_id).first)
not every human can remember all the associations. It is better to show/list everything that is linked to your model
You asked:
How do I go about deciding when to create a column in the table to hold foreign keys, and when to just create the association in the model .rb file?
I would answer:
Always create the column (cannot work if you don't) AND define every association(s) (relation(s)) inside the model.
Your first example is a scaffold that creates the model file and the migration.
has_one helps ActiveRecord understand the relationships between the tables so that it can, among other things, generate proper SQL queries for you.
But #1 has to be in place for #2 to even work. However, creating the db column via a scaffold command isn't necessary - it's just convenient sometimes, because it creates both the model file, and the associated migration.
You could just write the migration by hand. Just because whatever thing you're following doesn't always mention adding the db column doesn't mean it's not necessary. It's probably just assumed that you've already done it because these foreign key migrations are so common after you get up and running with Rails that they sort of go without saying after a while.

Why Rails hides the existence of id column?

I don't quite understand the need to hide the existence of id column in Rails.
It is neither reflected in migration file nor the schema.rb file.
There is no way for a newbie to know for the fact that a column named id has been created by default as a primary key.
Unless they go and check the actual schema of the table in database (rails dbconsole).
I can see the timestamps macro included by default in the migration file as well as in schema.rb as two fields created_at and updated_at. Here, a developer at least gets a clue. Rails could have done the same for id column too. But it doesn't.
Why the secrecy around id column? Is it a part of the famous convention over configuration? Or is it a norm across all MVC frameworks?
In database design it is generally accepted that numeric id's are preferred, because
they are easier to index, and thus easier to "follow" or check when creating links (foreign keys).
when editing/updating records, you have a unique (and efficient) identifier
So therefore it is advised to give all tables a unique numeric key, always.
Now this numeric key has no meaning whatsoever to your application, it is a "implementation detail" of your database layer. Also to make sure every table has an id, unless you explicitly ask not to.
I think this would indeed fall under the "convention over configuration" nomer: why explicitly specify an id for each table if you each table should have one.
The timestamps is different: this is interesting for some tables, but for same tables it is not important at all. It also depends on your application.
Note that this is not at all related to MVC. The M in MVC is a container for data, but in MVC it is actually not really important how the Model gets filled. In other words: the ORM part is not part of MVC. You will see that in most MVC implementations there is no ORM, or definitely not as tightly integrated as with Rails.
So in short: imho ommitting the 'id' from the migration is not a secret, it is just to make life easier, saves you some more typing, and it makes sure you follow a good convention unless you explicitly do not want to.
This is probably due to the fact that relational databases tend to use integer primary keys, and doing otherwise introduces complexities. I guess the reason it's hidden in rails is so that creating tables with integer primary keys does not require any special configuration, and having to write it into rails migrations invites inexperienced developers to play around with it (which is probable not a good idea).
Additionally, I think rails tries to abstract away things like numeric ids, if you want to create associations in a migration you do not need to specify foreign keys, you can simply write the name of the object you want to relate the table to.
I never thinked about the id field because almost every table have an id....
Check the documentation about migrations where they say:
A primary key column called id will also be added implicitly, as it's
the default primary key for all Active Record models. The timestamps
macro adds two columns, created_at and updated_at. These special
columns are automatically managed by Active Record if they exist.
If you want to check your table columns, just go to rails console and type Model.column_names
I think it's clear that if you don't add a primary key, then rails will add one generic key for you so that it can index your record and have a control over it, so basically it isn't stating that there WILL be an ID field, since I don't believe this has to be imperative, but rather optional in the event you do not provide a primary key.
It's a Rails convention to hide the I'd attribute to discourage and remove temptation of playing with it.
id attr is automatically generated with auto_increment to ad normalization to your data(to make each record unique an accessible). Injecting your own values would eventually corrupt and break the magic of ActiveRecord.

Rails - Basic model conventions and basic association confusion

My understanding of the conventions I'm currently dealing with is as follows:
Model names should be in TitleCaps.
Variable names should be lower_cased_and_under_scored.
Associations should be to the singular version of the foreign table name with _id appended, e.g. user_uploaded_picture_id
When doing "rails generate model ModelName" - should it be in TitleCaps at that point?
Should every database table I need have every association specified? On this note, do associations both ways need to be specified, i.e. should every has_one/has_many be matched to a belongs_to?
Should there be a model for every database table I intend to create?
Multiple questions in one :)
Both model_name and ModelName are accepted and generates the correct model and table names.
You don't need to specify every associations only those which you want to use.
No, you don't need to create a model for every table. But if you'll use that table from Rails it's easier to have one.

Resources