paulcarey-relaxdb 0.3.0 → 0.3.1

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/README.textile CHANGED
@@ -1,8 +1,11 @@
1
1
  h3. What's New?
2
2
 
3
- RelaxDB 0.3 released - compatible with CouchDB 0.9.
3
+ * 2009-04-19
4
+ ** Defaults to taf2-curb, falling back to Net/HTTP if it taf2-curb can't be loaded. Thanks to "Fred Cheung":http://www.spacevatican.org/2009/4/13/fun-with-ruby-http-clients.
5
+ ** For those interested in using RelaxDB with an ETag based cache, "look here":http://github.com/fcheung/relaxdb/commit/1d9acfd5f6b3c23da0d275252b6a6e064865440e
4
6
 
5
- Version 0.3 includes many breaking changes. Most notable are simplified view syntax changes and the requirement that a design doc be specified up front.
7
+ * 2009-03-31
8
+ ** RelaxDB 0.3 released - compatible with CouchDB 0.9.
6
9
 
7
10
  h2. Overview
8
11
 
@@ -102,17 +105,18 @@ puts ix.sender.name # prints sofa, a single CouchDB request made
102
105
 
103
106
  idup = i.dup
104
107
  i.save!
105
- idup.save # conflict printed
108
+ idup.save # conflict printed
106
109
 
107
110
  # Saving with and without validations
108
111
 
109
- i = Invite.new :sender => sofa, :name => "daily show"
110
- i.save! rescue :ok # save! throws an exception on validation failure or conflict
111
- i.save # returns false rather than throwing an exception
112
- puts i.errors.inspect # {:recipient=>"invalid:"}
112
+ i = Invite.new :sender => sofa, :event_name => "CouchCamp"
113
113
 
114
- i.validation_skip_list << :recipient # Any and all validations may be skipped
115
- i.save # succeeds
114
+ i.save! rescue :ok # save! throws an exception on validation failure or conflict
115
+ i.save # returns false rather than throwing an exception
116
+ puts i.errors.inspect # prints {:recipient=>"invalid:"}
117
+
118
+ i.validation_skip_list << :recipient # Any and all validations may be skipped
119
+ i.save # succeeds
116
120
 
117
121
  </code>
118
122
  </pre>
data/Rakefile CHANGED
@@ -4,7 +4,7 @@ require 'spec/rake/spectask'
4
4
 
5
5
  PLUGIN = "relaxdb"
6
6
  NAME = "relaxdb"
7
- GEM_VERSION = "0.3.0"
7
+ GEM_VERSION = "0.3.1"
8
8
  AUTHOR = "Paul Carey"
9
9
  EMAIL = "paul.p.carey@gmail.com"
10
10
  HOMEPAGE = "http://github.com/paulcarey/relaxdb/"
@@ -141,7 +141,7 @@ module RelaxDB
141
141
  # Only set instance variables on creation - object references are resolved on demand
142
142
 
143
143
  # If the variable name ends in _at, _on or _date try to convert it to a Time
144
- if [/_at$/, /_on$/, /_date$/].inject(nil) { |i, r| i ||= (key =~ r) }
144
+ if [/_at$/, /_on$/, /_date$/, /_time$/].inject(nil) { |i, r| i ||= (key =~ r) }
145
145
  val = Time.parse(val).utc rescue val
146
146
  end
147
147
 
@@ -210,7 +210,7 @@ module RelaxDB
210
210
  end
211
211
 
212
212
  def pre_save
213
- set_created_at if new_document?
213
+ set_timestamps
214
214
  return false unless validates?
215
215
  return false unless before_save
216
216
  true
@@ -300,11 +300,13 @@ module RelaxDB
300
300
  end
301
301
  alias_method :id, :to_param
302
302
 
303
- def set_created_at
304
- if methods.include? "created_at"
303
+ def set_timestamps
304
+ if new_document? && respond_to?(:created_at)
305
305
  # Don't override it if it's already been set
