Chris Bloom
2007-Oct-04 21:24 UTC
[TIP] Working with columns that end with "?", like "male?"
I was about to write a really long question asking how to do this, then I figured it out. I figured I''d post it in case anyone else runs into it. Lets say you have the following hypothetical table associated with the model Attendee: create_table :attendees do |t| t.column :name, :string t.column :first_time?, :string, :limit => 3, :default => "no" t.column :first_place?, :boolean, :default => false end I altered between using a string and a boolean for the sake of the example. Chances are you''d use one or the other. Now in Erb:>> a = Attendee.new=> #<Attendee:0x493421c @attributes={"first_place?"=>false,\ "name"=>nil, "first_time?"=>"no"}, @new_record=true> By convention, ActiveRecord automatically creates a "#{field_name}?" method for each field in your table which returns true or false depending on if the field is valued. So if we entered>> a.methodsWe''d see among the results "name" and "name?", correlating to the name column we created.>> a.name?=> false>> a.name = "CDB"=> "CDB">> a.name?=> true However, ActiveRecord does not create these methods if your field ends in with a "?"! In the list of methods mentioned above we would see only "first_place?" and "first_time?", not "first_place??" nor "first_time??" as I expected. It turns out that ActiveRecord skips this step because it sees there is already a method with this name.>> a.first_place?=> false>> a.first_time?=> "no" The first example is misleading as it returns a boolean just as our name? method does. This is because the field itself is a Boolean field. In fact, there really is no distinction between the name? method that ActiveRecord generates and the first_place? method that correlates to our field.>> a.first_place?.class=> TrueClass>> a.first_place?.class.ancestors=> [TrueClass, Object, Base64::Deprecated, Base64, Kernel]>> a.name?.class=> TrueClass>> a.name?.class.ancestors=> [TrueClass, Object, Base64::Deprecated, Base64, Kernel] The tricky part here is that ActiveRecord, for some reason, won''t let you set a new value to the first_time? and first_place? fields as you would normally do.>> a.first_place? = trueSyntaxError: compile error (irb):69: syntax error, unexpected ''='', expecting $end a.first_place? = true ^ from (irb):69 from :0>> a.first_time? = "yes"SyntaxError: compile error (irb):70: syntax error, unexpected ''='', expecting $end a.first_time? = "yes" ^ from (irb):70 from :0 So how do we do it? Using an alternate accessor syntax:>> a["first_time?"]=> "no">> a["first_time?"] = "yes"=> "yes">> a["first_place?"]=> true>> a["first_place?"] = false=> false I hope that saves someone else a bit of sanity. It had me scratching my head for a while. I''m not sure if this is a "bug" or a "feature", but I plan on reporting it just in case. ~ Chris -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Lionel Bouton
2007-Oct-04 21:29 UTC
Re: [TIP] Working with columns that end with "?", like "male?"
Chris Bloom wrote the following on 04.10.2007 23:24 :> [...] >>> a.first_place? = true >>> > SyntaxError: compile error > (irb):69: syntax error, unexpected ''='', expecting $end > a.first_place? = true > ^ > from (irb):69 > from :0 >This tries to send "first_place?=" to the a object. My guess is that it is Ruby that prevents the ? from being part of the method name unless it is the last character. Nothing ActiveRecord can do about it... Lionel --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Pat Maddox
2007-Oct-04 21:36 UTC
Re: [TIP] Working with columns that end with "?", like "male?"
On 10/4/07, Lionel Bouton <lionel-subscription-WTamNBQcZIx7tPAFqOLdPg@public.gmane.org> wrote:> > Chris Bloom wrote the following on 04.10.2007 23:24 : > > [...] > >>> a.first_place? = true > >>> > > SyntaxError: compile error > > (irb):69: syntax error, unexpected ''='', expecting $end > > a.first_place? = true > > ^ > > from (irb):69 > > from :0 > > > > This tries to send "first_place?=" to the a object. > > My guess is that it is Ruby that prevents the ? from being part of the > method name unless it is the last character. > > Nothing ActiveRecord can do about it...I think the real question is why on earth would you want to have those column names in the first place? If you have to work with a legacy db, sure, but I''d never ever ever do that in a migration myself. And if I did have a legacy db with that schema, I''d just write some sensible methods: def male=(val) write_attribute :male?, val end def male read_attribute :male? end def male? !!male end Normal assignment, raw attribute, and predicate...the Rails Way. Pat --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Chris Bloom
2007-Oct-05 02:01 UTC
Re: [TIP] Working with columns that end with "?", like "male
Lionel Bouton wrote:> My guess is that it is Ruby that prevents the ? from being part of the > method name unless it is the last character. > > Nothing ActiveRecord can do about it...Good point, Lionel. Pat Maddox wrote:> I think the real question is why on earth would you want to have those > column names in the first place? If you have to work with a legacy > db, sure, but I''d never ever ever do that in a migration myself.I didn''t write this to encourage anyone to do so, but in case anyone did run into it. I work with an "enterprise helpdesk application" (read: bloated piece of crap built on ASP) and the database has a mess of fields with special characters like that. So, if you can''t get RoR to work with your fields in the dot syntax, you can go at it the model["quoted_field_name"] way.> And if I did have a legacy db with that schema, I''d just write some > sensible methods: > > def male=(val) > write_attribute :male?, val > end > > def male > read_attribute :male? > end > > def male? > !!male > endYeah, that makes sense. I didn''t actually make it to the model code when I found this. I was working Erb trying to get some associations to work (see my numerous previous topics) and worked it out there before calling it quits for the day. You''re right though, you''re better off just building better accessor methods if those are the field names that you''re stuck with. Again. I''m not advocating using special field names, however: 1. This *does* follow the Ruby convention of least surprise (first_place? answers a question and returns a boolean), so it seemed natural to try to extend that to the DB (I know better now) 2. ActiveRecord didn''t complain about creating a column named :first_place?, so I would expect it to also handle it properly when accessing it later. Or, throw an error or warning when creating the field saying that YMMV when using that syntax. Thanks for weighing in. -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---