squares 0.2.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 09592e711ca540e1b0fb97bb9e841af69cb34175
4
+ data.tar.gz: e3d626d74d1184b164f5ba4f90b1cf1c7567610e
5
+ SHA512:
6
+ metadata.gz: 60351a2a9e968f992a4c578e2853729a090d15e3c4ec0d9d8d153d99686eb7b81081c4808ad3485d35ed71938ea3130b0079ec9f3d2bfc6ac888881128d4e3df
7
+ data.tar.gz: fc865c89c8de7e4fbbb5f6ffc0ca5e344a772848b29456f2cbc7618ede6c6e601e2c38951a2b088fad7aed3e166b76262510d1808961fe5cfe6788ae019e6ee0
data/.gitignore ADDED
@@ -0,0 +1,16 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
15
+ .ruby-version
16
+ .ruby-gemset
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,3 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1.5
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in squares.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Joel Helbling
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,189 @@
1
+ # Squares \[\*\]
2
+
3
+ A lightweight ORM backed by any hash-like storage. Hand-crafted from a solid piece of pure
4
+ aircraft-grade Ruby and drawing distilled awesomeness from atmospheric pollutants, its only
5
+ dependency is you.
6
+
7
+ ## Installation Blah, Blah, Blah
8
+
9
+ _I swear, this part of the README just rolled right out of `bundle gem squares`._
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ ```ruby
14
+ gem 'squares'
15
+ ```
16
+
17
+ And then execute:
18
+
19
+ $ bundle
20
+
21
+ Or install it yourself as:
22
+
23
+ $ gem install squares
24
+
25
+ _And yeah, I did enjoy typing `bundle gem squares`. It sounds like something to
26
+ eat. Now I'm hungry._
27
+
28
+ ## Usage
29
+
30
+ _Because you are going to use it._
31
+
32
+ ```ruby
33
+ require 'squares'
34
+ ```
35
+
36
+ ### Write Models
37
+
38
+ _How come they never write back?_
39
+
40
+ ```ruby
41
+ class Person < Squares::Base
42
+ properties :real_name, :age
43
+ end
44
+ ```
45
+
46
+ You can also provide a default value if you switch to the `property` variant:
47
+
48
+ ```ruby
49
+ class Person < Squares::Base
50
+ property :eye_color, default: 'brown'
51
+ end
52
+ ```
53
+
54
+ ### Bootstrapping
55
+
56
+ _A funny word for "setup & configure". Bootstrapping. Bootstrapping. See? Funny._
57
+
58
+ Now you can bootstrap `;)` your model to a hash-like storage object like so:
59
+
60
+ ```ruby
61
+ people_storage = Redis::Namespace.new(
62
+ Person.underscore_name,
63
+ :redis => $redis_connection )
64
+
65
+ Person.store = people_storage
66
+ ```
67
+
68
+ Or setup a bunch of 'em like this:
69
+
70
+ ```ruby
71
+ [Person, Place, Thing].each do |model|
72
+ model.store = LevelDB::DB.new("./tmp/#{model.underscore_name}")
73
+ end
74
+ ```
75
+
76
+ ...or if you just want to use a plain ole in-memory hash:
77
+
78
+ ```ruby
79
+ tom_sellecks_mustache = {}
80
+ Soup.store = tom_sellecks_mustache
81
+ ```
82
+
83
+ Squares actually defaults the store to an empty hash, which means if you're ok
84
+ with in-memory, transient storage (e.g. when writing tests, etc.) you don't have
85
+ to do any config-- er, bootstrapping `;)` at all!
86
+
87
+ ### Onward To The Fun
88
+
89
+ Squares does not auto-generate an `:id` for each new object --you'll do that
90
+ and it will be used as the "key" in the hash storage. In the following example,
91
+ we're creating a new `Person` and using 'spiderman' as the key:
92
+
93
+ ```ruby
94
+ pete = Person.new('spiderman', real_name: 'Peter Parker', age: 17)
95
+ # ^^^ key ^^^ ^^^^^^^^^^^ properties ^^^^^^^^^^^
96
+ pete.save
97
+
98
+ Person.has_key? 'spiderman' #=> true
99
+ pete.id #=> 'spiderman'
100
+ ```
101
+
102
+ When we retrieve an object, it returns an instance of that model:
103
+
104
+ ```ruby
105
+ wallcrawler = Person['spiderman']
106
+ wallcrawler = Person.find 'spiderman' #=> same, shmame.
107
+ wallcrawler.id #=> 'spiderman'
108
+ wallcrawler.real_name #=> 'Peter Parker'
109
+ wallcrawler.class #=> Person
110
+ ```
111
+
112
+ Of course, for some types of storage, the model object has to be serialized and
113
+ de-serialized when it's stored and retrieved. Squares uses `Marshal.dump` and
114
+ `Marshal.restore` to do that. This means that custom marshalling can be added
115
+ to your models (see [documentation on ruby Marshal][marshal]).
116
+
117
+ ### Even More Fun
118
+
119
+ You can use the ActiveRecord-esque `.where` method with a block to retrieve records
120
+ for which the block returns true:
121
+
122
+ ```ruby
123
+ Person.where { |p| p.left_handed == true } #=> all the lefties
124
+ ```
125
+
126
+ The `.where` method is actually just an alias of `.select`...which means, yeah!
127
+ Squares are enumerable, yay!
128
+
129
+ ```ruby
130
+ Person.map(&:name) #=> an array containing all the names
131
+ ```
132
+
133
+ ### What It Doesn't Do
134
+
135
+ Much like Wolverine, Squares doesn't do relationships. You'll have to
136
+ maintain those in your code. If you have an issue with that, leave me
137
+ an issue, and I'll think about what that might mean.
138
+
139
+ Squares neither knows nor cares about the type or contents of your model
140
+ instance's properties. This has consequences.
141
+
142
+ First, anything you stash had darn well better be marshal-able, or there
143
+ will be blood on the roller-rink. Or at least errors. Yeah, I've made
144
+ sure there won't be blood (you're welcome), but watch out for errors.
145
+ If you run into problems, refer to the [documentation on ruby Marshal][marshal].
146
+
147
+ Second, there is no magic-fu for stuff like generating question methods
148
+ for boolean properties. For example, it doesn't make a `#left_handed?` method
149
+ out of your `property :left_handed`). But hey, you know what you can
150
+ do? Behold:
151
+
152
+ ```ruby
153
+ class Person
154
+ property :awesome?, default: true #=> What?! is that a "?"
155
+ end
156
+ ```
157
+
158
+ Ok, don't interrupt me, I'm selling here...
159
+
160
+ ```ruby
161
+ you = Person.new
162
+ you.awesome? #=> true
163
+ ```
164
+
165
+ Of course, Squares doesn't mind how you use `#awesome?` and the corresponding `#awesome=` methods:
166
+
167
+ ```ruby
168
+ you.awesome = 'yak hair'
169
+ you.awesome? #=> 'yak hair'
170
+ ```
171
+
172
+ or
173
+
174
+ ```ruby
175
+ you.awesome = nil
176
+ you.awesome? #=> nil
177
+ ```
178
+
179
+ But hey, who cares, as long as yak hair is truthy?
180
+
181
+ [marshal]:http://www.ruby-doc.org/core-2.1.5/Marshal.html
182
+
183
+ ## Contributing
184
+
185
+ 1. Fork it ( https://github.com/joelhelbling/squares/fork )
186
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
187
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
188
+ 4. Push to the branch (`git push origin my-new-feature`)
189
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
7
+
@@ -0,0 +1,144 @@
1
+ module Squares
2
+ class Base
3
+ attr_accessor :id
4
+
5
+ def initialize *args
6
+ apply *args
7
+ end
8
+
9
+ def save
10
+ store[@id] = Marshal.dump self
11
+ nil
12
+ end
13
+
14
+ def == other
15
+ @id == other.id && properties_equal(other)
16
+ end
17
+
18
+ def properties
19
+ self.class.properties
20
+ end
21
+
22
+ private
23
+
24
+ def properties_equal other
25
+ ! properties.detect do |property|
26
+ self.send(property) != other.send(property)
27
+ end
28
+ end
29
+
30
+ def apply *args
31
+ @id, value_hash = *args
32
+ self.class.properties.each do |property|
33
+ value = args.last.to_h[property] || self.class.defaults[property]
34
+ # self.class.method_for(property)
35
+ self.send "#{property.to_s.gsub(/\?$/,'')}=".to_sym, value
36
+ end
37
+ end
38
+
39
+ def store
40
+ self.class.store
41
+ end
42
+
43
+ #############
44
+ class << self
45
+ include Enumerable
46
+
47
+ def [] id
48
+ if item = store[id]
49
+ Marshal.restore item
50
+ end
51
+ end
52
+ alias_method :find, :[]
53
+
54
+ def []= *args
55
+ id, instance = *args
56
+ if instance.class == self
57
+ instance.id = id
58
+ instance.save
59
+ elsif instance.respond_to?(:to_h)
60
+ self.new(id, instance).save
61
+ else
62
+ raise ArgumentError.new(<<-ERR)
63
+ You must provide an instance of #{self.name} or at least
64
+ something which responds to #to_h"
65
+ ERR
66
+ end
67
+ end
68
+ alias_method :create, :[]=
69
+
70
+ def has_key? key
71
+ store.has_key? key
72
+ end
73
+ alias_method :key?, :has_key?
74
+ alias_method :member?, :has_key?
75
+ alias_method :includes?, :has_key?
76
+
77
+ def each &block
78
+ store.values.map{ |i| Marshal.restore i }.each &block
79
+ end
80
+ alias_method :where, :select
81
+
82
+ def property prop, opts
83
+ @_properties ||= []
84
+ @_properties << prop
85
+ uniquify_properties
86
+ if prop.to_s.match(/\?$/)
87
+ define_method prop do
88
+ instance_variable_get "@#{self.class.instance_var_for prop}"
89
+ end
90
+ define_method prop.to_s.gsub(/\?$/, '=') do |v|
91
+ instance_variable_set "@#{self.class.instance_var_for prop}", v
92
+ end
93
+ else
94
+ attr_accessor prop
95
+ end
96
+ if default = opts[:default]
97
+ defaults[prop] = default
98
+ end
99
+ end
100
+
101
+ def properties *props
102
+ props.each do |prop|
103
+ property prop, {}
104
+ end
105
+ @_properties
106
+ end
107
+
108
+ def defaults
109
+ @_defaults ||= {}
110
+ end
111
+
112
+ def underscore_name
113
+ self.name.
114
+ gsub(/::/, '/').
115
+ gsub(/([^\/])([A-Z])/, '\1_\2').
116
+ downcase
117
+ end
118
+
119
+ def store= storage
120
+ @store = storage
121
+ end
122
+
123
+ def store
124
+ @store ||= {}
125
+ end
126
+
127
+ def instance_var_for property
128
+ if property.to_s.match(/\?$/)
129
+ "#{property.to_s.gsub(/\?$/,'')}__question__".to_sym
130
+ else
131
+ property
132
+ end
133
+ end
134
+
135
+ private
136
+
137
+ def uniquify_properties
138
+ @_properties = @_properties.uniq.compact
139
+ end
140
+
141
+ end
142
+ end
143
+ end
144
+
@@ -0,0 +1,3 @@
1
+ module Squares
2
+ VERSION = "0.2.0"
3
+ end
data/lib/squares.rb ADDED
@@ -0,0 +1,6 @@
1
+ require 'squares/version'
2
+ require 'squares/base'
3
+
4
+ module Squares
5
+ # Your code goes here...
6
+ end
@@ -0,0 +1,5 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
+
3
+ require 'pry'
4
+ require 'rspec-given'
5
+ require 'squares'
@@ -0,0 +1,164 @@
1
+ require 'spec_helper'
2
+ require 'squares/base'
3
+
4
+ module Marvel
5
+ class SuperHero < Squares::Base
6
+ properties :real_name, :special_powers
7
+ end
8
+ class Villain < Squares::Base
9
+ properties :vehicle, :lair
10
+ property :really_evil?, default: true
11
+ end
12
+ end
13
+
14
+ module Squares
15
+ describe Base do
16
+ Given(:storage) { {} }
17
+ Given(:test_class) { Marvel::SuperHero }
18
+ Given { test_class.store = storage }
19
+
20
+ Given(:id) { 'Captain America' }
21
+ Given(:name) { 'Steve Rogers' }
22
+ Given(:powers) { ['super strength', 'strategy', 'leadership'] }
23
+ When(:hero) { test_class.new id, real_name: name, special_powers: powers }
24
+
25
+ describe 'class' do
26
+
27
+ describe '.underscore_name' do
28
+ Then { test_class.underscore_name == 'marvel/super_hero' }
29
+ end
30
+
31
+ describe '.properties' do
32
+ Then { test_class.properties == [:real_name, :special_powers] }
33
+ end
34
+
35
+ describe '.use_storage' do
36
+ Given(:storage) { {attack: :fwoosh } }
37
+ When { test_class.store = storage }
38
+ Then { test_class.store == storage }
39
+ end
40
+
41
+ describe '.[]' do
42
+ Given { storage[id] = Marshal.dump hero }
43
+ When(:recovered_hero) { Marvel::SuperHero['Captain America'] }
44
+ Then { recovered_hero.class == Marvel::SuperHero }
45
+ Then { recovered_hero.id == 'Captain America' }
46
+ Then { recovered_hero.real_name == 'Steve Rogers' }
47
+ Then { recovered_hero.special_powers.include? 'leadership' }
48
+ end
49
+
50
+ describe '.[]= creates & stores a new instance' do
51
+ Given(:id) { 'Spiderman' }
52
+ Given(:name) { 'Peter Parker' }
53
+ Given(:powers) { [ 'wall crawling', 'web spinning', 'cracking wise' ] }
54
+
55
+ context 'whether created with an instance' do
56
+ Given(:instance) { test_class.new(id, real_name: name, special_powers: powers) }
57
+
58
+ When { test_class[id] = instance }
59
+ When(:spidey) { Marshal.restore storage.values.first }
60
+
61
+ Then { spidey.class == Marvel::SuperHero }
62
+ Then { spidey.id == 'Spiderman' }
63
+ Then { spidey.real_name == 'Peter Parker' }
64
+ Then { spidey.special_powers.include? 'cracking wise' }
65
+ end
66
+
67
+ context 'or creating using a hash' do
68
+ When { test_class[id] = { real_name: name, special_powers: powers } }
69
+
70
+ When(:spidey) { Marshal.restore storage.values.first }
71
+ Then { spidey.class == Marvel::SuperHero }
72
+ Then { spidey.id == 'Spiderman' }
73
+ Then { spidey.real_name == 'Peter Parker' }
74
+ Then { spidey.special_powers.include? 'cracking wise' }
75
+ end
76
+
77
+ context 'but creating with an invalid object' do
78
+ Then { expect{ test_class[id] = 12 } .to raise_error(ArgumentError) }
79
+ end
80
+ end
81
+
82
+ describe '.has_key?' do
83
+ Given { hero.save }
84
+ Then { expect(test_class).to have_key(id) }
85
+ Then { expect(test_class).to be_key(id) }
86
+ Then { expect(test_class).to be_member(id) }
87
+ Then { expect(test_class).to be_includes(id) }
88
+ end
89
+
90
+ describe 'more cool stuff' do
91
+ Given do
92
+ Marvel::SuperHero['Superman'] = { real_name: 'Clark Kent', special_powers: ['flying'] }
93
+ Marvel::SuperHero['Hulk'] = { real_name: 'Bruce Banner', special_powers: ['smash'] }
94
+ Marvel::SuperHero['Batman'] = { real_name: 'Bruce Wayne', special_powers: ['stuff'] }
95
+ end
96
+
97
+ describe '.where' do
98
+ When(:result) { Marvel::SuperHero.where { |h| h.real_name =~ /^Bruce/ } }
99
+ Then { result.count == 2 }
100
+ end
101
+
102
+ describe 'models are enumerable!' do
103
+ When(:result) { Marvel::SuperHero.map(&:special_powers).flatten }
104
+ Then { result == %w[ flying smash stuff ] }
105
+ end
106
+ end
107
+
108
+ end
109
+
110
+ describe 'instances' do
111
+ describe '#{{property}}' do
112
+ Then { hero.id == id }
113
+ Then { hero.real_name == name }
114
+ Then { hero.special_powers == powers }
115
+ end
116
+
117
+ describe '#save' do
118
+ When { hero.save }
119
+ When(:frozen_hero) { Marshal.restore storage.values.first }
120
+ Then { storage.keys.first == 'Captain America' }
121
+ Then { frozen_hero.real_name == 'Steve Rogers' }
122
+ Then { frozen_hero.class == Marvel::SuperHero }
123
+ end
124
+
125
+ describe '#==' do
126
+ Given(:hero1) { test_class.new id, real_name: name, special_powers: powers }
127
+ Given(:hero2) { test_class.new id, real_name: name, special_powers: powers }
128
+
129
+ context 'when they are equal' do
130
+ Then { hero1 == hero2 }
131
+ end
132
+
133
+ context 'when some property(ies) are not equal' do
134
+ Given { hero2.real_name = 'Steven Rogers' }
135
+ Then { hero1 != hero2 }
136
+ end
137
+ end
138
+
139
+ describe 'default values' do
140
+ Given do
141
+ class Marvel::SuperHero < Squares::Base
142
+ property :hair_color, default: 'black'
143
+ end
144
+ end
145
+ When(:hero) { test_class.new id, real_name: name }
146
+ Then { hero.special_powers == nil }
147
+ Then { hero.hair_color == 'black' }
148
+ Then { Marvel::SuperHero.defaults == { hair_color: 'black' } }
149
+ end
150
+
151
+ end
152
+
153
+ describe "models' properties don't bleed into each other" do
154
+ When(:villain) { Marvel::Villain.new 'Dr. Octopus', vehicle: 'jets', lair: 'abandonned sewer' }
155
+ Then { villain.class == Marvel::Villain }
156
+ Then { Marvel::Villain.properties == [:vehicle, :lair, :really_evil?] }
157
+ Then { villain.properties == [:vehicle, :lair, :really_evil?] }
158
+ Then { expect(villain).to_not respond_to(:hair_color) }
159
+ Then { expect(villain).to respond_to(:really_evil?) }
160
+ Then { expect(villain).to respond_to(:really_evil=) }
161
+ Then { expect(villain).to be_really_evil }
162
+ end
163
+ end
164
+ end
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+
3
+ describe Squares do
4
+ it 'has a version number' do
5
+ expect(Squares::VERSION).not_to be nil
6
+ end
7
+ end
data/squares.gemspec ADDED
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'squares/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "squares"
8
+ spec.version = Squares::VERSION
9
+ spec.authors = ["Joel Helbling"]
10
+ spec.email = ["joel@joelhelbling.com"]
11
+ spec.summary = %q{Lightweight ORM backed by any hash-like storage. [*]}
12
+ spec.description = %q{Redis, LevelDB or plain old hashes --any form of hash-like storage can be used to back Squares.}
13
+ spec.homepage = "http://github.com/joelhelbling/squares"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.7"
22
+ spec.add_development_dependency "rake", "~> 10.0"
23
+ spec.add_development_dependency "rspec"
24
+ spec.add_development_dependency "rspec-given"
25
+ spec.add_development_dependency "pry"
26
+ end
metadata ADDED
@@ -0,0 +1,132 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: squares
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - Joel Helbling
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-12-21 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.7'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec-given
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: pry
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: Redis, LevelDB or plain old hashes --any form of hash-like storage can
84
+ be used to back Squares.
85
+ email:
86
+ - joel@joelhelbling.com
87
+ executables: []
88
+ extensions: []
89
+ extra_rdoc_files: []
90
+ files:
91
+ - ".gitignore"
92
+ - ".rspec"
93
+ - ".travis.yml"
94
+ - Gemfile
95
+ - LICENSE.txt
96
+ - README.md
97
+ - Rakefile
98
+ - lib/squares.rb
99
+ - lib/squares/base.rb
100
+ - lib/squares/version.rb
101
+ - spec/spec_helper.rb
102
+ - spec/squares/base_spec.rb
103
+ - spec/squares_spec.rb
104
+ - squares.gemspec
105
+ homepage: http://github.com/joelhelbling/squares
106
+ licenses:
107
+ - MIT
108
+ metadata: {}
109
+ post_install_message:
110
+ rdoc_options: []
111
+ require_paths:
112
+ - lib
113
+ required_ruby_version: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ required_rubygems_version: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - ">="
121
+ - !ruby/object:Gem::Version
122
+ version: '0'
123
+ requirements: []
124
+ rubyforge_project:
125
+ rubygems_version: 2.4.3
126
+ signing_key:
127
+ specification_version: 4
128
+ summary: Lightweight ORM backed by any hash-like storage. [*]
129
+ test_files:
130
+ - spec/spec_helper.rb
131
+ - spec/squares/base_spec.rb
132
+ - spec/squares_spec.rb