306
306
  @created_at = Time.now if @created_at.nil?
307
307
  end
308
+
309
+ @updated_at = Time.now if respond_to?(:updated_at)
308
310
  end
309
311
 
310
312
  def create_or_get_proxy(klass, relationship, opts=nil)
@@ -0,0 +1,61 @@
1
+ module RelaxDB
2
+
3
+ class Server
4
+
5
+ def initialize(host, port)
6
+ @host = host
7
+ @port = port
8
+ end
9
+
10
+ def delete(uri)
11
+ request(Net::HTTP::Delete.new(uri))
12
+ end
13
+
14
+ def get(uri)
15
+ request(Net::HTTP::Get.new(uri))
16
+ end
17
+
18
+ def put(uri, json)
19
+ req = Net::HTTP::Put.new(uri)
20
+ req["content-type"] = "application/json"
21
+ req.body = json
22
+ request(req)
23
+ end
24
+
25
+ def post(uri, json)
26
+ req = Net::HTTP::Post.new(uri)
27
+ req["content-type"] = "application/json"
28
+ req.body = json
29
+ request(req)
30
+ end
31
+
32
+ def request(req)
33
+ res = Net::HTTP.start(@host, @port) {|http|
34
+ http.request(req)
35
+ }
36
+ if (not res.kind_of?(Net::HTTPSuccess))
37
+ handle_error(req, res)
38
+ end
39
+ res
40
+ end
41
+
42
+ def to_s
43
+ "http://#{@host}:#{@port}/"
44
+ end
45
+
46
+ private
47
+
48
+ def handle_error(req, res)
49
+ msg = "#{res.code}:#{res.message}\nMETHOD:#{req.method}\nURI:#{req.path}\n#{res.body}"
50
+ begin
51
+ klass = RelaxDB.const_get("HTTP_#{res.code}")
52
+ e = klass.new(msg)
53
+ rescue
54
+ e = RuntimeError.new(msg)
55
+ end
56
+
57
+ raise e
58
+ end
59
+ end
60
+
61
+ end
@@ -3,64 +3,6 @@ module RelaxDB
3
3
  class HTTP_404 < StandardError; end
4
4
  class HTTP_409 < StandardError; end
5
5
  class HTTP_412 < StandardError; end
6
-
7
- class Server
8
-
9
- def initialize(host, port)
10
- @host = host
11
- @port = port
12
- end
13
-
14
- def delete(uri)
15
- request(Net::HTTP::Delete.new(uri))
16
- end
17
-
18
- def get(uri)
19
- request(Net::HTTP::Get.new(uri))
20
- end
21
-
22
- def put(uri, json)
23
- req = Net::HTTP::Put.new(uri)
24
- req["content-type"] = "application/json"
25
- req.body = json
26
- request(req)
27
- end
28
-
29
- def post(uri, json)
30
- req = Net::HTTP::Post.new(uri)
31
- req["content-type"] = "application/json"
32
- req.body = json
33
- request(req)
34
- end
35
-
36
- def request(req)
37
- res = Net::HTTP.start(@host, @port) {|http|
38
- http.request(req)
39
- }
40
- if (not res.kind_of?(Net::HTTPSuccess))
41
- handle_error(req, res)
42
- end
43
- res
44
- end
45
-
46
- def to_s
47
- "http://#{@host}:#{@port}/"
48
- end
49
-
50
- private
51
-
52
- def handle_error(req, res)
53
- msg = "#{res.code}:#{res.message}\nMETHOD:#{req.method}\nURI:#{req.path}\n#{res.body}"
54
- begin
55
- klass = RelaxDB.const_get("HTTP_#{res.code}")
56
- e = klass.new(msg)
57
- rescue
58
- e = RuntimeError.new(msg)
59
- end
60
-
61
- raise e
62
- end
63
- end
64
6
 
65
7
  class CouchDB
66
8
 
@@ -97,8 +39,9 @@ module RelaxDB
97
39
  def replicate_db(source, target)
