hashie 0.3.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/VERSION +1 -1
- data/hashie.gemspec +2 -2
- data/lib/hashie/dash.rb +47 -44
- data/lib/hashie/hash.rb +2 -0
- data/lib/hashie/mash.rb +26 -4
- data/spec/hashie/dash_spec.rb +115 -68
- data/spec/hashie/mash_spec.rb +85 -6
- data/spec/hashie/trash_spec.rb +1 -2
- metadata +5 -5
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.4.0
|
data/hashie.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{hashie}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.4.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Michael Bleigh"]
|
12
|
-
s.date = %q{2010-08-
|
12
|
+
s.date = %q{2010-08-31}
|
13
13
|
s.description = %q{Hashie is a small collection of tools that make hashes more powerful. Currently includes Mash (Mocking Hash) and Dash (Discrete Hash).}
|
14
14
|
s.email = %q{michael@intridea.com}
|
15
15
|
s.extra_rdoc_files = [
|
data/lib/hashie/dash.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'hashie/hash'
|
2
|
+
require 'set'
|
2
3
|
|
3
4
|
module Hashie
|
4
|
-
include Hashie::PrettyInspect
|
5
5
|
# A Dash is a 'defined' or 'discrete' Hash, that is, a Hash
|
6
6
|
# that has a set of defined keys that are accessible (with
|
7
7
|
# optional defaults) and only those keys may be set or read.
|
@@ -26,56 +26,55 @@ module Hashie
|
|
26
26
|
def self.property(property_name, options = {})
|
27
27
|
property_name = property_name.to_sym
|
28
28
|
|
29
|
-
|
30
|
-
(@defaults ||= {})[property_name] = options.delete(:default)
|
29
|
+
self.properties << property_name
|
31
30
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
end
|
31
|
+
if options[:default] or self.defaults[property_name]
|
32
|
+
self.defaults[property_name] = options[:default]
|
33
|
+
end
|
36
34
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
35
|
+
unless instance_methods.map { |m| m.to_s }.include?("#{property_name}=")
|
36
|
+
class_eval <<-ACCESSORS
|
37
|
+
def #{property_name}
|
38
|
+
_regular_reader(#{property_name.to_s.inspect})
|
39
|
+
end
|
42
40
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
ancestors.each do |elder|
|
48
|
-
if elder.instance_variable_defined?("@properties")
|
49
|
-
properties << elder.instance_variable_get("@properties")
|
50
|
-
end
|
41
|
+
def #{property_name}=(value)
|
42
|
+
_regular_writer(#{property_name.to_s.inspect}, value)
|
43
|
+
end
|
44
|
+
ACCESSORS
|
51
45
|
end
|
52
46
|
|
53
|
-
|
47
|
+
if defined? @subclasses
|
48
|
+
@subclasses.each { |klass| klass.property(property_name, options) }
|
49
|
+
end
|
54
50
|
end
|
55
51
|
|
56
|
-
|
57
|
-
|
58
|
-
def self.property?(prop)
|
59
|
-
properties.include?(prop.to_s)
|
52
|
+
class << self
|
53
|
+
attr_reader :properties, :defaults
|
60
54
|
end
|
55
|
+
instance_variable_set('@properties', Set.new)
|
56
|
+
instance_variable_set('@defaults', {})
|
61
57
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
end
|
69
|
-
end
|
58
|
+
def self.inherited(klass)
|
59
|
+
super
|
60
|
+
(@subclasses ||= Set.new) << klass
|
61
|
+
klass.instance_variable_set('@properties', self.properties.dup)
|
62
|
+
klass.instance_variable_set('@defaults', self.defaults.dup)
|
63
|
+
end
|
70
64
|
|
71
|
-
|
65
|
+
# Check to see if the specified property has already been
|
66
|
+
# defined.
|
67
|
+
def self.property?(name)
|
68
|
+
properties.include? name.to_sym
|
72
69
|
end
|
73
70
|
|
74
71
|
# You may initialize a Dash with an attributes hash
|
75
72
|
# just like you would many other kinds of data objects.
|
76
|
-
def initialize(attributes = {})
|
77
|
-
|
78
|
-
|
73
|
+
def initialize(attributes = {}, &block)
|
74
|
+
super(&block)
|
75
|
+
|
76
|
+
self.class.defaults.each_pair do |prop, value|
|
77
|
+
self.send("#{prop}=", value)
|
79
78
|
end
|
80
79
|
|
81
80
|
attributes.each_pair do |att, value|
|
@@ -83,26 +82,30 @@ module Hashie
|
|
83
82
|
end if attributes
|
84
83
|
end
|
85
84
|
|
85
|
+
alias_method :_regular_reader, :[]
|
86
|
+
alias_method :_regular_writer, :[]=
|
87
|
+
private :_regular_reader, :_regular_writer
|
88
|
+
|
86
89
|
# Retrieve a value from the Dash (will return the
|
87
90
|
# property's default value if it hasn't been set).
|
88
91
|
def [](property)
|
89
|
-
|
92
|
+
assert_property_exists! property
|
93
|
+
super(property.to_s)
|
90
94
|
end
|
91
95
|
|
92
96
|
# Set a value on the Dash in a Hash-like way. Only works
|
93
97
|
# on pre-existing properties.
|
94
98
|
def []=(property, value)
|
95
|
-
|
99
|
+
assert_property_exists! property
|
100
|
+
super(property.to_s, value)
|
96
101
|
end
|
97
102
|
|
98
103
|
private
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
unless self.class.property?(property.to_sym)
|
104
|
+
|
105
|
+
def assert_property_exists!(property)
|
106
|
+
unless self.class.property?(property)
|
103
107
|
raise NoMethodError, "The property '#{property}' is not defined for this Dash."
|
104
108
|
end
|
105
|
-
true
|
106
109
|
end
|
107
110
|
end
|
108
111
|
end
|
data/lib/hashie/hash.rb
CHANGED
data/lib/hashie/mash.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'hashie/hash'
|
2
|
+
|
1
3
|
module Hashie
|
2
4
|
# Mash allows you to create pseudo-objects that have method-like
|
3
5
|
# accessors for hash keys. This is useful for such implementations
|
@@ -79,7 +81,7 @@ module Hashie
|
|
79
81
|
# if there isn't a value already assigned to the key requested.
|
80
82
|
def initializing_reader(key)
|
81
83
|
ck = convert_key(key)
|
82
|
-
regular_writer(ck,
|
84
|
+
regular_writer(ck, self.class.new) unless key?(ck)
|
83
85
|
regular_reader(ck)
|
84
86
|
end
|
85
87
|
|
@@ -96,14 +98,20 @@ module Hashie
|
|
96
98
|
# Performs a deep_update on a duplicate of the
|
97
99
|
# current mash.
|
98
100
|
def deep_merge(other_hash)
|
99
|
-
dup.
|
101
|
+
dup.deep_update(other_hash)
|
100
102
|
end
|
103
|
+
alias_method :merge, :deep_merge
|
101
104
|
|
102
105
|
# Recursively merges this mash with the passed
|
103
106
|
# in hash, merging each hash in the hierarchy.
|
104
107
|
def deep_update(other_hash)
|
105
108
|
other_hash.each_pair do |k,v|
|
106
|
-
|
109
|
+
key = convert_key(k)
|
110
|
+
if regular_reader(key).is_a?(Mash) and v.is_a?(::Hash)
|
111
|
+
regular_reader(key).deep_update(v)
|
112
|
+
else
|
113
|
+
regular_writer(key, convert_value(v, true))
|
114
|
+
end
|
107
115
|
end
|
108
116
|
self
|
109
117
|
end
|
@@ -111,6 +119,20 @@ module Hashie
|
|
111
119
|
alias_method :update, :deep_update
|
112
120
|
alias_method :merge!, :update
|
113
121
|
|
122
|
+
# Performs a shallow_update on a duplicate of the current mash
|
123
|
+
def shallow_merge(other_hash)
|
124
|
+
dup.shallow_update(other_hash)
|
125
|
+
end
|
126
|
+
|
127
|
+
# Merges (non-recursively) the hash from the argument,
|
128
|
+
# changing the receiving hash
|
129
|
+
def shallow_update(other_hash)
|
130
|
+
other_hash.each_pair do |k,v|
|
131
|
+
regular_writer(convert_key(k), convert_value(v, true))
|
132
|
+
end
|
133
|
+
self
|
134
|
+
end
|
135
|
+
|
114
136
|
# Will return true if the Mash has had a key
|
115
137
|
# set in addition to normal respond_to? functionality.
|
116
138
|
def respond_to?(method_name)
|
@@ -141,7 +163,7 @@ module Hashie
|
|
141
163
|
|
142
164
|
def convert_value(val, duping=false) #:nodoc:
|
143
165
|
case val
|
144
|
-
when
|
166
|
+
when self.class
|
145
167
|
val.dup
|
146
168
|
when ::Hash
|
147
169
|
val = val.dup if duping
|
data/spec/hashie/dash_spec.rb
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
+
Hashie::Hash.class_eval do
|
4
|
+
def self.inherited(klass)
|
5
|
+
klass.instance_variable_set('@inheritance_test', true)
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
3
9
|
class DashTest < Hashie::Dash
|
4
10
|
property :first_name
|
5
11
|
property :email
|
@@ -10,100 +16,141 @@ class Subclassed < DashTest
|
|
10
16
|
property :last_name
|
11
17
|
end
|
12
18
|
|
13
|
-
describe
|
14
|
-
|
15
|
-
|
19
|
+
describe DashTest do
|
20
|
+
|
21
|
+
it('subclasses Hashie::Hash') { should respond_to(:to_mash) }
|
22
|
+
|
23
|
+
its(:to_s) { should == '<#DashTest count=0>' }
|
24
|
+
|
25
|
+
it 'lists all set properties in inspect' do
|
26
|
+
subject.first_name = 'Bob'
|
27
|
+
subject.email = 'bob@example.com'
|
28
|
+
subject.inspect.should == '<#DashTest count=0 email="bob@example.com" first_name="Bob">'
|
16
29
|
end
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
30
|
+
|
31
|
+
its(:count) { should be_zero }
|
32
|
+
|
33
|
+
it { should respond_to(:first_name) }
|
34
|
+
it { should respond_to(:first_name=) }
|
35
|
+
it { should_not respond_to(:nonexistent) }
|
36
|
+
|
37
|
+
it 'errors out for a non-existent property' do
|
38
|
+
lambda { subject['nonexistent'] }.should raise_error(NoMethodError)
|
22
39
|
end
|
23
40
|
|
24
|
-
|
25
|
-
it '
|
26
|
-
|
27
|
-
DashTest.properties.include?('not_an_att').should be_true
|
41
|
+
context 'writing to properties' do
|
42
|
+
it 'fails writing to a non-existent property using []=' do
|
43
|
+
lambda { subject['nonexistent'] = 123 }.should raise_error(NoMethodError)
|
28
44
|
end
|
29
45
|
|
30
|
-
it '
|
31
|
-
|
46
|
+
it 'works for an existing property using []=' do
|
47
|
+
subject['first_name'] = 'Bob'
|
48
|
+
subject['first_name'].should == 'Bob'
|
49
|
+
subject[:first_name].should == 'Bob'
|
32
50
|
end
|
33
51
|
|
34
|
-
it '
|
35
|
-
|
52
|
+
it 'works for an existing property using a method call' do
|
53
|
+
subject.first_name = 'Franklin'
|
54
|
+
subject.first_name.should == 'Franklin'
|
36
55
|
end
|
37
56
|
end
|
38
57
|
|
39
|
-
describe '
|
40
|
-
it '
|
41
|
-
lambda{
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
describe ' writing to properties' do
|
46
|
-
before do
|
47
|
-
@dash = DashTest.new
|
58
|
+
describe '.new' do
|
59
|
+
it 'fails with non-existent properties' do
|
60
|
+
lambda { described_class.new(:bork => '') }.should raise_error(NoMethodError)
|
48
61
|
end
|
49
62
|
|
50
|
-
it 'should
|
51
|
-
|
63
|
+
it 'should set properties that it is able to' do
|
64
|
+
obj = described_class.new :first_name => 'Michael'
|
65
|
+
obj.first_name.should == 'Michael'
|
52
66
|
end
|
53
|
-
|
54
|
-
it '
|
55
|
-
lambda{
|
67
|
+
|
68
|
+
it 'accepts nil' do
|
69
|
+
lambda { described_class.new(nil) }.should_not raise_error
|
56
70
|
end
|
57
|
-
|
58
|
-
it '
|
59
|
-
|
60
|
-
|
71
|
+
|
72
|
+
it 'accepts block to define a global default' do
|
73
|
+
obj = described_class.new { |hash, key| key.to_s.upcase }
|
74
|
+
obj.first_name.should == 'FIRST_NAME'
|
75
|
+
obj.count.should be_zero
|
61
76
|
end
|
62
77
|
end
|
63
|
-
|
64
|
-
describe '
|
65
|
-
it '
|
66
|
-
|
67
|
-
end
|
68
|
-
|
69
|
-
it 'should set properties that it is able to' do
|
70
|
-
DashTest.new(:first_name => 'Michael').first_name.should == 'Michael'
|
78
|
+
|
79
|
+
describe 'properties' do
|
80
|
+
it 'lists defined properties' do
|
81
|
+
described_class.properties.should == Set.new([:first_name, :email, :count])
|
71
82
|
end
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
lambda { DashTest.new(nil) }.should_not raise_error
|
83
|
+
|
84
|
+
it 'checks if a property exists' do
|
85
|
+
described_class.property?('first_name').should be_true
|
86
|
+
described_class.property?(:first_name).should be_true
|
77
87
|
end
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
before do
|
82
|
-
@dash = DashTest.new
|
88
|
+
|
89
|
+
it 'doesnt include property from subclass' do
|
90
|
+
described_class.property?(:last_name).should be_false
|
83
91
|
end
|
84
|
-
|
85
|
-
it '
|
86
|
-
|
87
|
-
DashTest.new.defaulted.should == 'abc'
|
92
|
+
|
93
|
+
it 'lists declared defaults' do
|
94
|
+
described_class.defaults.should == { :count => 0 }
|
88
95
|
end
|
89
96
|
end
|
90
97
|
end
|
91
98
|
|
92
|
-
describe
|
93
|
-
|
94
|
-
|
99
|
+
describe Hashie::Dash, 'inheritance' do
|
100
|
+
before do
|
101
|
+
@top = Class.new(Hashie::Dash)
|
102
|
+
@middle = Class.new(@top)
|
103
|
+
@bottom = Class.new(@middle)
|
95
104
|
end
|
96
|
-
|
97
|
-
it
|
98
|
-
|
105
|
+
|
106
|
+
it 'reports empty properties when nothing defined' do
|
107
|
+
@top.properties.should be_empty
|
108
|
+
@top.defaults.should be_empty
|
99
109
|
end
|
100
|
-
|
101
|
-
it
|
102
|
-
|
103
|
-
|
110
|
+
|
111
|
+
it 'inherits properties downwards' do
|
112
|
+
@top.property :echo
|
113
|
+
@middle.properties.should include(:echo)
|
114
|
+
@bottom.properties.should include(:echo)
|
115
|
+
end
|
116
|
+
|
117
|
+
it 'doesnt inherit properties upwards' do
|
118
|
+
@middle.property :echo
|
119
|
+
@top.properties.should_not include(:echo)
|
120
|
+
@bottom.properties.should include(:echo)
|
121
|
+
end
|
122
|
+
|
123
|
+
it 'allows overriding a default on an existing property' do
|
124
|
+
@top.property :echo
|
125
|
+
@middle.property :echo, :default => 123
|
126
|
+
@bottom.properties.to_a.should == [:echo]
|
127
|
+
@bottom.new.echo.should == 123
|
128
|
+
end
|
129
|
+
|
130
|
+
it 'allows clearing an existing default' do
|
131
|
+
@top.property :echo
|
132
|
+
@middle.property :echo, :default => 123
|
133
|
+
@bottom.property :echo
|
134
|
+
@bottom.properties.to_a.should == [:echo]
|
135
|
+
@bottom.new.echo.should be_nil
|
104
136
|
end
|
137
|
+
end
|
105
138
|
|
106
|
-
|
107
|
-
|
139
|
+
describe Subclassed do
|
140
|
+
|
141
|
+
its(:count) { should be_zero }
|
142
|
+
|
143
|
+
it { should respond_to(:first_name) }
|
144
|
+
it { should respond_to(:first_name=) }
|
145
|
+
it { should respond_to(:last_name) }
|
146
|
+
it { should respond_to(:last_name=) }
|
147
|
+
|
148
|
+
it 'has one additional property' do
|
149
|
+
described_class.property?(:last_name).should be_true
|
150
|
+
end
|
151
|
+
|
152
|
+
it "didn't override superclass inheritance logic" do
|
153
|
+
described_class.instance_variable_get('@inheritance_test').should be_true
|
108
154
|
end
|
155
|
+
|
109
156
|
end
|
data/spec/hashie/mash_spec.rb
CHANGED
@@ -67,12 +67,67 @@ describe Hashie::Mash do
|
|
67
67
|
@mash.author.website.should == Hashie::Mash.new(:url => "http://www.mbleigh.com/")
|
68
68
|
end
|
69
69
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
70
|
+
context "updating" do
|
71
|
+
subject {
|
72
|
+
described_class.new :first_name => "Michael", :last_name => "Bleigh",
|
73
|
+
:details => {:email => "michael@asf.com", :address => "Nowhere road"}
|
74
|
+
}
|
75
|
+
|
76
|
+
describe "#deep_update" do
|
77
|
+
it "should recursively Hashie::Mash Hashie::Mashes and hashes together" do
|
78
|
+
subject.deep_update(:details => {:email => "michael@intridea.com", :city => "Imagineton"})
|
79
|
+
subject.first_name.should == "Michael"
|
80
|
+
subject.details.email.should == "michael@intridea.com"
|
81
|
+
subject.details.address.should == "Nowhere road"
|
82
|
+
subject.details.city.should == "Imagineton"
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should make #update deep by default" do
|
86
|
+
subject.update(:details => {:address => "Fake street"}).should eql(subject)
|
87
|
+
subject.details.address.should == "Fake street"
|
88
|
+
subject.details.email.should == "michael@asf.com"
|
89
|
+
end
|
90
|
+
|
91
|
+
it "should clone before a #deep_merge" do
|
92
|
+
duped = subject.deep_merge(:details => {:address => "Fake street"})
|
93
|
+
duped.should_not eql(subject)
|
94
|
+
duped.details.address.should == "Fake street"
|
95
|
+
subject.details.address.should == "Nowhere road"
|
96
|
+
duped.details.email.should == "michael@asf.com"
|
97
|
+
end
|
98
|
+
|
99
|
+
it "regular #merge should be deep" do
|
100
|
+
duped = subject.merge(:details => {:email => "michael@intridea.com"})
|
101
|
+
duped.should_not eql(subject)
|
102
|
+
duped.details.email.should == "michael@intridea.com"
|
103
|
+
duped.details.address.should == "Nowhere road"
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
describe "shallow update" do
|
108
|
+
it "should shallowly Hashie::Mash Hashie::Mashes and hashes together" do
|
109
|
+
subject.shallow_update(:details => {
|
110
|
+
:email => "michael@intridea.com", :city => "Imagineton"
|
111
|
+
}).should eql(subject)
|
112
|
+
|
113
|
+
subject.first_name.should == "Michael"
|
114
|
+
subject.details.email.should == "michael@intridea.com"
|
115
|
+
subject.details.address.should be_nil
|
116
|
+
subject.details.city.should == "Imagineton"
|
117
|
+
end
|
118
|
+
|
119
|
+
it "should clone before a #regular_merge" do
|
120
|
+
duped = subject.shallow_merge(:details => {:address => "Fake street"})
|
121
|
+
duped.should_not eql(subject)
|
122
|
+
end
|
123
|
+
|
124
|
+
it "regular merge should be shallow" do
|
125
|
+
duped = subject.shallow_merge(:details => {:address => "Fake street"})
|
126
|
+
duped.details.address.should == "Fake street"
|
127
|
+
subject.details.address.should == "Nowhere road"
|
128
|
+
duped.details.email.should be_nil
|
129
|
+
end
|
130
|
+
end
|
76
131
|
end
|
77
132
|
|
78
133
|
it "should convert hash assignments into Hashie::Mashes" do
|
@@ -100,6 +155,30 @@ describe Hashie::Mash do
|
|
100
155
|
record['submash'].should be_kind_of(SubMash)
|
101
156
|
end
|
102
157
|
|
158
|
+
it "should respect the class when passed a bang method for a non-existent key" do
|
159
|
+
record = Hashie::Mash.new
|
160
|
+
record.non_existent!.should be_kind_of(Hashie::Mash)
|
161
|
+
|
162
|
+
class SubMash < Hashie::Mash
|
163
|
+
end
|
164
|
+
|
165
|
+
son = SubMash.new
|
166
|
+
son.non_existent!.should be_kind_of(SubMash)
|
167
|
+
end
|
168
|
+
|
169
|
+
it "should respect the class when converting the value" do
|
170
|
+
record = Hashie::Mash.new
|
171
|
+
record.details = Hashie::Mash.new({:email => "randy@asf.com"})
|
172
|
+
record.details.should be_kind_of(Hashie::Mash)
|
173
|
+
|
174
|
+
class SubMash < Hashie::Mash
|
175
|
+
end
|
176
|
+
|
177
|
+
son = SubMash.new
|
178
|
+
son.details = Hashie::Mash.new({:email => "randyjr@asf.com"})
|
179
|
+
son.details.should be_kind_of(SubMash)
|
180
|
+
end
|
181
|
+
|
103
182
|
describe '#respond_to?' do
|
104
183
|
it 'should respond to a normal method' do
|
105
184
|
Hashie::Mash.new.should be_respond_to(:key?)
|
data/spec/hashie/trash_spec.rb
CHANGED
@@ -9,8 +9,7 @@ describe Hashie::Trash do
|
|
9
9
|
|
10
10
|
describe 'translating properties' do
|
11
11
|
it 'adds the property to the list' do
|
12
|
-
TrashTest.
|
13
|
-
TrashTest.properties.should include('not_an_att')
|
12
|
+
TrashTest.properties.should include(:first_name)
|
14
13
|
end
|
15
14
|
|
16
15
|
it 'creates a method for reading the property' do
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hashie
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 15
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
8
|
+
- 4
|
9
|
+
- 0
|
10
|
+
version: 0.4.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Michael Bleigh
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-08-
|
18
|
+
date: 2010-08-31 00:00:00 -05:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|