ShyCouch 0.3.5 → 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/Gemfile.lock +1 -1
- data/README +18 -4
- data/Rakefile +2 -1
- data/ShyCouch.gemspec +4 -3
- data/VERSION +1 -1
- data/lib/ShyCouch.rb +29 -41
- data/lib/ShyCouch/data.rb +66 -24
- data/test/test_ShyCouch.rb +5 -2
- data/test/test_couch_document.rb +5 -5
- data/test/test_views.rb +51 -0
- metadata +18 -17
data/Gemfile.lock
CHANGED
data/README
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
= ShyCouch
|
2
2
|
|
3
|
-
ShyCouch is a Ruby library for CouchDB. It's a data persistence layer that uses native objects and
|
3
|
+
ShyCouch is a Ruby library for CouchDB. It's a data persistence layer that uses native objects and lets you write native Ruby blocks that'll be parsed into MapReduce JavaScript functions.
|
4
4
|
|
5
|
-
|
5
|
+
The structure is a bit of a mess, but essentially it provides:
|
6
6
|
|
7
|
-
|
7
|
+
- a database object
|
8
|
+
- a CouchDocument object, which is a glorified hash
|
9
|
+
- a Design object representing the Design document for an app in CouchDB
|
8
10
|
|
9
|
-
|
11
|
+
At the moment, all views have to be written manually. I'm currently evaluating the wisdom of building a query language to dynamically write views and cache them in Couch.
|
10
12
|
|
11
13
|
= Usage
|
12
14
|
|
15
|
+
require 'shycouch'
|
16
|
+
settings = {
|
17
|
+
"db"=> {
|
18
|
+
"host" => "ramponeau.local",
|
19
|
+
"port" => 5984,
|
20
|
+
"name" => "food",
|
21
|
+
"user" => "cerales",
|
22
|
+
"password" => "password"
|
23
|
+
},
|
24
|
+
}
|
25
|
+
db = ShyCouch::CouchDatabase()
|
26
|
+
|
13
27
|
== Models
|
14
28
|
|
15
29
|
You don't need to define entity relationships or anything. Your models can just look like this:
|
data/Rakefile
CHANGED
data/ShyCouch.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{ShyCouch}
|
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 = [%q{Shy Inc.}, %q{Daniel Bryan}, %q{Cerales}]
|
12
|
-
s.date = %q{2011-08-
|
12
|
+
s.date = %q{2011-08-28}
|
13
13
|
s.description = %q{Ruby API for CouchDB, designed to work with the Camping micro-framework.}
|
14
14
|
s.email = %q{danbryan@gmail.com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -37,7 +37,8 @@ Gem::Specification.new do |s|
|
|
37
37
|
"test/test_couchdb_api.rb",
|
38
38
|
"test/test_couchdb_factory.rb",
|
39
39
|
"test/test_design_documents.rb",
|
40
|
-
"test/test_fields.rb"
|
40
|
+
"test/test_fields.rb",
|
41
|
+
"test/test_views.rb"
|
41
42
|
]
|
42
43
|
s.homepage = %q{http://github.com/Cerales/ShyCouch}
|
43
44
|
s.licenses = [%q{MIT}]
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.4.0
|
data/lib/ShyCouch.rb
CHANGED
@@ -11,63 +11,37 @@ $:.unshift(File.dirname(__FILE__)) unless
|
|
11
11
|
require 'net/http'
|
12
12
|
require 'json'
|
13
13
|
require 'resolv'
|
14
|
-
require 'shyrubyjs'
|
14
|
+
# require 'shyrubyjs'
|
15
|
+
require '~/dev/gems/ShyRubyJS/lib/ShyRubyJS'
|
15
16
|
# require everything from the 'ShyCouch' subdirectory
|
16
17
|
Dir.new(File.dirname(__FILE__)+'/ShyCouch').each { |f| require 'shycouch/' + f.split('.')[0] unless f == '.' or f == '..' }
|
17
18
|
|
18
19
|
|
19
20
|
module ShyCouch
|
20
21
|
class << self
|
21
|
-
def goes(m)
|
22
|
-
Camping.goes m
|
23
|
-
c = %{
|
24
|
-
#{m.to_s}::Models::CouchDocument = ShyCouch::Data::CouchDocument
|
25
|
-
}
|
26
|
-
eval(c)
|
27
|
-
ShyCouch.create
|
28
|
-
end
|
29
22
|
|
30
|
-
def create(settings=nil)
|
23
|
+
def create(settings=nil) #TODO - change this
|
31
24
|
$couchdb = ShyCouch.getDB(settings)
|
32
25
|
end
|
33
26
|
|
34
27
|
def getDB(settings=nil)
|
35
|
-
settings = $
|
36
|
-
database =
|
37
|
-
puts database.connect unless database.connect["ok"]
|
28
|
+
settings = $couch_settings unless settings
|
29
|
+
database = CouchDatabase.new(settings)
|
30
|
+
puts database.connect unless database.connect["ok"] #TODO - hm
|
38
31
|
database.create unless database.on_server?
|
39
32
|
return database
|
40
33
|
end
|
41
34
|
|
42
35
|
end
|
43
36
|
attr_accessor :database
|
44
|
-
|
45
|
-
class Connection
|
46
|
-
# Test that the database is accessible and give back a CouchDBAPI object if so.
|
47
|
-
# Doesn't actually gets instantiated - is just here to allow nice ShyCouch::Connection.Create syntax
|
48
|
-
# def self.Create(settings=nil)
|
49
|
-
# settings = $settings unless settings
|
50
|
-
# database = CouchDBAPI.new(settings["db"]["host"], settings["db"]["port"], settings["db"]["name"], settings["db"]["user"], settings["db"]["password"])
|
51
|
-
# puts database.connect unless database.connect["ok"]
|
52
|
-
# database.create unless database.on_server?
|
53
|
-
# return database
|
54
|
-
# end
|
55
|
-
|
56
|
-
def push_generic_views
|
57
|
-
#TODO
|
58
|
-
end
|
59
|
-
end
|
60
37
|
|
61
|
-
class
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
38
|
+
class ShyCouchError < StandardError; end
|
39
|
+
|
40
|
+
class CouchDatabase
|
41
|
+
def initialize(settings)
|
42
|
+
# args = explode_settings(args) if args.size == 1
|
43
|
+
init(settings)
|
66
44
|
end
|
67
|
-
#
|
68
|
-
# def initialize(*settings)
|
69
|
-
# @host, @port, @name, @user, @password = settings["db"]["host"], settings["db"]["port"], settings["db"]["name"], settings["db"]["user"], settings["db"]["password"]
|
70
|
-
# end
|
71
45
|
|
72
46
|
attr_accessor :server, :name, :host, :port, :views
|
73
47
|
|
@@ -134,6 +108,14 @@ module ShyCouch
|
|
134
108
|
end
|
135
109
|
|
136
110
|
private
|
111
|
+
|
112
|
+
def init(settings)
|
113
|
+
db_settings = settings["db"]
|
114
|
+
@host, @port, @name, @user, @password = db_settings["host"],db_settings["port"], db_settings["name"],db_settings["user"], db_settings["password"]
|
115
|
+
@views = []
|
116
|
+
@server = CouchServerConnection.allocate
|
117
|
+
end
|
118
|
+
|
137
119
|
class CouchServerConnection
|
138
120
|
def initialize(args, options=nil)#host, port, user, password, options = nil)
|
139
121
|
@host = args["host"]
|
@@ -237,9 +219,13 @@ module ShyCouch
|
|
237
219
|
|
238
220
|
private
|
239
221
|
|
240
|
-
def
|
222
|
+
def handle_failure(req, res)
|
241
223
|
raise RuntimeError.new("#{res.code}:#{res.message}\nMETHOD:#{req.method}\nURI:#{req.path}\n#{res.body}")
|
242
224
|
end
|
225
|
+
|
226
|
+
def handle_error(e)
|
227
|
+
raise RuntimeError.new("#{e.inspect}\n Maybe be due to illegal rev or id change")
|
228
|
+
end
|
243
229
|
|
244
230
|
def request(req)
|
245
231
|
res = Net::HTTP.start(@host, @port) { |http|
|
@@ -247,11 +233,13 @@ module ShyCouch
|
|
247
233
|
http.request(req)
|
248
234
|
}
|
249
235
|
unless res.kind_of?(Net::HTTPSuccess)
|
250
|
-
|
236
|
+
handle_failure(req, res)
|
251
237
|
end
|
252
238
|
res
|
239
|
+
rescue Errno::ECONNRESET => e
|
240
|
+
handle_error(e)
|
253
241
|
end
|
254
242
|
end
|
255
|
-
|
243
|
+
|
256
244
|
end
|
257
245
|
end
|
data/lib/ShyCouch/data.rb
CHANGED
@@ -5,9 +5,9 @@ module ShyCouch
|
|
5
5
|
class CouchDocument < Hash
|
6
6
|
class << self
|
7
7
|
# allows instance.class.requirements to be called
|
8
|
-
attr_accessor :requirements
|
9
8
|
end
|
10
|
-
|
9
|
+
@@needs, @@suggests = [], []
|
10
|
+
|
11
11
|
def initialize(hash={})
|
12
12
|
# Assumes that the "kind" is the class name unless explicitly stated otherwise
|
13
13
|
# TODO - maybe just force it to be the class name no matter what tbh
|
@@ -17,27 +17,30 @@ module ShyCouch
|
|
17
17
|
# super(hash)
|
18
18
|
end
|
19
19
|
|
20
|
-
# def initialize(hash=nil, requirements)
|
21
|
-
# @requirements = requirements
|
22
|
-
# merge!(hash) if hash
|
23
|
-
# raise TypeError unless valid? #TODO - should raise a more specific and useful error
|
24
|
-
# end
|
25
|
-
|
26
20
|
def self.all
|
27
|
-
database = CouchDatabase.new($settings)
|
28
|
-
database.get()
|
29
21
|
end
|
30
|
-
|
31
|
-
def self.
|
32
|
-
|
22
|
+
|
23
|
+
def self.needs(*requirements)
|
24
|
+
requirements.map { |requirement| @@needs << requirement } unless requirements.empty?
|
25
|
+
return @@needs
|
33
26
|
end
|
34
|
-
|
35
|
-
def
|
36
|
-
|
37
|
-
|
38
|
-
self[key] = value
|
27
|
+
|
28
|
+
def self.suggests(*suggestions)
|
29
|
+
suggestions.map { |suggestion| @@suggests << suggestion } unless suggestions.empty?
|
30
|
+
return @@suggests
|
39
31
|
end
|
40
|
-
|
32
|
+
|
33
|
+
def needs;self.class.needs; end
|
34
|
+
def suggests; self.class.suggests; end
|
35
|
+
|
36
|
+
def needs?(requirement)
|
37
|
+
@@needs.include?(requirement) ? true : false
|
38
|
+
end
|
39
|
+
|
40
|
+
def suggests?(requirement)
|
41
|
+
@@suggests.include?(requirement) ? true : false
|
42
|
+
end
|
43
|
+
|
41
44
|
def attr_keys
|
42
45
|
# returns the keys for all the attrs that aren't the id or rev
|
43
46
|
attr_keys = []
|
@@ -90,15 +93,54 @@ module ShyCouch
|
|
90
93
|
end
|
91
94
|
|
92
95
|
end
|
96
|
+
|
97
|
+
class View
|
98
|
+
attr_accessor :map, :reduce, :name
|
99
|
+
|
100
|
+
def initialize(view_name, &block)
|
101
|
+
@parser = ShyRubyJS::ShySexpParser.new
|
102
|
+
sexp_check = block.to_sexp
|
103
|
+
sexp = block.to_sexp(:strip_enclosure=>true)
|
104
|
+
|
105
|
+
# make sure the two blocks inside are calls to "map" and "reduce"
|
106
|
+
|
107
|
+
@name = view_name.to_s
|
108
|
+
if sexp[0] == :block
|
109
|
+
unless sexp_check[3][1][1][2] == :map and sexp_check[3][2][1][2] == :reduce
|
110
|
+
raise ShyCouchError, "view must be called with map block and optional reduce block"
|
111
|
+
end
|
112
|
+
[1,2].each { |num|
|
113
|
+
2.times { sexp[num].delete_at(1) }
|
114
|
+
}
|
115
|
+
@map = @parser.parse(sexp[1])[0]
|
116
|
+
@reduce = @parser.parse(sexp[2]) if sexp[2].length > 1
|
117
|
+
elsif sexp[0] == :iter
|
118
|
+
raise ShyCouchError, "view must be called with map block and optional reduce block" unless sexp[1][2] == :map
|
119
|
+
@map = @parser.parse(sexp[3])
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def as_hash
|
124
|
+
h = {}
|
125
|
+
h[@name] = {"map" => @map}
|
126
|
+
h.merge!({"reduce" => @reduce}) if @reduce
|
127
|
+
return h
|
128
|
+
end
|
129
|
+
end
|
93
130
|
|
94
131
|
class Design < CouchDocument
|
95
132
|
# this is used to manage design documents
|
96
133
|
# In practise, the Controllers should be a list of classes corresponding to design documents
|
97
|
-
|
98
|
-
def
|
99
|
-
|
100
|
-
|
101
|
-
|
134
|
+
|
135
|
+
def initialize(name)
|
136
|
+
merge! "_id" => "_design/#{name.to_s}"
|
137
|
+
@parser = ShyRubyJS::ShySexpParser.new
|
138
|
+
end
|
139
|
+
|
140
|
+
def self.setup
|
141
|
+
# setup_all_view
|
142
|
+
end
|
143
|
+
|
102
144
|
def push;end #must override push in order to set the ID
|
103
145
|
end
|
104
146
|
|
data/test/test_ShyCouch.rb
CHANGED
@@ -7,7 +7,8 @@ require_relative '../lib/ShyCouch'
|
|
7
7
|
# Settings for a database that is set up and working, with an admin user
|
8
8
|
$settings = {
|
9
9
|
"db"=> {
|
10
|
-
"host" => "
|
10
|
+
"host" => "ramponeau.local",
|
11
|
+
# "host" => "localhost",
|
11
12
|
"port" => 5984,
|
12
13
|
"name" => "test",
|
13
14
|
"user" => "cerales",
|
@@ -29,4 +30,6 @@ require_relative 'test_camping_integration'
|
|
29
30
|
|
30
31
|
require_relative 'test_couchdb_factory'
|
31
32
|
|
32
|
-
require_relative 'test_design_documents'
|
33
|
+
require_relative 'test_design_documents'
|
34
|
+
|
35
|
+
require_relative 'test_views'
|
data/test/test_couch_document.rb
CHANGED
@@ -38,7 +38,7 @@ class CouchDocumentTests# < Test::Unit::TestCase
|
|
38
38
|
def test_create_from_fixnum
|
39
39
|
# Ensure no doc creation with fixnum argument
|
40
40
|
fixnum = 1
|
41
|
-
|
41
|
+
assert_raise TypeError do
|
42
42
|
doc = ShyCouch::Data::CouchDocument.new(fixnum)
|
43
43
|
end
|
44
44
|
end
|
@@ -110,9 +110,9 @@ class CouchDocumentTests# < Test::Unit::TestCase
|
|
110
110
|
@existing_valid_documents.each { |doc|
|
111
111
|
# add some more attributes
|
112
112
|
assert(doc._rev)
|
113
|
-
doc
|
114
|
-
doc
|
115
|
-
doc
|
113
|
+
doc["owner"] = "the guvvmint"
|
114
|
+
doc["buttonCount"] = nil
|
115
|
+
doc["friends"] = nil
|
116
116
|
doc.buttonCount = 5
|
117
117
|
doc.friends = ["alan", "alex", "all me other mates"]
|
118
118
|
|
@@ -132,7 +132,7 @@ class CouchDocumentTests# < Test::Unit::TestCase
|
|
132
132
|
def test_illegal_change_to_rev
|
133
133
|
@existing_valid_documents.each { |doc|
|
134
134
|
doc._rev = "hurr"
|
135
|
-
|
135
|
+
assert_raise RuntimeError do
|
136
136
|
res = doc.push
|
137
137
|
end
|
138
138
|
}
|
data/test/test_views.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require_relative '../lib/ShyCouch.rb'
|
3
|
+
|
4
|
+
class CouchViewTests < Test::Unit::TestCase
|
5
|
+
JS_MAP_FUNCTION_HEADER = "function ( doc ) { \n "
|
6
|
+
JS_REDUCE_FUNCTION_HEADER = "function(key, values, rereduce)"
|
7
|
+
JS_FUNCTION_FOOTER = "}"
|
8
|
+
def setup
|
9
|
+
@couch_views = []
|
10
|
+
end
|
11
|
+
|
12
|
+
def view(view_name, &block)
|
13
|
+
@couch_views << ShyCouch::Data::View.new(view_name, &block)
|
14
|
+
end
|
15
|
+
def teardown; end
|
16
|
+
|
17
|
+
def test_define_map_view
|
18
|
+
view :five_star_butts do
|
19
|
+
map do
|
20
|
+
def function(doc)
|
21
|
+
emit(doc) if doc.kind == "butt" and doc.star_rating == 5
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
expected_js = JS_MAP_FUNCTION_HEADER + %{if( doc.kind == "butt" && doc.star_rating == 5 ) {\n emit(doc)\n} \n } + JS_FUNCTION_FOOTER
|
26
|
+
assert_equal(expected_js, @couch_views[0].map)
|
27
|
+
# puts @couch_views[0].map
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_define_map_and_reduce_view
|
31
|
+
view :beggar_count do
|
32
|
+
map do
|
33
|
+
def function(doc)
|
34
|
+
emit(doc) if doc.kind == "beggar"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
reduce do
|
38
|
+
def function(key, values, rereduce)
|
39
|
+
return sum(values)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
puts @couch_views[0].map
|
44
|
+
puts @couch_views[0].reduce
|
45
|
+
expected_map = JS_MAP_FUNCTION_HEADER + %{if( doc.kind == "beggar" ) {\n emit(doc)\n} \n } + JS_FUNCTION_FOOTER
|
46
|
+
expected_rejuce = JS_REDUCE_FUNCTION_HEADER
|
47
|
+
assert_equal(expected_map, @couch_views[0].map)
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ShyCouch
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -11,11 +11,11 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2011-08-
|
14
|
+
date: 2011-08-28 00:00:00.000000000Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: bundler
|
18
|
-
requirement: &
|
18
|
+
requirement: &70288155812040 !ruby/object:Gem::Requirement
|
19
19
|
none: false
|
20
20
|
requirements:
|
21
21
|
- - ~>
|
@@ -23,10 +23,10 @@ dependencies:
|
|
23
23
|
version: 1.0.0
|
24
24
|
type: :development
|
25
25
|
prerelease: false
|
26
|
-
version_requirements: *
|
26
|
+
version_requirements: *70288155812040
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: jeweler
|
29
|
-
requirement: &
|
29
|
+
requirement: &70288155810560 !ruby/object:Gem::Requirement
|
30
30
|
none: false
|
31
31
|
requirements:
|
32
32
|
- - ~>
|
@@ -34,10 +34,10 @@ dependencies:
|
|
34
34
|
version: 1.6.4
|
35
35
|
type: :development
|
36
36
|
prerelease: false
|
37
|
-
version_requirements: *
|
37
|
+
version_requirements: *70288155810560
|
38
38
|
- !ruby/object:Gem::Dependency
|
39
39
|
name: rcov
|
40
|
-
requirement: &
|
40
|
+
requirement: &70288155807920 !ruby/object:Gem::Requirement
|
41
41
|
none: false
|
42
42
|
requirements:
|
43
43
|
- - ! '>='
|
@@ -45,10 +45,10 @@ dependencies:
|
|
45
45
|
version: '0'
|
46
46
|
type: :development
|
47
47
|
prerelease: false
|
48
|
-
version_requirements: *
|
48
|
+
version_requirements: *70288155807920
|
49
49
|
- !ruby/object:Gem::Dependency
|
50
50
|
name: sourcify
|
51
|
-
requirement: &
|
51
|
+
requirement: &70288155806340 !ruby/object:Gem::Requirement
|
52
52
|
none: false
|
53
53
|
requirements:
|
54
54
|
- - ~>
|
@@ -56,10 +56,10 @@ dependencies:
|
|
56
56
|
version: 0.5.0
|
57
57
|
type: :development
|
58
58
|
prerelease: false
|
59
|
-
version_requirements: *
|
59
|
+
version_requirements: *70288155806340
|
60
60
|
- !ruby/object:Gem::Dependency
|
61
61
|
name: ShyRubyJS
|
62
|
-
requirement: &
|
62
|
+
requirement: &70288155792060 !ruby/object:Gem::Requirement
|
63
63
|
none: false
|
64
64
|
requirements:
|
65
65
|
- - ! '>='
|
@@ -67,10 +67,10 @@ dependencies:
|
|
67
67
|
version: '0'
|
68
68
|
type: :development
|
69
69
|
prerelease: false
|
70
|
-
version_requirements: *
|
70
|
+
version_requirements: *70288155792060
|
71
71
|
- !ruby/object:Gem::Dependency
|
72
72
|
name: ShyRubyJS
|
73
|
-
requirement: &
|
73
|
+
requirement: &70288155790660 !ruby/object:Gem::Requirement
|
74
74
|
none: false
|
75
75
|
requirements:
|
76
76
|
- - ! '>='
|
@@ -78,10 +78,10 @@ dependencies:
|
|
78
78
|
version: '0'
|
79
79
|
type: :runtime
|
80
80
|
prerelease: false
|
81
|
-
version_requirements: *
|
81
|
+
version_requirements: *70288155790660
|
82
82
|
- !ruby/object:Gem::Dependency
|
83
83
|
name: sourcify
|
84
|
-
requirement: &
|
84
|
+
requirement: &70288155789540 !ruby/object:Gem::Requirement
|
85
85
|
none: false
|
86
86
|
requirements:
|
87
87
|
- - ! '>='
|
@@ -89,7 +89,7 @@ dependencies:
|
|
89
89
|
version: '0'
|
90
90
|
type: :runtime
|
91
91
|
prerelease: false
|
92
|
-
version_requirements: *
|
92
|
+
version_requirements: *70288155789540
|
93
93
|
description: Ruby API for CouchDB, designed to work with the Camping micro-framework.
|
94
94
|
email: danbryan@gmail.com
|
95
95
|
executables: []
|
@@ -119,6 +119,7 @@ files:
|
|
119
119
|
- test/test_couchdb_factory.rb
|
120
120
|
- test/test_design_documents.rb
|
121
121
|
- test/test_fields.rb
|
122
|
+
- test/test_views.rb
|
122
123
|
homepage: http://github.com/Cerales/ShyCouch
|
123
124
|
licenses:
|
124
125
|
- MIT
|
@@ -134,7 +135,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
134
135
|
version: '0'
|
135
136
|
segments:
|
136
137
|
- 0
|
137
|
-
hash:
|
138
|
+
hash: 1563418179645536452
|
138
139
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
139
140
|
none: false
|
140
141
|
requirements:
|