98
40
  @logger.info("Replicating from #{source} to #{target}")
99
41
  create_db_if_non_existant target
100
- data = { "source" => source, "target" => target}
101
- @server.post("/_replicate", data.to_json)
42
+ # Manual JSON encoding to allow for dbs containing a '/'
43
+ data = %Q({"source":"#{source}","target":"#{target}"})
44
+ @server.post("/_replicate", data)
102
45
  end
103
46
 
104
47
  def delete(path=nil)
@@ -0,0 +1,62 @@
1
+ module RelaxDB
2
+
3
+ class Server
4
+ class Response
5
+ attr_reader :body
6
+ def initialize body
7
+ @body = body
8
+ end
9
+ end
10
+
11
+ def initialize(host, port)
12
+ @host, @port = host, port
13
+ end
14
+
15
+ def delete(uri)
16
+ request(uri, 'delete'){ |c| c.http_delete}
17
+ end
18
+
19
+ def get(uri)
20
+ request(uri, 'get'){ |c| c.http_get}
21
+ end
22
+
23
+ def put(uri, json)
24
+ request(uri, 'put') do |c|
25
+ c.headers['content-type'] = 'application/json'
26
+ c.http_put json
27
+ end
28
+ end
29
+
30
+ def post(uri, json)
31
+ request(uri, 'post') do |c|
32
+ c.headers['content-type'] = 'application/json'
33
+ c.http_post json
34
+ end
35
+ end
36
+
37
+ def request(uri, method)
38
+ c = Curl::Easy.new "http://#{@host}:#{@port}#{uri}"
39
+ yield c
40
+
41
+ if c.response_code < 200 || c.response_code >= 300
42
+ status_line = c.header_str.split('\r\n').first
43
+ msg = "#{c.response_code}:#{status_line}\nMETHOD:#{method}\nURI:#{uri}\n#{c.body_str}"
44
+ begin
45
+ klass = RelaxDB.const_get("HTTP_#{c.response_code}")
46
+ e = klass.new(msg)
47
+ rescue
48
+ e = RuntimeError.new(msg)
49
+ end
50
+
51
+ raise e
52
+ end
53
+ Response.new c.body_str
54
+ end
55
+
56
+ def to_s
57
+ "http://#{@host}:#{@port}/"
58
+ end
59
+
60
+ end
61
+
62
+ end
data/lib/relaxdb.rb CHANGED
@@ -15,6 +15,14 @@ $:.unshift(File.dirname(__FILE__)) unless
15
15
 
16
16
  require 'relaxdb/validators'
17
17
 
18
+ begin
19
+ gem 'taf2-curb'
20
+ require 'curb'
21
+ require 'relaxdb/taf2_curb_server'
22
+ rescue LoadError
23
+ require 'relaxdb/net_http_server'
24
+ end
25
+
18
26
  require 'relaxdb/all_delegator'
19
27
  require 'relaxdb/belongs_to_proxy'
20
28
  require 'relaxdb/design_doc'
data/readme.rb CHANGED
@@ -66,14 +66,15 @@ puts ix.sender.name # prints sofa, a single CouchDB request made
66
66
 
67
67
  idup = i.dup
68
68
  i.save!
69
- idup.save # conflict printed
69
+ idup.save # conflict printed
70
70
 
71
71
  # Saving with and without validations
72
72
 
73
- i = Invite.new :sender => sofa, :name => "daily show"
74
- i.save! rescue :ok # save! throws an exception on validation failure or conflict
75
- i.save # returns false rather than throwing an exception
76
- puts i.errors.inspect # {:recipient=>"invalid:"}
73
+ i = Invite.new :sender => sofa, :event_name => "CouchCamp"
77
74
 
78
- i.validation_skip_list << :recipient # Any and all validations may be skipped
79
- i.save # succeeds
75
+ i.save! rescue :ok # save! throws an exception on validation failure or conflict
76
+ i.save # returns false rather than throwing an exception
77
+ puts i.errors.inspect # prints {:recipient=>"invalid:"}
78
+
79
+ i.validation_skip_list << :recipient # Any and all validations may be skipped
80
+ i.save # succeeds
@@ -80,12 +80,32 @@ describe RelaxDB::Document do
80
80
  p.save
81
81
  end
82
82
 
83
- it "should set created_at when first saved" do
84
- now = Time.now
85
- created_at = Post.new.save.created_at
86
- now.should be_close(created_at, 1)
83
+ it "should set created_at on first save only" do
84
+ ts = Time.now
85
+ p = Post.new
86
+
87
+ created_at = p.save.created_at
88
+ created_at.should be_close(ts, 1)
89
+
90
+ roll_clock_forward(60) do
91
+ created_at = p.save.created_at
92
+ created_at.should be_close(ts, 1)
93
+ end
87
94
  end
88
95
 
96
+ it "should set updated_at on each save" do
97
+ ts = Time.now
98
+ p = Primitives.new
99
+
100
+ updated_at = p.save.updated_at
101
+ updated_at.should be_close(ts, 1)
102
+
103
+ roll_clock_forward(60) do
104
+ updated_at = p.save.updated_at
105
+ updated_at.should be_close(Time.at(ts.to_i + 60), 1)
106
+ end
107
+ end
108
+
89
109
  it "should set created_at when first saved unless supplied to the constructor" do
90
110
  back_then = Time.now - 1000
91
111
  p = Post.new(:created_at => back_then).save
@@ -185,7 +205,7 @@ describe RelaxDB::Document do
185
205
 
186
206
  it "should prevent the object from being resaved" do
187
207
  p = Atom.new.save.destroy!
188
- # Exepcted failure - see http://issues.apache.org/jira/browse/COUCHDB-292
208
+ # Exepcted failure - see http://issues.apache.org/jira/browse/COUCHDB-292
189
209
  lambda { p.save! }.should raise_error
190
210
  end
191
211
 
data/spec/spec_helper.rb CHANGED
@@ -42,3 +42,20 @@ def create_base_db
42
42
  require File.dirname(__FILE__) + '/spec_models.rb'
43
43
  puts "Created relaxdb_spec_base"
44
44
  end
45
+
46
+ def roll_clock_forward(distance)
47
+ Time.meta_class.instance_eval do
48
+ define_method(:future_now) do
49
+ standard_now + distance
50
+ end
51
+ alias_method :standard_now, :now
52
+ alias_method :now, :future_now
53
+ begin
54
+ yield
55
+ rescue => e
56
+ raise e
57
+ ensure
58
+ alias_method :now, :standard_now
59
+ end
60
+ end
61
+ end
data/spec/spec_models.rb CHANGED
@@ -18,6 +18,7 @@ class Primitives < RelaxDB::Document
18
18
  property :true_bool
19
19
  property :false_bool
20
20
  property :created_at
21
+ property :updated_at
21
22
  property :empty
22
23
 
23
24
  view_by :num
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: paulcarey-relaxdb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paul Carey
@@ -64,6 +64,7 @@ files:
64
64
  - lib/relaxdb/extlib.rb
65
65
  - lib/relaxdb/has_many_proxy.rb
66
66
  - lib/relaxdb/has_one_proxy.rb
67
+ - lib/relaxdb/net_http_server.rb
67
68
  - lib/relaxdb/paginate_params.rb
68
69
  - lib/relaxdb/paginator.rb
69
70
  - lib/relaxdb/query.rb
@@ -71,6 +72,7 @@ files:
71
72
  - lib/relaxdb/relaxdb.rb
72
73
  - lib/relaxdb/server.rb
73
74
  - lib/relaxdb/uuid_generator.rb
75
+ - lib/relaxdb/taf2_curb_server.rb
74
76
  - lib/relaxdb/validators.rb
75
77
  - lib/relaxdb/view_object.rb
76
78
  - lib/relaxdb/view_result.rb