cushion 0.0.3 → 0.0.4

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.
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile CHANGED
@@ -1,4 +1,2 @@
1
1
  source 'http://rubygems.org'
2
-
3
2
  gemspec
4
-
@@ -0,0 +1,24 @@
1
+ # Cushion
2
+
3
+ A HashWithIndifferentAccess with a CouchDB persistence layer.
4
+
5
+ ## Synopsis
6
+
7
+ Using Cushion is as simple as this:
8
+
9
+ hash = Cushion.new('/db/document')
10
+ hash.load
11
+ hash[:foo] = 'bar'
12
+ hash.save
13
+
14
+ When the document's URI consists only of the database part (`/db`), the id will be a UUID, set by CouchDB on `.save`.
15
+
16
+ Cushion can also be inherited from, which will lead to the database name being taken from the inheriting classes name. Like this:
17
+
18
+ class MyCushion < Cushion; end
19
+ hash = MyCushion.new
20
+ hash.save
21
+
22
+ In this case a document URI doesn't have to be given explicitly (even though, it can be given). For the above example, the URI would be `/my_cushions/<UUID set by CouchDB>`.
23
+
24
+
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path('../lib', __FILE__)
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = 'cushion'
6
+ s.version = '0.0.4'
7
+ s.authors = ['Helge Rausch']
8
+ s.email = ['helge@rausch.io']
9
+ s.homepage = 'https://github.com/tsujigiri/cushion'
10
+ s.summary = %q{A Hash with CouchDB persistence}
11
+ s.description = %q{A Hash with indifferent access and CouchDB persistence layer}
12
+
13
+ s.files = `git ls-files`.split("\n")
14
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
15
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
16
+
17
+ s.add_development_dependency 'test-unit'
18
+ s.add_development_dependency 'shoulda'
19
+ s.add_development_dependency 'ruby-debug19'
20
+ s.add_runtime_dependency 'active_support'
21
+ s.require_paths = ['lib']
22
+ end
@@ -13,33 +13,39 @@ class Cushion < HashWithIndifferentAccess
13
13
  uri = args.shift
14
14
  end
15
15
  if uri.nil?
16
- if self.class.ancestors.include?(Cushion)
16
+ if self.class.ancestors[1..-1].include?(Cushion)
17
17
  uri = '/' << self.class.name.underscore.pluralize
18
18
  else
19
19
  raise "No database URI given"
20
20
  end
21
21
  end
22
- document_uri uri
22
+ document_location uri
23
23
  data = args.shift
24
24
  super(data, &block)
25
25
  end
26
26
 
27
- def document_uri uri = nil
28
- return @document_uri unless uri
29
- uri =~ /(http:\/\/)?(\w+)?:?([0-9]+)?\/(\w+)(\/(\w+))?/
27
+ def document_location uri = nil
28
+ return @document_location unless uri
29
+ uri =~ /(http:\/\/)?([^:\/\?]+)?(:([0-9]+))?\/(\w+)(\/(\w+))?/
30
30
 
31
- @document_uri = { host: $2 || 'localhost',
32
- port: $3 || 5984 }
31
+ self.class.server [ $2 || 'localhost', $4 ? $4.to_i : 5984 ]
32
+ @document_location = {}
33
+ @document_location[:database] = $5
34
+ @id = $7
35
+ @document_location[:uri] = "/#{@document_location[:database]}/#{@id}" if @id
36
+ end
33
37
 
34
- @document_uri[:database] = $4
35
- @id = $6
36
- @document_uri[:uri] = "/#{@document_uri[:database]}/#{@id}" if @id
38
+ def self.create_database uri
39
+ put(uri) unless get(uri)['db_name']
40
+ database_created true
37
41
  end
38
42
 
39
- def create_database
40
- database_uri = "/#{document_uri[:database]}"
41
- put(database_uri) unless get(database_uri)['db_name']
42
- @database_created = true
43
+ def self.database_created true_or_false = nil
44
+ if [ true, false ].include?(true_or_false)
45
+ @database_created = true_or_false
46
+ else
47
+ @database_created
48
+ end
43
49
  end
44
50
 
45
51
  def revision
