I'm writing my first rails app & want to get into some good habits from the start. The table in question is to be to hold employee data, one of the fields being the manager's ID. To reflect the hierarchical structure, I'm thinking of using acts_as_tree, so the parent_id would be the manager's id field (right?). If we are to use (import) data from our existing HR application - PeopleSoft - the employee ID is a string. Employee ID seems to make the most sense as a PK (coming from the PeopleSoft developer perspective, I realize I may be biased and/or not seeing all of the possibilities -- I welcome suggestions on this as well)
I know that one of the philosophies behind rails is "convention over configuration", so I'd like to use the defaults - the PK being the autoincrementing integer. Would it make sense in this case to create a "lookup table" or something in order to maintain the use/association of the ID coming from PS? There will be reports/exports going back into the PS world....
Thanks
You're correct in that the convention in Rails is to use the default auto-incrementing id. If you have a one-to-one relationship between people and employee IDs, then employee ID should just be a field (column) on your person model. Make it a key (but not a primary key) if you're going to be doing a lot of lookups using it.
Related
I am building a db in sql server, then I will build the web app. The data has some pretty good natural key columns that I will use as the PKs. However, several of them are composite keys, which will be a bit unwieldy in the application side.
For example, a golf course can have 1, 2, or 3 courses at one location. The location has a number (32201) and each course has a name (bayou front, bayou back, bayou exec) so I would make a composite key from the number and name.
However, in the application (asp mvc) the internal routing allows for passing a single integer id from controller to view, etc for use in identifying stuff. So I am thinking of adding an non-key identity column to the Golf Course table, and others like it, so I can us the identity filed in the app. So someone can select the bayou back course on the index page of the app, and I would pass the non-key identity id number to the controller to select the details for the course from the DB and pass them to the view.
It seems at first, like I would be bypassing the purpose of the primary key by using this non-key integer, but the PK would come into play for things like referential integrity when doing updates, inserts, etc.
Thoughts?
What you're talking about sounds like a surrogate key (as opposed to a natural key). There are pros and cons to using each, and both approaches have been discussed before, rather extensively, I think.
From the answer here: go ahead and use both. They are both tools, and each one should be used when it is the best tool for the job.
The only thing I'd add for your situation is that, since your tables would have both a surrogate and natural key on the same table, make sure that one (natural key or surrogate key) is the actual PK and that the other has a unique key or index on it. That way, either one can be used to uniquely identify rows in your tables.
I need to create a product code which will be generated with a custom function. It will start with a letter, have the id of the category and then have a random 7 digit number. For this, I can set the primary_key to a string and generate the code or I can use FriendlyID. What might be the best for this situation?
Short answer: Use something like friendly_id
The story now:
Choosing a natural key for the primary_key of a table should always be measured well, it has an impact on your data model.
The first issue is regarding related records in other tables. If you will have related tables, the foreign key in those tables should also be VARCHAR and match your generated primary key. If you are not sure what to do, avoid custom primary keys.
Another issue in your question may be:
It will start with a letter, have the id of the category
Is this id the primary key of a Category model? If it's the case, you are generating a key with DB isolation in mind, but re-tighting with this one. Think again for this one.
Go for a slug generated by your function, you will be free for the future. You may create a brand new algorithm and thus only do a once for all change of the slugs. You may even have 2 slugs, the old one which redirects to the new one, and the new one.
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.
I'm creating a web application with grails, and I'm working on the CRUD prototype using Scaffold. Out of the box, the scaffold will use the unique id (which makes sense) for foreign key values, and I'm wondering if I can easily replace the unique id with a readable value (such as a combination of two values from said table).
For example:
I have Location and RoomNumber domains that represent a Hotel location and room number. Each number therefore "belongs-to" a location. When I go to create a room, I have a drop-down auto-generated that allows me to pick from existing locations. These are unintuitive values though... such as "project.Location : 1"
I'd like to replace this "project.Location : 1" with the name, city, and state column values that correspond to id 1. Is this an easy thing to modify? I'd think there's some simple mapping that needs to be done...
Thanks in advance!
Turns out the solution is really simple... just need to implement the toString method in the corresponding Domain class. Received this answer from the Grails mailing list.
My understanding is that Actice Record is based on a object-relational mapping (ORM) pattern described by Martin Fowler in his book Pattern of Enterprise Application Architecture (Addison-Wesley, 2002); which states a one-to-one mapping relationship exists between a database record and the object that represents it in an object-oriented program (OOP). When Rails creator David Heinemeier sought to implement an ORM for his Rails framework, he based it on Fowler's pattern.
Here's the problem, does ActiveRecord assign a surrogate primary key to every table using the naming convention "ID", and if so, why? Reason I ask is that it appears it'd make more sense to assign a a surrogate primary key using the naming convention "tablename_ID"; as in fact it appears ActiveRecord does when creating foreign keys. Further, is it possible to override the default config, and assign a surrogate primary key using the naming convention "tablename_ID"; reason being that especially in the case of primary keys, it appears to be a good idea not to use a shared name, since telling the difference between two columns ID's is not possible if simply looking at the column namesing: ID, ID, ID. As a use case example of where this appears there would be a problem, if I export data to a single table from two tables, there will be two columns with the ID name; when I import that document with updates, it would appear that there's no way to map the ID columns by default.
It's already obvious to see what the ID is, because it is in a certain table. You don't have table_name.table_name_id but table_name.id. I like the distinction between foreign keys and primary keys this way, but admittedly, it's a matter of opinion.
Unless you have a really good reason to use anything other, you should stick to the convention. That's what conventions are for. ActiveRecord gives you the option to change it, like so:
ActiveRecord::Base.primary_key_prefix_type = :table_name_with_underscore
This sets the way primary keys are generated globally. products.id becomes products.product_id.