title: Named Parameters in Ruby Structs
body: <p>I'm pretty new to Ruby so apologies if this is an obvious question.</p>
  
  <p>I'd like to use named parameters when instantiating a Struct, i.e. be able to specify which items in the Struct get what values, and default the rest to nil.</p>
  
  <p>For example I want to do:</p>
  
  <pre><code>Movie = Struct.new :title, :length, :rating
  m = Movie.new :title =&gt; 'Some Movie', :rating =&gt; 'R'
  </code></pre>
  
  <p>This doesn't work.</p>
  
  <p>So I came up with the following:</p>
  
  <pre><code>class MyStruct &lt; Struct
    # Override the initialize to handle hashes of named parameters
    def initialize *args
      if (args.length == 1 and args.first.instance_of? Hash) then
        args.first.each_pair do |k, v|
          if members.include? k then
            self[k] = v
          end
        end
      else
        super *args
      end
    end
  end
  
  Movie = MyStruct.new :title, :length, :rating
  m = Movie.new :title =&gt; 'Some Movie', :rating =&gt; 'R'
  </code></pre>
  
  <p>This seems to work just fine, but I'm not sure if there's a better way of doing this, or if I'm doing something pretty insane. If anyone can validate/rip apart this approach, I'd be most grateful.</p>
  
  <p><em>UPDATE</em></p>
  
  <p>I ran this initially in 1.9.2 and it works fine; however having tried it in other versions of Ruby (thank you rvm), it works/doesn't work as follows:</p>
  
  <ul>
  <li>1.8.7: Not working</li>
  <li>1.9.1: Working</li>
  <li>1.9.2: Working</li>
  <li>JRuby (set to run as 1.9.2): not working</li>
  </ul>
  
  <p>JRuby is a problem for me, as I'd like to keep it compatible with that for deployment purposes.</p>
  
  <p><em>YET ANOTHER UPDATE</em></p>
  
  <p>In this ever-increasing rambling question, I experimented with the various versions of Ruby and discovered that Structs in 1.9.x store their members as symbols, but in 1.8.7 and JRuby, they are stored as strings, so I updated the code to be the following (taking in the suggestions already kindly given):</p>
  
  <pre><code>class MyStruct &lt; Struct
    # Override the initialize to handle hashes of named parameters
    def initialize *args
      return super unless (args.length == 1 and args.first.instance_of? Hash)
      args.first.each_pair do |k, v|
        self[k] = v if members.map {|x| x.intern}.include? k
      end
    end
  end
  
  Movie = MyStruct.new :title, :length, :rating
  m = Movie.new :title =&gt; 'Some Movie', :rating =&gt; 'R'
  </code></pre>
  
  <p>This now appears to work for all the flavours of Ruby that I've tried.</p>