key_struct

Defines KeyStruct, which acts the same as ruby’s Struct but the struct’s initializer takes keyword args (using a hash, rails-style). Use it to define a class via:

Name = KeyStruct[:first, :last]

or as an anonymous base class for your own enhanced struct:

class Name < KeyStruct[:first, :last]
  def to_s
    "#{@last}, #{@first}"
  end
end

Then you can create an instance of the class using keywords for the parameters:

name = Name.new(:first => "Jack", :last => "Ripper")

and you have the usal readers and writers:

name.first            # --> "Jack"
name.last             # --> "Ripper"
name.last = "Sprat"
name.last             # --> "Sprat"
name.to_s             # --> "Sprat, Jack" for the enhanced class example

Readers and Writers

As per above, the normal behavior is get readers and writers. But, by analogy with attr_reader vs attr_accessor, you can choose whether you want read/write or just read:

Writeable = KeyStruct.accesor(:first, :last)      # aliased as KeyStruct[]
Readonly = KeyStruct.reader(:first, :last)        # class has readers but not writers

Default values

If you leave off a keyword when instantiating, normally the member value is nil:

name = Name.new(:first => "Jack")
name.last             # --> nil

But the class definition can specify defaults, e.g.

Name = KeyStruct[:first, :last => "Doe"]

name = Name.new(:first => "John")
name.first            # --> "John"
name.last             # --> "Doe"

Argument Checking

The struct initializer checks for invalid arguments:

name = Name.new(:middle => "Xaviar")  # --> raises ArgumentError

Equaltiy

KeyStruct classes define the == operator, which returns true iff all corresponding struct members are equal (likewise via ==)

Name.new(:first => "John", :last => "Doe") == Name.new(:first => "John", :last => "Doe")    # --> true
Name.new(:first => "John", :last => "Doe") == Name.new(:first => "Jane", :last => "Doe")    # --> false

Installation

Install via:

% gem install key_struct

or in your Gemfile:

gem "key_struct"

Versions

Requires ruby >= 1.9.2. (Has been tested on MRI 1.9.2 and MRI 1.9.3)

History

Future: I hope that this gem will be obviated in future versions of ruby.

Note on Patches/Pull Requests

  • Fork the project.

  • Make your feature addition or bug fix.

  • Add tests for it. This is important so I don’t break it in a future version unintentionally. Make sure that the coverage report (generated automatically when you run rspec) is at 100%

  • Commit, do not mess with Rakefile, version, or history. (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)

  • Send me a pull request.

Released under the MIT License. See LICENSE for details.