SitePoint Sponsor

User Tag List

Results 1 to 21 of 21

Thread: Gotchas

Hybrid View

  1. #1
    SitePoint Evangelist
    Join Date
    Feb 2006
    Location
    Worcs. UK
    Posts
    404
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Gotchas

    Ruby on Rails is a fabulous frame work. However, I have been surprised by a couple of gotchas:

    Development log files can get very big very quickly
    I didn't notice this until I copied a development framework to a production server and suddenly lost a lot of disk space. The development.log file was over a gig. Of course, I should have been more careful with what I copied over but I wasn't..

    YAML files don't like tabs
    When I first started working with Rails, I was using an editor that put tabs in when I indented content. No problem until I started editing database.yml and got lots of strange errors. It took me a while to track down the problem.

    I now set up editors to only enter spaces.

    Ruby isn't very clever with dates
    I've found you have to be very cautious with dates. It doesn't help that Ruby has two data types (Time and Date) that do similar things, but are different. I try to use Datetime everywhere, but still get the odd surprise.

    Rail's handling of months isn't too clever either. 3.months.ago doesn't actually take you back three months but rather 3 times 30 days. That's well documented, but can catch out the unwary (ok - I mean it caught me out). Also worth pointing out that what Rails actually does is subtract 30 times the number of seconds in a day, from the current Time to go back one "month".

    Dividing an integer by an integer returns an integer
    1/2 = 0
    My more experienced programmings friend say "of course it does", but it caught me out. The solution:
    1.0/2.0 = 0.5

    Having said all that, otherwise developing using Ruby on Rails has been a joy. I love it.

    Any other gotchas out there that I've yet to find?
    Last edited by ReggieB; Apr 18, 2006 at 07:58.

  2. #2
    ☆★☆★ silver trophy vgarcia's Avatar
    Join Date
    Jan 2002
    Location
    in transition
    Posts
    21,235
    Mentioned
    1 Post(s)
    Tagged
    1 Thread(s)
    I got caught out by scope/access when I first got into Ruby. I didn't think that this:
    Code:
    class Whatever
      def method1
      end
    
      protected
      def method2
      end
    end
    was any different than this:
    Code:
    class Whatever
    
      protected
      def method2
      end
    
      def method1
      end
      
    end
    I didn't realize that every method under the "protected" keyword would be protected unless I changed it later on. Oops

  3. #3
    SitePoint Enthusiast Stevenwulf's Avatar
    Join Date
    May 2002
    Location
    Berkeley
    Posts
    76
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Don't ever name an instance variable in a controller @template

    I suppose some people would say "Duh," but I had created a controller for generating html templates and at the time it seemed logical to name an instance variable @template. Anyway, doing this totally blows up the app.

  4. #4
    SitePoint Wizard stereofrog's Avatar
    Join Date
    Apr 2004
    Location
    germany
    Posts
    4,324
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    My favorite gotcha is that "0" is "true". First time it costed me two hours to find out why "if(!count)" doesn't work...

    Quote Originally Posted by ReggieB
    Dividing an integer by an integer returns an integer
    1/2 = 0
    My more experienced programmings friend say "of course it does", but it caught me out.
    The good about ruby is that you can change almost everything:
    Code:
    class Fixnum
    	alias idiv /
    	def /(other)
    		self.to_f / other
    	end
    end
    
    print 1/2

  5. #5
    SitePoint Guru Majglow's Avatar
    Join Date
    Aug 1999
    Location
    B-Town
    Posts
    645
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by stereofrog
    My favorite gotcha is that "0" is "true". First time it costed me two hours to find out why "if(!count)" doesn't work...
    [/code]
    I might be weird, but I was quite happy when I found out about this. I tend to differentiate a lot between false and numbers including 0 in my code and didn't like $foo === false in PHP.

    quick example
    Code:
    if rating_percentage
      puts rating_percentage.to_s + '%'
    else
      puts 'no rating yet'
    end
    As for "Gotchas", the only thing I've encountered is the naming conventions. Sometimes I forget them and mess up (ie, when to use singular and when to use plurals).

    Are there any "cheat sheets" listing all these naming conventions?
    Ohai!

  6. #6
    ☆★☆★ silver trophy vgarcia's Avatar
    Join Date
    Jan 2002
    Location
    in transition
    Posts
    21,235
    Mentioned
    1 Post(s)
    Tagged
    1 Thread(s)
    Quote Originally Posted by Majglow
    As for "Gotchas", the only thing I've encountered is the naming conventions. Sometimes I forget them and mess up (ie, when to use singular and when to use plurals).

    Are there any "cheat sheets" listing all these naming conventions?
    Database tables: plural
    Models: singular
    Controllers: plural

    Any others?

  7. #7
    SitePoint Guru
    Join Date
    Aug 2005
    Posts
    986
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    This is not a real gotcha, but it is good to know.

    Don't stay away from the features other languages don't have, just because you don't know them.

    This code, for example:

    Code:
    time = '2006-04-17 10:57'
    year = time[0..3]
    month = time[5..6]
    day = time[8..9]
    hour = time[11..12]
    min = time[14..15]
    Time.local(year, month, day, hour, min)
    => Mon Apr 17 10:57:00 West-Europe(GMT) 2006
    Is very ugly, in my opinion. This is better:

    Code:
    time = '2006-04-17 10:57'
    Time.local(*[0..3, 5..6, 8..9, 11..12, 14..15].map{|r| time[r]})
    => Mon Apr 17 10:57:00 West-Europe(GMT) 2006
    Also, if, case, etc return values.

    So use this:

    Code:
    name = if only_first_name?
      first_name
    else
      [first_name, last_name].join(' ')
    end
    Instead of:

    Code:
    if only_first_name?
      name = first_name
    else
      name = [first_name, last_name].join(' ')
    end
    To remove duplication.

    And remember that (0..3).to_a => [0, 1, 2, 3] and (0...3).to_a => [0, 1, 2].

    Everything is true, *except* false and nil. So [], 0, {} are all true. Use obj.blank? to convert it to bools: [].blank? => true "".blank? => true, etc.

  8. #8
    SitePoint Wizard stereofrog's Avatar
    Join Date
    Apr 2004
    Location
    germany
    Posts
    4,324
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Fenrir2


    Code:
    time = '2006-04-17 10:57'
    Time.local(*[0..3, 5..6, 8..9, 11..12, 14..15].map{|r| time[r]})
    => Mon Apr 17 10:57:00 West-Europe(GMT) 2006
    How about
    Code:
    Time.local(*time.match(/(\d+)-(\d+)-(\d+)\s+(\d+):(\d+)/)[1..-1])

  9. #9
    SitePoint Zealot
    Join Date
    Jul 2004
    Location
    Oklahoma
    Posts
    119
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by ReggieB
    Ruby isn't very clever with dates
    I've found you have to be very cautious with dates. It doesn't help that Ruby has two data types (Time and Date) that do similar things, but are different. I try to use Datetime everywhere, but still get the odd surprise.

    Ruby's handling of months isn't too clever either. 3.months.ago doesn't actually take you back three months but rather 3 times 30 days. That's well documented, but can catch out the unwary (ok - I mean it caught me out). Also worth pointing out that what Ruby actually does is subtract 30 times the number of seconds in a day, from the current Time to go back one "month".
    I don't mean to be pedantic but Ruby doesn't have the (days|weeks|moths).ago functionality, that's a Rails extension.

  10. #10
    SitePoint Evangelist
    Join Date
    Jun 2004
    Location
    California
    Posts
    440
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Sgarissta
    I don't mean to be pedantic but Ruby doesn't have the (days|weeks|moths).ago functionality, that's a Rails extension.
    This is true.
    Happy switcher to OS X running on a MacBook Pro.

    Zend Certified Engineer

  11. #11
    SitePoint Evangelist
    Join Date
    Feb 2006
    Location
    Worcs. UK
    Posts
    404
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Sgarissta
    I don't mean to be pedantic but Ruby doesn't have the (days|weeks|moths).ago functionality, that's a Rails extension.
    Thank you for the correction Sgarissta. As my introduction to Ruby has been through Rails, I've been sloppy there. What I should have said was
    Quote Originally Posted by ReggieB
    Rail's handling of months isn't too clever either

  12. #12
    SitePoint Zealot
    Join Date
    Jul 2004
    Location
    Oklahoma
    Posts
    119
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by ReggieB
    Thank you for the correction Sgarissta. As my introduction to Ruby has been through Rails, I've been sloppy there. What I should have said was
    It's a very common mistake, I tend to be a bit over-zealous in correcting these mistakes, as I don't want people blaming the language for faults of the framework. But this is a nice list of gotchas, and I hope people keep posting, as both Ruby and Rails have a fair number of surprising elements.

  13. #13
    SitePoint Evangelist
    Join Date
    Feb 2006
    Location
    Worcs. UK
    Posts
    404
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Sgarissta
    I tend to be a bit over-zealous in correcting these mistakes, as I don't want people blaming the language for faults of the framework.
    I've just realised that I can still edit my original posting. This I have done now.

  14. #14
    SitePoint Guru
    Join Date
    Aug 2005
    Posts
    986
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Code:
    Time.local(*[0..3,5..6,8..9,11..12,14..15].map{|r|time[r]})
    Time.local(*time.match(/(\d+)-(\d+)-(\d+)\s+(\d+):(\d+)/)[1..-1])
    Good too, and checks a little bit stricter:

    1aa3?21&78`87^12

    Would be recognized as a valid thing by mine, but yours will see that it isn't

    But all this comes for the cost of 6 extra bytes ;-).

  15. #15
    SitePoint Guru Majglow's Avatar
    Join Date
    Aug 1999
    Location
    B-Town
    Posts
    645
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Wait... controllers: plural? what do you mean?
    Ohai!

  16. #16
    ☆★☆★ silver trophy vgarcia's Avatar
    Join Date
    Jan 2002
    Location
    in transition
    Posts
    21,235
    Mentioned
    1 Post(s)
    Tagged
    1 Thread(s)
    Quote Originally Posted by Majglow
    Wait... controllers: plural? what do you mean?
    If you want the same naming convention you'd get in a scaffold, but aren't using scaffolding, then your controller should be plural when you do script/generate
    Code:
    ruby script/generate controller pages

  17. #17
    Mal Reynolds Mandibal's Avatar
    Join Date
    Aug 2003
    Location
    Columbus
    Posts
    718
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Couple of cheat sheets:
    http://www.ilovejackdaniels.com/ruby...s-cheat-sheet/

    and this one which I think does cover the naming conventions:

    http://www.blainekendall.com/index.p...ilscheatsheet/
    Erh

  18. #18
    throw me a bone ... now bonefry's Avatar
    Join Date
    Nov 2004
    Location
    Romania
    Posts
    848
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    The block syntax with do ... end is not the same as the one that uses braces.
    Thus ...

    Code:
    v = [1,2,3,4]
    
    # correct
    x = v.find do |x| x % 3 == 0 end
    puts x
    
    # correct
    puts v.find { |x| x % 3 == 0 }
    
    # syntax error
    puts v.find do |x| x % 3 == 0 end
    
    # syntax error
    puts(v.find do |x| x % 3 == 0 end)
    the problem is that the do ... end block syntax has lower priority than the function call that's invoked with puts, while the braces syntax has higher priority.

  19. #19
    SitePoint Wizard stereofrog's Avatar
    Join Date
    Apr 2004
    Location
    germany
    Posts
    4,324
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Perhaps everyone's seen this before, but still

    Things That Newcomers to Ruby Should Know -- nice list of gotchas

    How Ruby Sucks by Matz.

  20. #20
    SitePoint Guru
    Join Date
    Aug 2005
    Posts
    986
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    This gotcha also works the other way around:

    Code:
    irb(main):001:0> def a(b)
    irb(main):002:1> yield b
    irb(main):003:1> end
    => nil
    irb(main):004:0> a 3 do |v| puts v; end
    3
    => nil
    irb(main):005:0> a 3 {|v| puts v}
    SyntaxError: compile error
    (irb):5: syntax error
    a 3 {|v| puts v}
         ^
            from (irb):5
    irb(main):006:0> a(3){|v| puts v}
    3
    => nil
    That's why you have to use do ... end to define a rake-task, rather than {...}.

  21. #21
    SitePoint Evangelist
    Join Date
    Jun 2004
    Location
    California
    Posts
    440
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Not really a gotcha as it is working as expected but this has bitten me in the butt a few times for not remembering: redirect_to and render do not end the action there. If you call a redirect_to or render later, after already calling one of either or both, you will get a double render error. Rails will not override the redirect to the new nor render the new. A way to get past this, if you wish the action to end at that redirect or render is to return that:
    Code:
    def bla
      ...
      return redirect_to :action => :index if something.problem?
      ...
      render :action => :bla
    end
    Happy switcher to OS X running on a MacBook Pro.

    Zend Certified Engineer


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •