SitePoint Sponsor

User Tag List

Results 1 to 11 of 11
  1. #1
    Avid Logophile silver trophy
    ParkinT's Avatar
    Join Date
    May 2006
    Location
    Central Florida
    Posts
    2,285
    Mentioned
    181 Post(s)
    Tagged
    4 Thread(s)

    Unhappy Nested Hash - can it be done?

    I am working on a small DSL; my first 'real' Ruby project.
    In one function I want to pass a Hash as the single parameter, but would really like the capability for it to be nested.
    Here is an example of what I have tried (unsuccessfully):
    Code Ruby:
       def bar(options=nil)
         if not options == nil
           @chartOrientation = (options[:orientation] != nil) ? options[:orientation].to_s : "default"
           @chartBarGroup = (nil != options[:grouped]) ? options[:grouped] : false
           if nil != options[:bars_width]
             self.chbh = options[:bars][:width].to_s
             self.chbh += options[:bars][:spacing_in_groups].to_s if not options[:bars][:spacing_in_groups] == nil
             self.chbh += options[:bars][:spacing_between_groups].to_s if ((nil != options[:bars][:spacing_in_groups]) && (nil != options[:bars][:spacing_between_groups]))
           end
         end
      ... more code ...
      end
    The essence of what I want is a Hash whose parameters are also other Hashes. (such as "options[:bars][:width]")
    I have met severe resistence from the compiler.
    Any guidance would be GREATLY appreciated.
    Don't be yourself. Be someone a little nicer. -Mignon McLaughlin, journalist and author (1913-1983)


    Literally, the best app for readers.
    Make Your P@ssw0rd Secure
    Leveraging SubDomains

  2. #2
    SitePoint Guru
    Join Date
    Aug 2005
    Posts
    986
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Sure you can do nested hash tables.

    All the nil checking is bad code smell.

    Code ruby:
    @chartOrientation = (options[:orientation] != nil) ? options[:orientation].to_s : "default"

    I'd do that like this:

    Code ruby:
    @chart_orientation = options[:orientation] || "default"

    Or better yet -- don't do it at all. Why don't you use a hash with all the default options and merge it with the options hash passed as a parameter.

    Like this:

    Code ruby:
    def bar(options = {})
      defaults = {:someoption => "some value", ...}
      options = defaults.merge(options)
      ...
    end

  3. #3
    Avid Logophile silver trophy
    ParkinT's Avatar
    Join Date
    May 2006
    Location
    Central Florida
    Posts
    2,285
    Mentioned
    181 Post(s)
    Tagged
    4 Thread(s)
    That is brilliant!
    Actually, quite elegant (very Ruby-esque)

    Thanks for the help.
    Don't be yourself. Be someone a little nicer. -Mignon McLaughlin, journalist and author (1913-1983)


    Literally, the best app for readers.
    Make Your P@ssw0rd Secure
    Leveraging SubDomains

  4. #4
    SitePoint Enthusiast AllTom's Avatar
    Join Date
    Feb 2008
    Location
    Wherever danger lies...
    Posts
    48
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Did you figure out nested hashes?

    Code Ruby:
    { :a => "a", :b => { :x => "x", :y => "y" } }
    There are some things you shouldn't try to code at home.

  5. #5
    Avid Logophile silver trophy
    ParkinT's Avatar
    Join Date
    May 2006
    Location
    Central Florida
    Posts
    2,285
    Mentioned
    181 Post(s)
    Tagged
    4 Thread(s)
    Yes, AllTom. I thought.
    But, as I work on it more and more it begins to demonstrate strange behavior.
    Do you have some insight on this?
    Don't be yourself. Be someone a little nicer. -Mignon McLaughlin, journalist and author (1913-1983)


    Literally, the best app for readers.
    Make Your P@ssw0rd Secure
    Leveraging SubDomains

  6. #6
    SitePoint Enthusiast AllTom's Avatar
    Join Date
    Feb 2008
    Location
    Wherever danger lies...
    Posts
    48
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    What kind of behavior do you get? In my experience, unlike some other corners of Ruby, hash syntax has been consistent.
    There are some things you shouldn't try to code at home.

  7. #7
    Avid Logophile silver trophy
    ParkinT's Avatar
    Join Date
    May 2006
    Location
    Central Florida
    Posts
    2,285
    Mentioned
    181 Post(s)
    Tagged
    4 Thread(s)

    Merging Hashes

    Apparently, the .merge command is NOT giving me what I want.
    I thought using .merge! was the answer. But, there I am still not getting an XOR of the hash values.

    With this call in my controller:
    Code Ruby:
         @chart.bar(:options => {:bars => { :grouped =>true, :width => 30}, :orientation => "horizontal"})
    I used, as Fenrir2 suggested, this in the 'def' (my mixin class)
    Code Ruby:
    puts options.inspect
         defaults = {:orientation=>"horizontal", :bars => {:width=>30, :spacing_in_groups => nil, :spacing_between_groups => nil, :grouped => false}}
         options = defaults.merge!(options)
    puts options.inspect
    *The PUTS are for troubleshooting.

    ----
    My results demonstrate that the hash "options" contains both the defaults AND my input values.
    Code Ruby:
    {:options=>{:bars=>{:width=>30, :grouped=>true}, :orientation=>"horizontal"}}
    {:bars=>{:width=>30, :grouped=>false, :spacing_in_groups=>nil, :spacing_between_groups=>nil}, :orientation=>"horizontal", :options=>{:bars=>{:width=>30, :grouped=>true}, :orientation=>"horizontal"}}

    What I want is the ability to pass any (all or none) of the parameters into my method.
    Any guidance would be greatly appreciated.
    Don't be yourself. Be someone a little nicer. -Mignon McLaughlin, journalist and author (1913-1983)


    Literally, the best app for readers.
    Make Your P@ssw0rd Secure
    Leveraging SubDomains

  8. #8
    SitePoint Guru
    Join Date
    Aug 2005
    Posts
    986
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I see. The problem is that you're calling your method like this:

    Code ruby:
    @chart.bar(:options => {:bars => { :grouped =>true, :width => 30}, :orientation => "horizontal"})

    But I assumed that you'd call it like this:

    Code ruby:
    @chart.bar(:bars => { :grouped =>true, :width => 30}, :orientation => "horizontal")

    That is, without the outer options => .... Try this code, it should work

    I personally like the second way better because it's shorter, but if you want to use options, then you can modify the method like this:

    Code ruby:
    def bar(options)
      options = options[:options]
      defaults = {...}
      options = defaults.merge(options)
      ...
    end

    BTW, you don't have to use merge!, merge works too.

  9. #9
    Avid Logophile silver trophy
    ParkinT's Avatar
    Join Date
    May 2006
    Location
    Central Florida
    Posts
    2,285
    Mentioned
    181 Post(s)
    Tagged
    4 Thread(s)
    Thanks, Fenrir2.
    I also prefer the shorter (aka more concise) method.

    After my last post I realized the stupidity I was demonstrating (a few well-placed "options.inspect" calls helped).
    Thanks for your help.
    Don't be yourself. Be someone a little nicer. -Mignon McLaughlin, journalist and author (1913-1983)


    Literally, the best app for readers.
    Make Your P@ssw0rd Secure
    Leveraging SubDomains

  10. #10
    SitePoint Guru
    Join Date
    Aug 2005
    Posts
    986
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Haha, but the topic is confusing, especially the hash as named parameters. I didn't see the problem at first either.

  11. #11
    Avid Logophile silver trophy
    ParkinT's Avatar
    Join Date
    May 2006
    Location
    Central Florida
    Posts
    2,285
    Mentioned
    181 Post(s)
    Tagged
    4 Thread(s)
    Thanks for your help.
    I am beginning to feel comfortable with Ruby. But there are areas into which I have not completely ventured. Of course, we use hashes a lot.
    This is my first time developing a function that needs to receive a hash as a parameter.
    But, that is how we learn!!
    Don't be yourself. Be someone a little nicer. -Mignon McLaughlin, journalist and author (1913-1983)


    Literally, the best app for readers.
    Make Your P@ssw0rd Secure
    Leveraging SubDomains


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
  •