Hey folks, I''m pleased to announce the release of a new rails plugin for ActiveRecord. acts_as_enumerated, has_enumerated and ActiveRecord::VirtualEnumerations. What is it? As part of the work I''ve been doing at Site5.com[1] (who have very graciously allowed me to release this code into the wild) I put together an extension to treat an ActiveRecord model as an enumeration. I.e.: class BookingStatus < ActiveRecord::Base acts_as_enumerated, :order => ''position ASC'' end booking.status = BookingStatus[:confirmed] Values for acts_as_enumerated models are cached (reducing hits to the database) and you can define ''virtual'' acts_as_enumeration classes, eliminating the need to clutter your models directory with classes that do nothing more than acts_as_enumerated. The has_enumerated macro allows your models to refer to acts_as_enumerated instances without resorting to using belongs_to (which can require you to jump through hoops to avoid the database hit when retrieving the enumeration value). I should point out that this isn''t the first time something like this has been done. Michael Shuerig sent a mail [2] to the list a while back (when I was first looking at this feature) outlining how he was adding enumerations to his Boilerplate library. Boilerplate''s enumerations differ from this plugin in some pretty significant ways but Michael''s technique of hooking into Module.const_missing was the missing piece of the puzzle I needed to eliminate clutter in the models directory - I''m very grateful for that. How is it installed? Well, the new rails ''plugins'' feature makes packaging and releasing extensions a *lot* more straight forward. First of all, you need to be running a plugin-compatible version of rails (0.14 and above). Then you simply: cd vendor/plugins svn export http://svn.protocool.com/rails/plugins/enumerations_mixin/trunk enumerations_mixin The README_ENUMERATIONS file should be enough to get you started - when I manage to scrape together some spare time I''ll insert some (hopefully) more helpful rdoc. What''s missing? Well, proper documentation, for a start. Apart from that it''s fully functional. Regards, Trevor [1] - in a shameless plug, Site5 is poised to release a rather nifty rails app. See http://engineering.site5.com for a teaser. [2] - Michael''s email is here: http://thread.gmane.org/gmane.comp.lang.ruby.rails/19193 -- Trevor Squires http://somethinglearned.com
Jean-Christophe Michel
2005-Oct-25 21:40 UTC
Re: [ANN] New Plugin - ActiveRecord Enumerations
Hi, Trevor Squires wrote:> As part of the work I''ve been doing at Site5.com[1] (who have very > graciously allowed me to release this code into the wild) I put together > an extension to treat an ActiveRecord model as an enumeration. I.e.: > > class BookingStatus < ActiveRecord::Base > acts_as_enumerated, :order => ''position ASC'' > end > > booking.status = BookingStatus[:confirmed]Thks, seems good. But would it be possible to have different string values depending on language, for i18n ? -- Jean-Christophe Michel
Hi, I hope I''m not misunderstanding you - please let me know if this doesn''t make sense. i18n is outside the scope of this plugin. There''s nothing stopping you from displaying a translated string for your users based on the ''name'' field in an acts_as_enumerated record. However, the actual text in the name field is for the *programmer* to use. So if you were using r18n (which I have no personal experience of) I assume that something like this would work: Status of your booking: <%= _(@booking.status.name) %> or <%= select :booking, :status_id, BookingStatus.all.collect {|s| [ _(s.name), s.id]} %> I hope this helps, and do let me know if I''ve misunderstood you. Regards, Trevor On 25-Oct-05, at 2:40 PM, Jean-Christophe Michel wrote:>> >> class BookingStatus < ActiveRecord::Base >> acts_as_enumerated, :order => ''position ASC'' >> end >> >> booking.status = BookingStatus[:confirmed] > > Thks, seems good. But would it be possible to have different string > values depending on language, for i18n ? > -- > Jean-Christophe Michel > _______________________________________________ > Rails mailing list > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > http://lists.rubyonrails.org/mailman/listinfo/rails >-- Trevor Squires http://somethinglearned.com
Hi Trevor, This looks pretty cool. If I understand enumerations correctly, their basic application is (for example) to create drop-down lists from the database and reduce the number of queries on the database while doing so. Is that what you''re using them for? Duane Johnson (canadaduane) On Oct 25, 2005, at 1:47 PM, Trevor Squires wrote:> Hey folks, > > I''m pleased to announce the release of a new rails plugin for > ActiveRecord. acts_as_enumerated, has_enumerated and > ActiveRecord::VirtualEnumerations. > > What is it? > > As part of the work I''ve been doing at Site5.com[1] (who have very > graciously allowed me to release this code into the wild) I put > together an extension to treat an ActiveRecord model as an > enumeration. I.e.: > > class BookingStatus < ActiveRecord::Base > acts_as_enumerated, :order => ''position ASC'' > end > > booking.status = BookingStatus[:confirmed] > > Values for acts_as_enumerated models are cached (reducing hits to > the database) and you can define ''virtual'' acts_as_enumeration > classes, eliminating the need to clutter your models directory with > classes that do nothing more than acts_as_enumerated. > > The has_enumerated macro allows your models to refer to > acts_as_enumerated instances without resorting to using belongs_to > (which can require you to jump through hoops to avoid the database > hit when retrieving the enumeration value). > > I should point out that this isn''t the first time something like > this has been done. Michael Shuerig sent a mail [2] to the list a > while back (when I was first looking at this feature) outlining how > he was adding enumerations to his Boilerplate library. > Boilerplate''s enumerations differ from this plugin in some pretty > significant ways but Michael''s technique of hooking into > Module.const_missing was the missing piece of the puzzle I needed > to eliminate clutter in the models directory - I''m very grateful > for that. > > How is it installed? > > Well, the new rails ''plugins'' feature makes packaging and releasing > extensions a *lot* more straight forward. > > First of all, you need to be running a plugin-compatible version of > rails (0.14 and above). Then you simply: > > cd vendor/plugins > svn export http://svn.protocool.com/rails/plugins/ > enumerations_mixin/trunk enumerations_mixin > > The README_ENUMERATIONS file should be enough to get you started - > when I manage to scrape together some spare time I''ll insert some > (hopefully) more helpful rdoc. > > What''s missing? > > Well, proper documentation, for a start. Apart from that it''s > fully functional. > > Regards, > Trevor > > [1] - in a shameless plug, Site5 is poised to release a rather > nifty rails app. See http://engineering.site5.com for a teaser. > [2] - Michael''s email is here: http://thread.gmane.org/ > gmane.comp.lang.ruby.rails/19193 > > -- > Trevor Squires > http://somethinglearned.com > > _______________________________________________ > Rails mailing list > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > http://lists.rubyonrails.org/mailman/listinfo/rails
Hi Duane Thanks for the feedback. Yes, I use them a lot for dropdowns and validations etc. However, the main reason I use them is I get to treat the acts_as_enumerated class like it was code: booking.status = BookingStatus[:confirmed] ... or ... if booking.status.in?(:provisional, :confirmed) That sort of thing. So apart from the caching, it''s mostly syntactic sugar... Regards, Trevor On 3-Nov-05, at 2:26 PM, Duane Johnson wrote:> Hi Trevor, > > This looks pretty cool. If I understand enumerations correctly, their > basic application is (for example) to create drop-down lists from the > database and reduce the number of queries on the database while doing > so. Is that what you''re using them for? > > Duane Johnson > (canadaduane) > >-- Trevor Squires http://somethinglearned.com
Jean-Christophe Michel
2005-Nov-03 23:35 UTC
Re: [ANN] New Plugin - ActiveRecord Enumerations
Trevor Squires wrote:> Hi, > > I hope I''m not misunderstanding you - please let me know if this doesn''t > make sense. > > i18n is outside the scope of this plugin. There''s nothing stopping you > from displaying a translated string for your users based on the ''name'' > field in an acts_as_enumerated record. However, the actual text in the > name field is for the *programmer* to use.I simply wanted to know if it would be possible to add a lang field, have (id,lang) be unique and have :conditions => { ''lang=?'',:lang } added to queries. So a list of values could be abstracted by ids, whatever the language the user uses on the gui. -- Jean-Christophe Michel
On Nov 3, 2005, at 4:22 PM, Trevor Squires wrote:> Hi Duane > > Thanks for the feedback. > > Yes, I use them a lot for dropdowns and validations etc. However, > the main reason I use them is I get to treat the acts_as_enumerated > class like it was code: > > booking.status = BookingStatus[:confirmed] > ... or ... > if booking.status.in?(:provisional, :confirmed) >Hey, that''s kinda cool. Mind sharing the code for "in?" ?> That sort of thing. So apart from the caching, it''s mostly > syntactic sugar... >Thanks for the sweet stuff! :) Duane Johnson (canadaduane)
Hey, On 3-Nov-05, at 6:37 PM, Duane Johnson wrote:>> booking.status = BookingStatus[:confirmed] >> ... or ... >> if booking.status.in?(:provisional, :confirmed) >> > Hey, that''s kinda cool. Mind sharing the code for "in?" ? >It''s an instance method added to acts_as_enumerated classes. in lib/active_record/acts/enumerated.rb ActiveRecord::Acts::Enumerated::InstanceMethods ... which reminds me, I should rename my packages before I get some stern words from Jamis :-) Regards, Trevor
On Nov 3, 2005, at 7:57 PM, Trevor Squires wrote:> Hey, > > On 3-Nov-05, at 6:37 PM, Duane Johnson wrote: > >>> booking.status = BookingStatus[:confirmed] >>> ... or ... >>> if booking.status.in?(:provisional, :confirmed) >>> >> Hey, that''s kinda cool. Mind sharing the code for "in?" ? >> > > It''s an instance method added to acts_as_enumerated classes. > > in lib/active_record/acts/enumerated.rb > ActiveRecord::Acts::Enumerated::InstanceMethods >It sounds to me that it should be added to Object. Dang, that''d be a nice way to switch the usual .include? syntax around... it seems like .include? is *always* backwards. On conditionals, I want to do this: a = 1 do(something) if a.in?(my_array)> ... which reminds me, I should rename my packages before I get some > stern words from Jamis :-) >Hehe, glad someone''s keeping the namespace clean :) Duane Johnson (canadaduane)
hi... I am trying my hand at the enumeration plugin... I would like to use VitualEnumerations to define my million and one enumerations. In an attempt to do so i placed the following in my RAILS_ROOT/config/virtual_enumerations.rb ActiveRecord::VirtualEnumerations.define do |config| config.define ''ResponsiblePerson'', :table_name => ''enumerations'', :conditions => [''enumeration_type = ?'',"responsible_person_type"], :order => ''position ASC'' end I have an numeration table that looks like this enumerations id: int(11) enumeration_type: varchar(50) code: varchar(10) name: varchar(255) position: int(11) test fixtures in vi test/fixtures/enumerations.csv that look like this "id","enumeration_type","code","name","position" "272","responsible_person_type","ATT","Attorney","0" "273","responsible_person_type","BEN","Beneficiaries","0" "274","responsible_person_type","DIR","Director","0" "275","responsible_person_type","INC","Incorporator","0" "276","responsible_person_type","LQD","Liquidator","0" "277","responsible_person_type","SEC","Secretary","0" "278","responsible_person_type","PNR","Partner","0" "279","responsible_person_type","REC","Receiver","0" "280","responsible_person_type","SGN","Signatory","0" "281","responsible_person_type","SET","Settler","0" "282","liability_type","1","Limited by Shares","0" I am trying to setup a test as a prof of concept in vi test/unit/enumeration_test.rb require File.dirname(__FILE__) + ''/../test_helper'' class EnumerationTest < Test::Unit::TestCase fixtures :enumerations def setup @responsible_person = ResponsiblePerson.find(272) end # Replace this with your real tests. def test_truth assert_kind_of ResponsiblePerson, @responsible_person end end Any test I try to setup fails test_truth(EnumerationTest): ActiveRecord::RecordNotFound: Couldn''t find ResponsiblePerson with ID=272 /usr/lib/ruby/gems/1.8/gems/activerecord-1.12.2/lib/active_record/base.rb:413:in `find'' ./test/unit/enumeration_test.rb:7:in `setup_without_fixtures'' /usr/lib/ruby/gems/1.8/gems/activerecord-1.12.2/lib/active_record/fixtures.rb:520:in `setup'' Help me!!... (newbie) On 11/4/05, Duane Johnson <duane.johnson-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> > On Nov 3, 2005, at 7:57 PM, Trevor Squires wrote: > > > Hey, > > > > On 3-Nov-05, at 6:37 PM, Duane Johnson wrote: > > > >>> booking.status = BookingStatus[:confirmed] > >>> ... or ... > >>> if booking.status.in?(:provisional, :confirmed) > >>> > >> Hey, that''s kinda cool. Mind sharing the code for "in?" ? > >> > > > > It''s an instance method added to acts_as_enumerated classes. > > > > in lib/active_record/acts/enumerated.rb > > ActiveRecord::Acts::Enumerated::InstanceMethods > > > > It sounds to me that it should be added to Object. Dang, that''d be a > nice way to switch the usual .include? syntax around... it seems > like .include? is *always* backwards. On conditionals, I want to do > this: > > a = 1 > do(something) if a.in?(my_array) > > > > ... which reminds me, I should rename my packages before I get some > > stern words from Jamis :-) > > > > Hehe, glad someone''s keeping the namespace clean :) > > Duane Johnson > (canadaduane) > > _______________________________________________ > Rails mailing list > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > http://lists.rubyonrails.org/mailman/listinfo/rails >-- First they laugh at you, then they ignore you, then they fight you. Then you win. -- Mahatma Karamchand Gandhi
Hi Leon, I''m a bit swamped at work so I don''t have the time to try out your config (and what I think may be the problem). See below: On 4-Nov-05, at 5:17 AM, Leon Leslie wrote:> > require File.dirname(__FILE__) + ''/../test_helper'' > > class EnumerationTest < Test::Unit::TestCase > fixtures :enumerations > > def setup > @responsible_person = ResponsiblePerson.find(272) > end > > # Replace this with your real tests. > def test_truth > assert_kind_of ResponsiblePerson, @responsible_person > end > end > > Any test I try to setup fails > > test_truth(EnumerationTest): > ActiveRecord::RecordNotFound: Couldn''t find ResponsiblePerson with > ID=272 > > /usr/lib/ruby/gems/1.8/gems/activerecord-1.12.2/lib/active_record/ > base.rb:413:in > `find'' > ./test/unit/enumeration_test.rb:7:in `setup_without_fixtures'' > > /usr/lib/ruby/gems/1.8/gems/activerecord-1.12.2/lib/active_record/ > fixtures.rb:520:in > `setup'' >The significant thing here is what it''s *not* complaining about. We know that it a) found the virtual enumeration class and b) found the table ''enumerations''. All that remains is not being able to find record 272. Personally I''ve never used CSV for fixtures and I''m wondering if that''s the problem. Try this. Run ./script/console and type: ResponsiblePerson.enumeration_model_updates_permitted = true ResponsiblePerson.create( :enumeration_type => ''responsible_person_type'', :code => ''ATT'', :name => ''Attorney'', :position => 1) x = ResponsiblePerson.find(:conditions => [''code = ?'', ''ATT'']) x.name What happens? Does ''Attorney'' get printed after the last line? After we figure out what''s going on with your records, I''ve got some recommendations that will make your life easier (your table definition is working against you a bit here). Regards, Trevor -- Trevor Squires http://somethinglearned.com
If you are interested, here is a great post with some more of that sugar: http://nat.truemesh.com/archives/000535.html Lee On 11/4/05, Duane Johnson <duane.johnson-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> > > On Nov 3, 2005, at 7:57 PM, Trevor Squires wrote: > > > Hey, > > > > On 3-Nov-05, at 6:37 PM, Duane Johnson wrote: > > > >>> booking.status = BookingStatus[:confirmed] > >>> ... or ... > >>> if booking.status.in?(:provisional<http://booking.status.in?(:provisional>, > :confirmed) > >>> > >> Hey, that''s kinda cool. Mind sharing the code for "in?" ? > >> > > > > It''s an instance method added to acts_as_enumerated classes. > > > > in lib/active_record/acts/enumerated.rb > > ActiveRecord::Acts::Enumerated::InstanceMethods > > > > It sounds to me that it should be added to Object. Dang, that''d be a > nice way to switch the usual .include? syntax around... it seems > like .include? is *always* backwards. On conditionals, I want to do > this: > > a = 1 > do(something) if a.in?(my_array) <http://a.in?(my_array)> > > > > ... which reminds me, I should rename my packages before I get some > > stern words from Jamis :-) > > > > Hehe, glad someone''s keeping the namespace clean :) > > Duane Johnson > (canadaduane) > > _______________________________________________ > Rails mailing list > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > http://lists.rubyonrails.org/mailman/listinfo/rails >********************************* All that is gold does not glitter. Not all those who wander are lost. The old who are strong do not whither. Deep roots are not touched by the frost. -- J.R.R. Tolkein _______________________________________________ Rails mailing list Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org http://lists.rubyonrails.org/mailman/listinfo/rails
ResponsiblePerson.enumeration_model_updates_permitted = true NoMethodError: undefined method `enumeration_model_updates_permitted='' for ResponsiblePerson:Class from /usr/lib/ruby/gems/1.8/gems/activerecord-1.12.2/lib/active_record/base.rb:942:in `method_missing'' from (irb):1 do i have to use require anythere? just wondering why my Class is not defined. (newbie sorry) talk to me about the table definition Thanks for the help thus far Regards, Leon On 11/4/05, Trevor Squires <trevor-k8q5a0yEZAgS+FvcfC7Uqw@public.gmane.org> wrote:> Hi Leon, > > I''m a bit swamped at work so I don''t have the time to try out your > config (and what I think may be the problem). > > See below: > > On 4-Nov-05, at 5:17 AM, Leon Leslie wrote: > > > > > require File.dirname(__FILE__) + ''/../test_helper'' > > > > class EnumerationTest < Test::Unit::TestCase > > fixtures :enumerations > > > > def setup > > @responsible_person = ResponsiblePerson.find(272) > > end > > > > # Replace this with your real tests. > > def test_truth > > assert_kind_of ResponsiblePerson, @responsible_person > > end > > end > > > > Any test I try to setup fails > > > > test_truth(EnumerationTest): > > ActiveRecord::RecordNotFound: Couldn''t find ResponsiblePerson with > > ID=272 > > > > /usr/lib/ruby/gems/1.8/gems/activerecord-1.12.2/lib/active_record/ > > base.rb:413:in > > `find'' > > ./test/unit/enumeration_test.rb:7:in `setup_without_fixtures'' > > > > /usr/lib/ruby/gems/1.8/gems/activerecord-1.12.2/lib/active_record/ > > fixtures.rb:520:in > > `setup'' > > > > The significant thing here is what it''s *not* complaining about. We > know that it a) found the virtual enumeration class and b) found the > table ''enumerations''. > > All that remains is not being able to find record 272. Personally I''ve > never used CSV for fixtures and I''m wondering if that''s the problem. > > Try this. Run ./script/console and type: > > ResponsiblePerson.enumeration_model_updates_permitted = true > ResponsiblePerson.create( :enumeration_type => > ''responsible_person_type'', :code => ''ATT'', :name => ''Attorney'', > :position => 1) > x = ResponsiblePerson.find(:conditions => [''code = ?'', ''ATT'']) > x.name > > What happens? Does ''Attorney'' get printed after the last line? > > After we figure out what''s going on with your records, I''ve got some > recommendations that will make your life easier (your table definition > is working against you a bit here). > > Regards, > Trevor > -- > Trevor Squires > http://somethinglearned.com > > _______________________________________________ > Rails mailing list > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > http://lists.rubyonrails.org/mailman/listinfo/rails >-- First they laugh at you, then they ignore you, then they fight you. Then you win. -- Mahatma Karamchand Gandhi
Ok... I found the error. Sorry about the noise on the mailing list... ResponsiblePerson was previously a model before i discovered the wonderful enumeration plugin.... Trevor - Any advice on the enumeration table definition will be greatly appreciated. regards, Leon . On 11/4/05, Leon Leslie <leonleslie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> ResponsiblePerson.enumeration_model_updates_permitted = true > > NoMethodError: undefined method `enumeration_model_updates_permitted='' > for ResponsiblePerson:Class > from /usr/lib/ruby/gems/1.8/gems/activerecord-1.12.2/lib/active_record/base.rb:942:in > `method_missing'' > from (irb):1 > > do i have to use require anythere? just wondering why my Class is not > defined. (newbie sorry) > talk to me about the table definition > > Thanks for the help thus far > > Regards, > Leon > > On 11/4/05, Trevor Squires <trevor-k8q5a0yEZAgS+FvcfC7Uqw@public.gmane.org> wrote: > > Hi Leon, > > > > I''m a bit swamped at work so I don''t have the time to try out your > > config (and what I think may be the problem). > > > > See below: > > > > On 4-Nov-05, at 5:17 AM, Leon Leslie wrote: > > > > > > > > require File.dirname(__FILE__) + ''/../test_helper'' > > > > > > class EnumerationTest < Test::Unit::TestCase > > > fixtures :enumerations > > > > > > def setup > > > @responsible_person = ResponsiblePerson.find(272) > > > end > > > > > > # Replace this with your real tests. > > > def test_truth > > > assert_kind_of ResponsiblePerson, @responsible_person > > > end > > > end > > > > > > Any test I try to setup fails > > > > > > test_truth(EnumerationTest): > > > ActiveRecord::RecordNotFound: Couldn''t find ResponsiblePerson with > > > ID=272 > > > > > > /usr/lib/ruby/gems/1.8/gems/activerecord-1.12.2/lib/active_record/ > > > base.rb:413:in > > > `find'' > > > ./test/unit/enumeration_test.rb:7:in `setup_without_fixtures'' > > > > > > /usr/lib/ruby/gems/1.8/gems/activerecord-1.12.2/lib/active_record/ > > > fixtures.rb:520:in > > > `setup'' > > > > > > > The significant thing here is what it''s *not* complaining about. We > > know that it a) found the virtual enumeration class and b) found the > > table ''enumerations''. > > > > All that remains is not being able to find record 272. Personally I''ve > > never used CSV for fixtures and I''m wondering if that''s the problem. > > > > Try this. Run ./script/console and type: > > > > ResponsiblePerson.enumeration_model_updates_permitted = true > > ResponsiblePerson.create( :enumeration_type => > > ''responsible_person_type'', :code => ''ATT'', :name => ''Attorney'', > > :position => 1) > > x = ResponsiblePerson.find(:conditions => [''code = ?'', ''ATT'']) > > x.name > > > > What happens? Does ''Attorney'' get printed after the last line? > > > > After we figure out what''s going on with your records, I''ve got some > > recommendations that will make your life easier (your table definition > > is working against you a bit here). > > > > Regards, > > Trevor > > -- > > Trevor Squires > > http://somethinglearned.com > > > > _______________________________________________ > > Rails mailing list > > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > > http://lists.rubyonrails.org/mailman/listinfo/rails > > > > > -- > First they laugh at you, then they ignore you, then they fight you. > Then you win. > -- Mahatma Karamchand Gandhi >-- First they laugh at you, then they ignore you, then they fight you. Then you win. -- Mahatma Karamchand Gandhi