Ruby Methods and Optional parameters

后端 未结 11 1584

I\'m playing with Ruby on Rails and I\'m trying to create a method with optional parameters. Apparently there are many ways to do it. I trying naming the optional parameters

相关标签:
11条回答
  • 2020-12-13 09:58

    To answer the question of "why?": the way you're calling your function,

    my_info "Bill", age: 99, weight: 300, city: "Sao Paulo"
    

    is actually doing

    my_info "Bill", {:age => 99, :weight => 300, :city => "Sao Paulo"}
    

    Notice you are passing two parameters, "Bill" and a hash object, which will cause the default hash value you've provided in my_info2 to be completely ignored.

    You should use the default value approach that the other answerers have mentioned.

    0 讨论(0)
  • 2020-12-13 09:59

    You can also define method signatures with keyword arguments (New since, Ruby 2.0, since this question is old):

    def my_info2(name, age: 27, weight: 160, city: "New York", **rest_of_options)
        p [name, age, weight, city, rest_of_options]
    end
    
    my_info2('Joe Lightweight', weight: 120, age: 24, favorite_food: 'crackers')
    

    This allows for the following:

    • Optional parameters (:weight and :age)
    • Default values
    • Arbitrary order of parameters
    • Extra values collected in a hash using double splat (:favorite_food collected in rest_of_options)
    0 讨论(0)
  • 2020-12-13 10:03

    If you want to default the values in your options hash, you want to merge the defaults in your function. If you put the defaults in the default parameter itself, it'll be over-written:

    def my_info(name, options = {})
      options.reverse_merge!(age: 27, weight: 160, city: "New York")
    
      ...
    end
    
    0 讨论(0)
  • 2020-12-13 10:03

    #fetch is your friend!

    class Example
      attr_reader :age
      def my_info(name, options = {})
        @age = options.fetch(:age, 27)
        self
      end
    end
    
    person = Example.new.my_info("Fred")
    puts person.age #27
    
    0 讨论(0)
  • 2020-12-13 10:05

    I don't see anything wrong with using an or operator to set defaults. Here's a real life example (note, uses rails' image_tag method):

    file:

    def gravatar_for(user, options = {} )   
        height = options[:height] || 90
        width = options[:width] || 90
        alt = options[:alt] || user.name + "'s gravatar"
    
        gravatar_address = 'http://1.gravatar.com/avatar/'
    
        clean_email = user.email.strip.downcase 
        hash = Digest::MD5.hexdigest(clean_email)
    
        image_tag gravatar_address + hash, height: height, width: width, alt: alt 
    end
    

    console:

    2.0.0-p247 :049 > gravatar_for(user)
     => "<img alt=\"jim&#39;s gravatar\" height=\"90\" src=\"http://1.gravatar.com/avatar/<hash>\" width=\"90\" />" 
    2.0.0-p247 :049 > gravatar_for(user, height: 123456, width: 654321)
     => "<img alt=\"jim&#39;s gravatar\" height=\"123456\" src=\"http://1.gravatar.com/avatar/<hash>\" width=\"654321\" />" 
    2.0.0-p247 :049 > gravatar_for(user, height: 123456, width: 654321, alt: %[dogs, cats, mice])
     => "<img alt=\"dogs cats mice\" height=\"123456\" src=\"http://1.gravatar.com/avatar/<hash>\" width=\"654321\" />" 
    

    It feels similar to using the initialize method when calling a class.

    0 讨论(0)
提交回复
热议问题