@@ -51,46 +57,57 @@ class Cushion < HashWithIndifferentAccess
51
57
  end
52
58
 
53
59
  def load
54
- replace(get)
60
+ replace(self.class.get(document_location[:uri]))
55
61
  end
56
62
 
57
63
  def save
58
- create_database unless @database_created
64
+ unless self.class.database_created
65
+ self.class.create_database('/' << document_location[:database])
66
+ end
59
67
  if @id.present?
60
- response = put(document_uri[:uri], self)
68
+ copy = @revision ? self.merge(_rev: @revision) : self.dup
69
+ response = self.class.put(document_location[:uri], copy)
61
70
  @revision = response['rev']
62
71
  else
63
- response = post('/' << document_uri[:database], self)
72
+ response = self.class.post('/' << document_location[:database], self)
64
73
  @id = response['id']
65
74
  @revision = response['rev']
75
+ @document_location[:uri] = "/#{@document_location[:database]}/#{@id}"
66
76
  end
77
+ @revision
67
78
  end
68
79
 
69
- def get uri = document_uri[:uri]
70
- JSON.parse(request(Net::HTTP::Get.new(uri)).body)
71
- end
72
-
73
- def put uri = document_uri[:uri], data = nil
74
- req = Net::HTTP::Put.new(uri)
75
- req["content-type"] = "application/json"
76
- req.body = data.to_json if data.present?
77
- JSON.parse(request(req).body)
78
- end
79
-
80
- def post uri = document_uri[:uri], data = nil
81
- req = Net::HTTP::Post.new(uri)
82
- req["content-type"] = "application/json"
83
- req.body = data.to_json if data.present?
84
- JSON.parse(request(req).body)
85
- end
86
-
87
- def delete uri = document_uri[:uri]
88
- JSON.parse(request(Net::HTTP::Delete.new(uri)).body)
89
- end
90
-
91
- private
80
+ class << self
81
+ def server host_and_port = nil
82
+ host_and_port.present? ? @server = host_and_port : @server
83
+ end
92
84
 
93
- def request(req)
94
- Net::HTTP.start(document_uri[:host], document_uri[:port]) { |http| http.request(req) }
85
+ def get uri
86
+ JSON.parse(request(Net::HTTP::Get.new(uri)).body)
87
+ end
88
+
89
+ def put uri, data = nil
90
+ req = Net::HTTP::Put.new(uri)
91
+ req["content-type"] = "application/json"
92
+ req.body = data.to_json if data.present?
93
+ JSON.parse(request(req).body)
94
+ end
95
+
96
+ def post uri, data = nil
97
+ req = Net::HTTP::Post.new(uri)
98
+ req["content-type"] = "application/json"
99
+ req.body = data.to_json if data.present?
100
+ JSON.parse(request(req).body)
101
+ end
102
+
103
+ def delete uri
104
+ JSON.parse(request(Net::HTTP::Delete.new(uri)).body)
105
+ end
106
+
107
+ private
108
+
109
+ def request(req)
110
+ Net::HTTP.start(*server) { |http| http.request(req) }
111
+ end
95
112
  end
96
113
  end
@@ -1,6 +1,6 @@
1
1
  require 'rubygems'
2
2
  require 'bundler'
3
- Bundler.require(:default, :test)
3
+ Bundler.require(:default, :development)
4
4
  require_relative '../lib/cushion'
5
5
 
6
6
  class CushionTest < Test::Unit::TestCase
@@ -11,11 +11,25 @@ class CushionTest < Test::Unit::TestCase
11
11
  @doc = Cushion.new(@doc_uri, { foo: "bar", test: "data" })
12
12
  end
13
13
 
14
- should "create a document" do
15
- @doc.save
14
+ should "save a document with an explicit id" do
15
+ revision = @doc.save
16
16
  doc = Cushion.new(@doc_uri)
17
+ assert_equal nil, doc[:foo]
17
18
  doc.load
18
19
  assert_equal "bar", doc[:foo]
