diff options
author | Michael Bleigh <michael@intridea.com> | 2009-11-12 09:08:55 -0500 |
---|---|---|
committer | Michael Bleigh <michael@intridea.com> | 2009-11-12 09:08:55 -0500 |
commit | 12449988586fbb2a75a378bc1864a3e3b0143a53 (patch) | |
tree | a7e0560d740770ec55a04ae45d6d0427c9116bdf | |
parent | fc03a24666ee9db6cfb6c85c6b1fa12d3308c586 (diff) | |
download | hashie-12449988586fbb2a75a378bc1864a3e3b0143a53.tar.gz |
Adding README
-rw-r--r-- | LICENSE | 2 | ||||
-rw-r--r-- | README.rdoc | 69 | ||||
-rw-r--r-- | Rakefile | 7 | ||||
-rw-r--r-- | lib/hashie.rb | 3 | ||||
-rw-r--r-- | lib/hashie/dash.rb | 72 | ||||
-rw-r--r-- | spec/hashie/dash_spec.rb | 58 | ||||
-rw-r--r-- | spec/hashie_spec.rb | 7 |
7 files changed, 200 insertions, 18 deletions
@@ -1,4 +1,4 @@ -Copyright (c) 2009 Michael Bleigh +Copyright (c) 2009 Intridea, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/README.rdoc b/README.rdoc index fbf75b3..fcba853 100644 --- a/README.rdoc +++ b/README.rdoc @@ -3,17 +3,74 @@ Hashie is a growing collection of tools that extend Hashes and make them more useful. +== Installation + +Hashie is a gem and is available on Gemcutter. If you don't have Gemcutter, +install it: + + gem install gemcutter + gem tumble + +Then you can install Hashie: + + gem install hashie + +== Mash + +Mash is an extended Hash that gives simple pseudo-object functionality +that can be built from hashes and easily extended. It is designed to +be used in RESTful API libraries to provide easy object-like access +to JSON and XML parsed hashes. + +=== Example: + + mash = Hashie::Mash.new + mash.name? # => false + mash.name # => nil + mash.name = "My Mash" + mash.name # => "My Mash" + mash.name? # => true + mash.inspect # => <Hashie::Mash name="My Mash"> + + mash = Mash.new + # use bang methods for multi-level assignment + mash.author!.name = "Michael Bleigh" + mash.author # => <Hashie::Mash name="Michael Bleigh"> + +== Dash + +Dash is an extended Hash that has a discrete set of defined properties +and only those properties may be set on the hash. Additionally, you +can set defaults for each property. + +=== Example: + + class Person < Hashie::Dash + property :name + property :email + property :occupation, :default => 'Rubyist' + end + + p = Person.new + p.name # => nil + p.occupation # => 'Rubyist' + p.email = 'abc@def.com' + p.email # => 'abc@def.com' + p['awesome'] # => NoMethodError + + == 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. -* 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) +* Add tests for it. This is important so I don't break it in a future version unintentionally. +* 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. Bonus points for topic branches. +== Authors + +* Michael Bleigh + == Copyright -Copyright (c) 2009 Michael Bleigh. See LICENSE for details. +Copyright (c) 2009 Intridea, Inc (http://intridea.com/). See LICENSE for details. @@ -5,14 +5,15 @@ begin require 'jeweler' Jeweler::Tasks.new do |gem| gem.name = "hashie" - gem.summary = %Q{TODO: one-line summary of your gem} - gem.description = %Q{TODO: longer description of your gem} + gem.summary = %Q{Your friendly neighborhood hash toolkit.} + gem.description = %Q{Hashie is a small collection of tools that make hashes more powerful. Currently includes Mash (Mocking Hash) and Dash (Discrete Hash).} gem.email = "michael@intridea.com" - gem.homepage = "http://github.com/mbleigh/hashie" + gem.homepage = "http://github.com/intridea/hashie" gem.authors = ["Michael Bleigh"] gem.add_development_dependency "rspec" # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings end + Jeweler::GemcutterTasks.new rescue LoadError puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler" end diff --git a/lib/hashie.rb b/lib/hashie.rb index e24d544..87c8d45 100644 --- a/lib/hashie.rb +++ b/lib/hashie.rb @@ -1,3 +1,4 @@ require 'hashie/hash_extensions' require 'hashie/hash' -require 'hashie/mash'
\ No newline at end of file +require 'hashie/mash' +require 'hashie/dash'
\ No newline at end of file diff --git a/lib/hashie/dash.rb b/lib/hashie/dash.rb new file mode 100644 index 0000000..9e5bb48 --- /dev/null +++ b/lib/hashie/dash.rb @@ -0,0 +1,72 @@ +require 'hashie/hash' + +module Hashie + # A Dash is a 'defined' or 'discrete' Hash, that is, a Hash + # that has a set of defined keys that are accessible (with + # optional defaults) and only those keys may be set or read. + # + # Dashes are useful when you need to create a very simple + # lightweight data object that needs even fewer options and + # resources than something like a DataMapper resource. + # + # It is preferrable to a Struct because of the in-class + # API for defining properties as well as per-property defaults. + class Dash < Hashie::Hash + # Defines a property on the Dash. Options are + # as follows: + # + # * <tt>:default</tt> - Specify a default value for this property, + # to be returned before a value is set on the property in a new + # Dash. + # + def self.property(property_name, options = {}) + property_name = property_name.to_sym + + (@properties ||= []) << property_name + (@defaults ||= {})[property_name] = options.delete(:default) + + class_eval <<-RUBY + def #{property_name} + self['#{property_name}'] + end + + def #{property_name}=(val) + self['#{property_name}'] = val + end + RUBY + end + + # Get a String array of the currently defined + # properties on this Dash. + def self.properties + @properties.collect{|p| p.to_s} + end + + # Check to see if the specified property has already been + # defined. + def self.property?(prop) + properties.include?(prop.to_s) + end + + # The default values that have been set for this Dash + def self.defaults + @defaults + end + + # Retrieve a value from the Dash (will return the + # property's default value if it hasn't been set). + def [](property_name) + super || self.class.defaults[property_name.to_sym] + end + + # Set a value on the Dash in a Hash-like way. Only works + # on pre-existing properties. + def []=(property, value) + if self.class.property?(property) + super + else + raise NoMethodError, 'You may only set pre-defined properties.' + end + end + end +end
\ No newline at end of file diff --git a/spec/hashie/dash_spec.rb b/spec/hashie/dash_spec.rb new file mode 100644 index 0000000..d9fc01e --- /dev/null +++ b/spec/hashie/dash_spec.rb @@ -0,0 +1,58 @@ +require File.dirname(__FILE__) + '/../spec_helper' + +class DashTest < Hashie::Dash + property :first_name + property :email + property :count, :default => 0 +end + +describe Hashie::Dash do + it 'should be a subclass of Hashie::Hash' do + (Hashie::Dash < Hash).should be_true + end + + describe ' creating properties' do + it 'should add the property to the list' do + DashTest.property :not_an_att + DashTest.properties.include?('not_an_att').should be_true + end + + it 'should create a method for reading the property' do + DashTest.new.respond_to?(:first_name).should be_true + end + + it 'should create a method for writing the property' do + DashTest.new.respond_to?(:first_name=).should be_true + end + end + + describe ' writing to properties' do + before do + @dash = DashTest.new + end + + it 'should not be able to write to a non-existent property using []=' do + lambda{@dash['abc'] = 123}.should raise_error(NoMethodError) + end + + it 'should be able to write to an existing property using []=' do + lambda{@dash['first_name'] = 'Bob'}.should_not raise_error + end + + it 'should be able to read/write to an existing property using a method call' do + @dash.first_name = 'Franklin' + @dash.first_name.should == 'Franklin' + end + end + + describe ' defaults' do + before do + @dash = DashTest.new + end + + it 'should return the default value for defaulted' do + DashTest.property :defaulted, :default => 'abc' + DashTest.new.defaulted.should == 'abc' + end + end +end
\ No newline at end of file diff --git a/spec/hashie_spec.rb b/spec/hashie_spec.rb deleted file mode 100644 index fd8dc81..0000000 --- a/spec/hashie_spec.rb +++ /dev/null @@ -1,7 +0,0 @@ -require File.expand_path(File.dirname(__FILE__) + '/spec_helper') - -describe "Hashie" do - it "fails" do - fail "hey buddy, you should probably rename this file and start specing for real" - end -end |