I have written a natural key macro for Rails, which essentially provides a way to validate uniqueness for an arbitrary number of keys in a table. Before I submit a patch for this, I was wondering whether this is in keeping with the philosophy of Rails, and whether people would find this useful. Most large systems have quite complex data models which contain entities whose logical primary key is made up of quite large numbers of attributes (I think 15 is the record in the site in which I work), and Rails'' basis of using surrogate keys in every table does not easily support this. Having the ability to at least validate that the real primary key is unique seems to be at least a step in the right direction. (I''ll save making disparaging comments about the mandatory use of surrogate keys for a time when I''m in the mood for a flame war :). I was a DBA in a former life, I''m sure it shows.) The natural key is specified in the model in the same way as other declarations about the entity, eg: class Book < ActiveRecord::Base belongs_to :author belongs_to :library natural_key :title, :author, :library, :copy validates_presence_of :author validates_numericality_of :num_pages One final question - I''ve vacillated between having foreign key fields specified by the column name (:author_id), as it would be done with validates_uniqueness_of, or by the parent name (:author), as it is with belongs_to. Is one or the other more in keeping with the philosophy of Rails ? Find local movie times and trailers on Yahoo! Movies. http://au.movies.yahoo.com
On 5/12/05, Matthew Keene <dfg778-/E1597aS9LT0CCvOHzKKcA@public.gmane.org> wrote:> I have written a natural key macro for Rails, whichIt looks like something that could be useful.> One final question - I''ve vacillated between having > foreign key fields specified by the column name > (:author_id), as it would be done with > validates_uniqueness_of, or by the parent name > (:author), as it is with belongs_to. Is one or the > other more in keeping with the philosophy of Rails ?I would say that you almost have to use the field names in the "key" because even in your example I would assume something like title wouldn''t be a foreign key and actually would be the book''s title so if Rails tried to assume it was an "_id" field then it wouldn''t work. -- John W Higgins wishdev-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org
Isn''t it simple/adequate enough to catch the exception from the DB if one attempts to insert a duplicate PK? So you''re trying to do it on your application side instead. Where is the value add? On 5/12/05, John Higgins <wishdev-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> On 5/12/05, Matthew Keene <dfg778-/E1597aS9LT0CCvOHzKKcA@public.gmane.org> wrote: > > I have written a natural key macro for Rails, which > > It looks like something that could be useful. > > > One final question - I''ve vacillated between having > > foreign key fields specified by the column name > > (:author_id), as it would be done with > > validates_uniqueness_of, or by the parent name > > (:author), as it is with belongs_to. Is one or the > > other more in keeping with the philosophy of Rails ? > > I would say that you almost have to use the field names in the "key" > because even in your example I would assume something like title > wouldn''t be a foreign key and actually would be the book''s title so if > Rails tried to assume it was an "_id" field then it wouldn''t work. > > -- > John W Higgins > wishdev-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org > _______________________________________________ > Rails mailing list > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > http://lists.rubyonrails.org/mailman/listinfo/rails >
On Thursday 12 May 2005 02:24 pm, Corey Lawson wrote:> Isn''t it simple/adequate enough to catch the exception from the DB if > one attempts to insert a duplicate PK? > > So you''re trying to do it on your application side instead. Where is > the value add?As a general rule, business rules (like what has to be unique) belong in a business layer, not in the persistence layer (database). Diavd
>From: David Corbin <dcorbin-wmGZ+vDKSyrZJqsBc5GL+g@public.gmane.org>>>On Thursday 12 May 2005 02:24 pm, Corey Lawsonwrote:>> Isn''t it simple/adequate enough to catch theexception from the DB if>> one attempts to insert a duplicate PK? >> >> So you''re trying to do it on your application sideinstead. Where is>> the value add?>As a general rule, business rules (like what has tobe >unique) be>long>in a >business layer, not in the persistence layer >(database).Ah, the traditional database logic versus program logic debate. While I generally agree that this type of functionality is best implemented in the database, the philosophy behind Rails seems to be minimise the amount of coding required, and to be able to specify the behaviour of the model using simple declarative statements (hence my proposal). Handling errors by catching the duplicate key exception would require: * The user having to override the update and create methods for every model object for which this might occur, or * Coding database platform specific logic into the framework to successfully trap and analyze the appropriate exceptions * My proposed macro also generates a user friendly message when a violation occurs, so doing this would involve rummaging around in the database''s catalog tables to generate based on the columns in the primary key. So in general I would say that the value add here is a cleaner and simpler interface for the user/designer, and a platform independent architecture within the framework...and the option is still open to you to do the exception handling yourself if that''s what you want to do. The overhead is a single extra call to the database for every insert or update, and in a framework which builds the model structure by querying the target database''s catalog for every transaction, that may not be so much of a problem. In most circumstances, I would probably recommend to have a unique key on these natural/alternate keys anyway, especially where the database is likely to be updated by programs outside the Rails framework. Find local movie times and trailers on Yahoo! Movies. http://au.movies.yahoo.com
From: John Higgins <wishdev-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>>> One final question - I''ve vacillated between having >> foreign key fields specified by the column name >> (:author_id), as it would be done with >> validates_uniqueness_of, or by the parent name >> (:author), as it is with belongs_to. Is one or the >> other more in keeping with the philosophy of Rails?>I would say that you almost have to use the fieldnames in the "key">because even in your example I would assume somethinglike title>wouldn''t be a foreign key and actually would be thebook''s title so if>Rails tried to assume it was an "_id" field then itwouldn''t work. I actually use the reflect_on_all_associations method to get the list of foreign keys defined using belongs_to, and hence the name used on the belongs_to macro (which is what is used on the natural key, in my current implementation). So I''m able to tell whether each member of the key is an attribute of the table or a reference to a foreign key, and in this example I know that since "title" isn''t a foreign key then it must be an attribute of the current object. Find local movie times and trailers on Yahoo! Movies. http://au.movies.yahoo.com
On Friday 13 May 2005 06:58 am, Matthew Keene wrote:> >From: David Corbin <dcorbin-wmGZ+vDKSyrZJqsBc5GL+g@public.gmane.org> > Ah, the traditional database logic versus program > logic debate. While I generally agree that this type > of functionality is best implemented in the database, > the philosophy behind Rails seems to be minimise the > amount of coding required, and to be able to specify > the behaviour of the model using simple declarative > statements (hence my proposal).You misunderstood my comment. Raising the business layer issue was actually in support of your macro. Where does business logic get placed in Rails if not in the model''s object. It''s certainly bettera than relying on the DB (Not that the DB shouldn''t have constraints, just I don''t think the code should rely on it.)