20
+ assert_equal 'test_doc', @doc.id
21
+ new_revision = revision.to_i + 1
22
+ assert_match /#{new_revision}-[0-9a-f]{32}/, @doc.save
23
+ end
24
+
25
+ should "save a document without an explicit id" do
26
+ doc = FooCushion.new(foo: "bar")
27
+ assert_equal({ database: "foo_cushions" }, doc.document_location)
28
+ assert revision = doc.save
29
+ assert_match /\A\/foo_cushions\/[0-9a-f]{32}\Z/, doc.document_location[:uri]
30
+ assert id = doc.id
31
+ new_revision = revision.to_i + 1
32
+ assert_match /#{new_revision}-[0-9a-f]{32}/, doc.save
19
33
  end
20
34
 
21
35
  should "convert to JSON like a hash" do
@@ -23,13 +37,25 @@ class CushionTest < Test::Unit::TestCase
23
37
  end
24
38
 
25
39
  should "find the important parts in the given uri" do
26
- @doc.document_uri "/foo"
27
- assert_equal "foo", @doc.document_uri[:database]
40
+ @doc.document_location "/foo"
41
+ assert_equal "foo", @doc.document_location[:database]
42
+ assert_equal [ 'localhost', 5984 ], @doc.class.server
43
+ @doc.document_location "http://example.com/foo"
44
+ assert_equal "foo", @doc.document_location[:database]
45
+ assert_equal [ 'example.com', 5984 ], @doc.class.server
46
+ @doc.document_location "http://example.com:1234/foo"
47
+ assert_equal "foo", @doc.document_location[:database]
48
+ assert_equal [ 'example.com', 1234 ], @doc.class.server
49
+ @doc.document_location "/foo/bar"
50
+ assert_equal "foo", @doc.document_location[:database]
51
+ assert_equal "/foo/bar", @doc.document_location[:uri]
52
+ assert_equal [ 'localhost', 5984 ], @doc.class.server
53
+ assert_equal 'bar', @doc.id
28
54
  end
29
55
 
30
56
  should "take the database name from the class name when inherited" do
31
57
  foo = FooCushion.new
32
- assert_equal "foo_cushions", foo.document_uri[:database]
58
+ assert_equal "foo_cushions", foo.document_location[:database]
33
59
  end
34
60
  end
35
61
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cushion
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-09-29 00:00:00.000000000Z
12
+ date: 2011-11-05 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: test-unit
16
- requirement: &20647580 !ruby/object:Gem::Requirement
16
+ requirement: &11099760 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *20647580
24
+ version_requirements: *11099760
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: shoulda
27
- requirement: &20647100 !ruby/object:Gem::Requirement
27
+ requirement: &11099020 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,21 @@ dependencies:
32
32
  version: '0'
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *20647100
35
+ version_requirements: *11099020
36
+ - !ruby/object:Gem::Dependency
37
+ name: ruby-debug19
38
+ requirement: &11098400 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *11098400
36
47
  - !ruby/object:Gem::Dependency
37
48
  name: active_support
38
- requirement: &20646620 !ruby/object:Gem::Requirement
49
+ requirement: &11097680 !ruby/object:Gem::Requirement
39
50
  none: false
40
51
  requirements:
41
52
  - - ! '>='
@@ -43,7 +54,7 @@ dependencies:
43
54
  version: '0'
44
55
  type: :runtime
45
56
  prerelease: false
46
- version_requirements: *20646620
57
+ version_requirements: *11097680
47
58
  description: A Hash with indifferent access and CouchDB persistence layer
48
59
  email:
49
60
  - helge@rausch.io
@@ -51,7 +62,11 @@ executables: []
51
62
  extensions: []
52
63
  extra_rdoc_files: []
53
64
  files:
65
+ - .gitignore
54
66
  - Gemfile
67
+ - README.md
68
+ - Rakefile
69
+ - cushion.gemspec
55
70
  - lib/cushion.rb
56
71
  - test/cushion_test.rb
57
72
  homepage: https://github.com/tsujigiri/cushion
@@ -74,7 +89,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
74
89
  version: '0'
75
90
  requirements: []
76
91
  rubyforge_project:
77
- rubygems_version: 1.8.6
92
+ rubygems_version: 1.8.10
78
93
  signing_key:
79
94
  specification_version: 3
80
95
  summary: A Hash with CouchDB persistence