(I posted this at ruby-forum, but I figured that I should also try here): I''m new to Ruby and Rails and am evaluating using Ruby on Rails as the framework for an asset management project I''m working on and have run into an issue with Active Record that I''m wondering if there is anyway around. The issue is this, one of the requirements I have is that all asset primary keys must be UUIDs. MySQL 4.1 allows the generation of UUIDs using ''SELECT UUID()'' so to implement support for using a UUID as a primary key, I added the following methods to my model class: Code: def uuid() sql = "SELECT UUID()" record = connection.select_one(sql, " #{name} UUID generated") return record[''UUID()''] end # Override create to insert the identifier prior to creation. def create self.id = uuid(); super end As this code will be common to all models in the application I figured that I could move this into a super-class (that extends ActiveRecord::Base) that sub-classes can extend to get this functionality for free. The problem is that ActiveRecord tries apply the single-table inheritance rule to the model and tries to insert a type in the table (which fails because it isn''t in the model). And so the question is this. Is there anyway of having a custom super-class for your models which won''t trigger the single-table inheritance rule ? (while I realize that I can just add a ''type'' field to the database, it seems like the wrong thing to have to do in this case. I also tried using a Module, but this seemed not to work, but I suspect that was down to my newness with Ruby) Thanks Aled -- Aled Davies <awd-bAttSoROYyI@public.gmane.org> _______________________________________________ Rails mailing list Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org http://lists.rubyonrails.org/mailman/listinfo/rails
I''m new to both Ruby and Rails, so someone may well have a better suggestion, but here''s how I''d do this:- module UUIDHelper def before_create() sql = "SELECT UUID()" record = connection.select_one(sql, " #{name} UUID generated") self.id = record[''UUID()''] end end class ModelClass < ActiveRecord::Base include UUIDHelper end Including the module should add the methods defined as a mixin, while before_create is a callback method called before creation (a bit cleaner than overriding create). http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html Hope this is helpful, Tom Ward On Tue, 9 Nov 2004 23:05:51 -0800, Aled Davies <awd-bAttSoROYyI@public.gmane.org> wrote:> (I posted this at ruby-forum, but I figured that I should also try > here): > > I''m new to Ruby and Rails and am evaluating using Ruby on Rails as the > framework for an asset management project I''m working on and have run > into an issue with Active Record that I''m wondering if there is anyway > around. > > The issue is this, one of the requirements I have is that all asset > primary keys must be UUIDs. MySQL 4.1 allows the generation of UUIDs > using ''SELECT UUID()'' so to implement support for using a UUID as a > primary key, I added the following methods to my model class: > > Code: > > def uuid() > sql = "SELECT UUID()" > record = connection.select_one(sql, " #{name} UUID generated") > return record[''UUID()''] > end > > # Override create to insert the identifier prior to creation. > def create > self.id = uuid(); > super > end > > As this code will be common to all models in the application I figured > that I could move this into a super-class (that extends > ActiveRecord::Base) that sub-classes can extend to get this > functionality for free. The problem is that ActiveRecord tries apply > the single-table inheritance rule to the model and tries to insert a > type in the table (which fails because it isn''t in the model). > > And so the question is this. Is there anyway of having a custom > super-class for your models which won''t trigger the single-table > inheritance rule ? > > (while I realize that I can just add a ''type'' field to the database, it > seems like the wrong thing to have to do in this case. I also tried > using a Module, but this seemed not to work, but I suspect that was > down to my newness with Ruby) > > Thanks > > Aled > > -- > Aled Davies <awd-bAttSoROYyI@public.gmane.org> > > > _______________________________________________ > Rails mailing list > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > http://lists.rubyonrails.org/mailman/listinfo/rails > > > >
This worked perfectly :). I was trying to do something similar with the code that I had but was getting problems with the class not finding methods and the like. I suspect that was down my lack of Ruby knowledge. Having solved this I can say I will be trying Rails for this project :). Thanks Aled -- Aled Davies <awd-bAttSoROYyI@public.gmane.org> On Nov 10, 2004, at 4:00 AM, rails-request-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org wrote:> Message: 5 > Date: Wed, 10 Nov 2004 11:27:30 +0000 > From: Tom Ward <tom.ward-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> > Subject: Re: [Rails] Active Record Question > To: rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > Message-ID: <e9b09d890411100327253a8dc1-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> > Content-Type: text/plain; charset=US-ASCII > > I''m new to both Ruby and Rails, so someone may well have a better > suggestion, but here''s how I''d do this:- > > module UUIDHelper > def before_create() > sql = "SELECT UUID()" > record = connection.select_one(sql, " #{name} UUID generated") > self.id = record[''UUID()''] > end > end > > class ModelClass < ActiveRecord::Base > include UUIDHelper > end > > Including the module should add the methods defined as a mixin, while > before_create is a callback method called before creation (a bit > cleaner than overriding create). > > http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html > > Hope this is helpful, > > Tom Ward > > On Tue, 9 Nov 2004 23:05:51 -0800, Aled Davies <awd-bAttSoROYyI@public.gmane.org> wrote: >> (I posted this at ruby-forum, but I figured that I should also try >> here): >> >> I''m new to Ruby and Rails and am evaluating using Ruby on Rails as the >> framework for an asset management project I''m working on and have run >> into an issue with Active Record that I''m wondering if there is anyway >> around. >> >> The issue is this, one of the requirements I have is that all asset >> primary keys must be UUIDs. MySQL 4.1 allows the generation of UUIDs >> using ''SELECT UUID()'' so to implement support for using a UUID as a >> primary key, I added the following methods to my model class: >> >> Code: >> >> def uuid() >> sql = "SELECT UUID()" >> record = connection.select_one(sql, " #{name} UUID generated") >> return record[''UUID()''] >> end >> >> # Override create to insert the identifier prior to creation. >> def create >> self.id = uuid(); >> super >> end >> >> As this code will be common to all models in the application I figured >> that I could move this into a super-class (that extends >> ActiveRecord::Base) that sub-classes can extend to get this >> functionality for free. The problem is that ActiveRecord tries apply >> the single-table inheritance rule to the model and tries to insert a >> type in the table (which fails because it isn''t in the model). >> >> And so the question is this. Is there anyway of having a custom >> super-class for your models which won''t trigger the single-table >> inheritance rule ? >> >> (while I realize that I can just add a ''type'' field to the database, >> it >> seems like the wrong thing to have to do in this case. I also tried >> using a Module, but this seemed not to work, but I suspect that was >> down to my newness with Ruby) >> >> Thanks >> >> Aled >> >> -- >> Aled Davies <awd-bAttSoROYyI@public.gmane.org> >> >> >> _______________________________________________ >> Rails mailing list >> Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org >> http://lists.rubyonrails.org/mailman/listinfo/rails >> >> >> >> > > > ------------------------------ > > _______________________________________________ > Rails mailing list > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > http://lists.rubyonrails.org/mailman/listinfo/rails > > > End of Rails Digest, Vol 2, Issue 14 > ************************************ >_______________________________________________ Rails mailing list Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org http://lists.rubyonrails.org/mailman/listinfo/rails
On Tue, 9 Nov 2004 23:05:51 -0800, Aled Davies <awd-bAttSoROYyI@public.gmane.org> wrote:> The issue is this, one of the requirements I have is that all asset > primary keys must be UUIDs. MySQL 4.1 allows the generation of UUIDs > using ''SELECT UUID()''...Out of curiosity, what is the advantage of using UUIDs as opposed to an auto_increment''ing integer? -- Regards, John Wilger ----------- Alice came to a fork in the road. "Which road do I take?" she asked. "Where do you want to go?" responded the Cheshire cat. "I don''t know," Alice answered. "Then," said the cat, "it doesn''t matter." - Lewis Carrol, Alice in Wonderland
Chris Brooks
2004-Nov-10 17:19 UTC
Re: Slightly Off Topic (Was: Re: Active Record Question)
On Wed, 10 Nov 2004 11:40:59 -0500, John Wilger <johnwilger-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> Out of curiosity, what is the advantage of using UUIDs as opposed to > an auto_increment''ing integer?The rationale is usually to ensure uniqueness across multiple domains. This introduces complexity but has the potential to ease data migration / conversion in the future. It can also help prevent "bad" joins where you join two tables using IDs that don''t represent the same entity. All that said, I still generally just use auto_increment. -- Chris Brooks http://www.chrisbrooks.org
Tom Ward wrote:>before_create is a callback method called before creation (a bit >cleaner than overriding create). > >We''ve done it this way (mixin defining callbacks) in RForum, because I didn''t want to spend time figuring out how to avoid the problems with the Inflector. Now we are about to change it to the abstract base class approach. Reason: all the time you need to add other class-specific behaviors to those callbacks. With mixin it looks quite awkward. With abstract base class, much better. There are some awkward incantations that you have to write in your abstract base class. See here: http://rubyonrails.org/show/HowtoMakeAbstractModel Best regards, Alexey Verkhovsky