medea 0.6.6 → 0.6.7
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 +1 -1
- data/lib/medea.rb +1 -0
- data/lib/medea/jason_base.rb +3 -0
- data/lib/medea/jason_blob.rb +6 -2
- data/lib/medea/jasondb.rb +6 -2
- data/lib/medea/jasonlistproperty.rb +3 -2
- data/lib/medea/jasonobject.rb +71 -11
- data/lib/medea/meta_properties.rb +41 -10
- data/lib/medea/version.rb +1 -1
- data/medea.gemspec +2 -0
- data/spec/jason_object_spec.rb +45 -0
- data/spec/spec_helper.rb +13 -5
- metadata +17 -22
data/Gemfile
CHANGED
data/lib/medea.rb
CHANGED
data/lib/medea/jason_base.rb
CHANGED
@@ -124,6 +124,9 @@ module Medea
|
|
124
124
|
@__jason_data = JSON.parse response
|
125
125
|
@__jason_etag = response.headers[:etag]
|
126
126
|
@__jason_timestamp = response.headers[:timestamp]
|
127
|
+
if response.headers[:http_x_public]
|
128
|
+
@public = response.headers[:http_x_public].split(",")
|
129
|
+
end
|
127
130
|
@__jason_state = :stale
|
128
131
|
end
|
129
132
|
|
data/lib/medea/jason_blob.rb
CHANGED
data/lib/medea/jasondb.rb
CHANGED
@@ -19,8 +19,12 @@ module JasonDB
|
|
19
19
|
host = "rest.jasondb.com"
|
20
20
|
end
|
21
21
|
protocol = "http"
|
22
|
-
|
23
|
-
|
22
|
+
if mode == :secure
|
23
|
+
protocol << "s"
|
24
|
+
"#{protocol}://#{user}:#{password}@#{host}/#{topic}/"
|
25
|
+
else #mode == :public
|
26
|
+
"#{protocol}://#{host}/#{topic}/"
|
27
|
+
end
|
24
28
|
end
|
25
29
|
|
26
30
|
end
|
@@ -23,9 +23,10 @@ module Medea
|
|
23
23
|
|
24
24
|
def method_missing name, *args, &block
|
25
25
|
#is this a list property on the base class?
|
26
|
-
|
26
|
+
lists = @type.class_variable_defined?(:@@opts) ? (@type.class_variable_get :@@opts)[:lists] : nil
|
27
|
+
if lists && lists.has_key?(name)
|
27
28
|
#if so, we'll just return a new ListProperty with my query as the parent
|
28
|
-
new_list_class, new_list_type =
|
29
|
+
new_list_class, new_list_type = lists[name]
|
29
30
|
base_query = self.clone
|
30
31
|
base_query.result_format = :keylist
|
31
32
|
JasonListProperty.new base_query, name.to_sym, new_list_class, new_list_type
|
data/lib/medea/jasonobject.rb
CHANGED
@@ -7,6 +7,9 @@ module Medea
|
|
7
7
|
|
8
8
|
class JasonObject < JasonBase
|
9
9
|
|
10
|
+
#these verbs are able to be made public
|
11
|
+
HTTP_VERBS = [:GET, :POST, :PUT, :DELETE]
|
12
|
+
|
10
13
|
include Medea::ActiveModelMethods
|
11
14
|
if defined? ActiveModel
|
12
15
|
extend ActiveModel::Naming
|
@@ -18,8 +21,7 @@ module Medea
|
|
18
21
|
|
19
22
|
#Here we're going to put the "query" interface
|
20
23
|
|
21
|
-
#create a JasonDeferredQuery
|
22
|
-
#if mode is set to :eager, we create the JasonDeferredQuery, invoke it's execution and then return it
|
24
|
+
#create a JasonDeferredQuery for all records of this class & with some optional conditions
|
23
25
|
def JasonObject.all(opts=nil)
|
24
26
|
q = JasonDeferredQuery.new :class => self, :filters => {:VERSION0 => nil, :FILTER => {:HTTP_X_CLASS => self, :HTTP_X_ACTION => :POST}}
|
25
27
|
if opts && opts[:limit]
|
@@ -112,12 +114,17 @@ module Medea
|
|
112
114
|
|
113
115
|
def initialize initialiser = nil, mode = :eager
|
114
116
|
@attachments = {}
|
115
|
-
if
|
116
|
-
|
117
|
+
if opts[:attachments]
|
118
|
+
opts[:attachments].each do |k|
|
117
119
|
@attachments[k] = nil
|
118
120
|
end
|
119
121
|
end
|
120
122
|
|
123
|
+
@public = []
|
124
|
+
if opts[:public]
|
125
|
+
opts[:public].each {|i| @public << i}
|
126
|
+
end
|
127
|
+
|
121
128
|
if initialiser
|
122
129
|
if initialiser.is_a? Hash
|
123
130
|
@__jason_state = :new
|
@@ -175,11 +182,45 @@ module Medea
|
|
175
182
|
#no changes? no save!
|
176
183
|
return if @__jason_state == :stale or @__jason_state == :ghost
|
177
184
|
|
185
|
+
#validations
|
186
|
+
if self.class.owned
|
187
|
+
#the parent object needs to be defined!
|
188
|
+
raise "#{self.class.name} cannot be saved without setting a parent and list!" unless self.jason_parent && self.jason_parent_list
|
189
|
+
end
|
190
|
+
|
178
191
|
persist_changes :post
|
179
192
|
end
|
180
193
|
|
181
|
-
def
|
182
|
-
|
194
|
+
def add_public *args
|
195
|
+
args.reject! do |i|
|
196
|
+
not HTTP_VERBS.include? i
|
197
|
+
end
|
198
|
+
@public += args
|
199
|
+
@public.uniq!
|
200
|
+
end
|
201
|
+
|
202
|
+
def remove_public *args
|
203
|
+
args.reject! do |i|
|
204
|
+
not HTTP_VERBS.include? i
|
205
|
+
end
|
206
|
+
@public -= args
|
207
|
+
@public.uniq!
|
208
|
+
end
|
209
|
+
|
210
|
+
def set_public *args
|
211
|
+
args.reject! do |i|
|
212
|
+
not HTTP_VERBS.include? i
|
213
|
+
end
|
214
|
+
@public = args
|
215
|
+
@public.uniq!
|
216
|
+
end
|
217
|
+
|
218
|
+
def to_url mode=:secure
|
219
|
+
"#{JasonDB::db_auth_url mode}#{self.class.name}/#{self.jason_key}"
|
220
|
+
end
|
221
|
+
|
222
|
+
def to_public_url
|
223
|
+
to_url :public
|
183
224
|
end
|
184
225
|
|
185
226
|
def persist_changes method = :post
|
@@ -194,14 +235,24 @@ module Medea
|
|
194
235
|
}
|
195
236
|
post_headers["IF-MATCH"] = @__jason_etag if @__jason_state == :dirty
|
196
237
|
|
197
|
-
if self.class.owned
|
198
|
-
#the parent object needs to be defined!
|
199
|
-
raise "#{self.class.name} cannot be saved without setting a parent and list!" unless self.jason_parent && self.jason_parent_list
|
200
|
-
end
|
201
|
-
|
202
238
|
post_headers["X-PARENT"] = self.jason_parent.jason_key if self.jason_parent
|
203
239
|
post_headers["X-LIST"] = self.jason_parent_list if self.jason_parent_list
|
204
240
|
|
241
|
+
if opts[:located]
|
242
|
+
#set the location headers
|
243
|
+
if geohash?
|
244
|
+
post_headers["X-GEOHASH"] = geohash
|
245
|
+
end
|
246
|
+
if latitude? && longitude?
|
247
|
+
post_headers["X-LATITUDE"] = latitude
|
248
|
+
post_headers["X-LONGITUDE"] = longitude
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
if @public.any?
|
253
|
+
post_headers["X-PUBLIC"] = @public.join(",")
|
254
|
+
end
|
255
|
+
|
205
256
|
url = to_url()
|
206
257
|
|
207
258
|
#puts "Saving to #{url}"
|
@@ -227,5 +278,14 @@ module Medea
|
|
227
278
|
end
|
228
279
|
|
229
280
|
#end object persistence
|
281
|
+
|
282
|
+
private
|
283
|
+
def opts
|
284
|
+
if self.class.class_variable_defined? :@@opts
|
285
|
+
self.class.class_variable_get :@@opts
|
286
|
+
else
|
287
|
+
{}
|
288
|
+
end
|
289
|
+
end
|
230
290
|
end
|
231
291
|
end
|
@@ -4,11 +4,18 @@ module JasonObjectMetaProperties
|
|
4
4
|
end
|
5
5
|
|
6
6
|
module MetaProperties
|
7
|
+
def _class_options &block
|
8
|
+
self.send(:class_variable_set, :@@opts, {}) unless self.send(:class_variable_defined?, :@@opts)
|
9
|
+
opts = self.send(:class_variable_get, :@@opts)
|
10
|
+
yield opts
|
11
|
+
self.send(:class_variable_set, :@@opts, opts)
|
12
|
+
end
|
13
|
+
|
7
14
|
def create_member_list list_name, list_class, list_type
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
15
|
+
_class_options do |o|
|
16
|
+
o[:lists] ||= {}
|
17
|
+
o[:lists][list_name] = [list_class, list_type]
|
18
|
+
end
|
12
19
|
|
13
20
|
define_method(list_name) do
|
14
21
|
#puts "Looking at the #{list_name.to_s} list, which is full of #{list_type.name}s"
|
@@ -29,16 +36,40 @@ module JasonObjectMetaProperties
|
|
29
36
|
end
|
30
37
|
|
31
38
|
def has_attachment attachment_name
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
39
|
+
_class_options do |o|
|
40
|
+
o[:attachments] ||= []
|
41
|
+
o[:attachments] << attachment_name
|
42
|
+
o[:attachments].uniq!
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def has_location
|
47
|
+
_class_options do |o|
|
48
|
+
o[:located] = true
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
#sets the default public/private status for objects in this class
|
53
|
+
def public *args
|
54
|
+
verbs = [:GET, :POST, :PUT, :DELETE]
|
55
|
+
args.reject! do |i|
|
56
|
+
not verbs.include? i
|
57
|
+
end
|
58
|
+
_class_options do |o|
|
59
|
+
o[:public] ||= []
|
60
|
+
o[:public] << args
|
61
|
+
o[:public].flatten!
|
62
|
+
o[:public].uniq!
|
63
|
+
end
|
37
64
|
end
|
38
65
|
|
39
66
|
def key_field field_name
|
40
67
|
#this field must be present to save, and it must be unique
|
41
|
-
|
68
|
+
_class_options do |o|
|
69
|
+
o[:key_fields] ||= []
|
70
|
+
o[:key_fields] << field_name
|
71
|
+
o[:key_fields].uniq!
|
72
|
+
end
|
42
73
|
end
|
43
74
|
end
|
44
75
|
end
|
data/lib/medea/version.rb
CHANGED
data/medea.gemspec
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
|
1
2
|
# -*- encoding: utf-8 -*-
|
2
3
|
$:.push File.expand_path("../lib", __FILE__)
|
3
4
|
require "medea/version"
|
@@ -20,6 +21,7 @@ Gem::Specification.new do |s|
|
|
20
21
|
s.add_dependency "json"
|
21
22
|
s.add_dependency "rest-client"
|
22
23
|
s.add_dependency "uuidtools"
|
24
|
+
s.add_dependency "pr_geohash"
|
23
25
|
|
24
26
|
s.add_development_dependency "rspec"
|
25
27
|
end
|
data/spec/jason_object_spec.rb
CHANGED
@@ -92,4 +92,49 @@ describe "JasonObject" do
|
|
92
92
|
user2.jason_timestamp.should_not be_nil
|
93
93
|
user2.jason_timestamp.should be > t
|
94
94
|
end
|
95
|
+
|
96
|
+
it "should post location information properly" do
|
97
|
+
@user.geohash = "r1r0rshvpuxg"
|
98
|
+
RestClient.should_receive(:post).with(anything(), anything(), hash_including("X-GEOHASH" => "r1r0rshvpuxg")).and_return(DummyResponse.new)
|
99
|
+
@user.save!
|
100
|
+
@user.latitude, @user.longitude = [-37.901949, 145.180206]
|
101
|
+
RestClient.should_receive(:post).with(anything(), anything(), hash_including("X-LATITUDE" => -37.901949,
|
102
|
+
"X-LONGITUDE" => 145.180206)).and_return(DummyResponse.new)
|
103
|
+
@user.save!
|
104
|
+
end
|
105
|
+
|
106
|
+
it "should load location information properly" do
|
107
|
+
@user.geohash = "r1r0rshvpuxg"
|
108
|
+
@user.latitude, @user.longitude = [-37.901949, 145.180206]
|
109
|
+
@user.save!
|
110
|
+
retrieved_user = User.get_by_key(@user.jason_key)
|
111
|
+
retrieved_user.geohash.should eq(@user.geohash)
|
112
|
+
retrieved_user.latitude.should eq(@user.latitude)
|
113
|
+
retrieved_user.longitude.should eq(@user.longitude)
|
114
|
+
end
|
115
|
+
|
116
|
+
it "should provide it's public (insecure) url" do
|
117
|
+
#should return url non-https, and with no user/password
|
118
|
+
(@user.to_url :public).should match(/http:\/\/rest.jasondb.com/)
|
119
|
+
@user.to_public_url.should eq(@user.to_url :public)
|
120
|
+
end
|
121
|
+
|
122
|
+
it "should post security information properly" do
|
123
|
+
@user.add_public :GET, :POST
|
124
|
+
RestClient.should_receive(:post).with(anything(), anything(), hash_including("X-PUBLIC" => "GET,POST")).and_return(DummyResponse.new)
|
125
|
+
@user.save!
|
126
|
+
end
|
127
|
+
|
128
|
+
it "should only post valid verbs" do
|
129
|
+
@user.add_public :GET, :FAKEVERB
|
130
|
+
RestClient.should_receive(:post).with(anything(), anything(), hash_including("X-PUBLIC" => "GET")).and_return(DummyResponse.new)
|
131
|
+
@user.save!
|
132
|
+
end
|
133
|
+
|
134
|
+
it "should load security information properly" do
|
135
|
+
@user.set_public :GET, :POST
|
136
|
+
@user.save!
|
137
|
+
retrieved_user = User.get_by_key @user.jason_key
|
138
|
+
(retrieved_user.send(:instance_variable_get, :@public)).should eq(["GET", "POST"])
|
139
|
+
end
|
95
140
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -7,13 +7,21 @@ class Message < Medea::JasonObject
|
|
7
7
|
end
|
8
8
|
|
9
9
|
class User < Medea::JasonObject
|
10
|
+
has_location
|
10
11
|
has_many :followees, User
|
11
12
|
owns_many :messages, Message
|
12
13
|
end
|
13
14
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
"https://michael:password@rest.jasondb.com/medea-test/"
|
15
|
+
class DummyResponse
|
16
|
+
def code
|
17
|
+
201
|
18
18
|
end
|
19
|
-
|
19
|
+
def headers
|
20
|
+
{:Etag => "sometag",
|
21
|
+
:timestamp => "12345678"}
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
ENV["jason_user"] = "michael"
|
26
|
+
ENV["jason_topic"] = "medea-test"
|
27
|
+
ENV["jason_password"] = "password"
|
metadata
CHANGED
@@ -1,12 +1,8 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: medea
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
prerelease:
|
5
|
-
|
6
|
-
- 0
|
7
|
-
- 6
|
8
|
-
- 6
|
9
|
-
version: 0.6.6
|
4
|
+
prerelease:
|
5
|
+
version: 0.6.7
|
10
6
|
platform: ruby
|
11
7
|
authors:
|
12
8
|
- Michael Jensen
|
@@ -14,7 +10,7 @@ autorequire:
|
|
14
10
|
bindir: bin
|
15
11
|
cert_chain: []
|
16
12
|
|
17
|
-
date: 2011-02-
|
13
|
+
date: 2011-02-07 00:00:00 +11:00
|
18
14
|
default_executable:
|
19
15
|
dependencies:
|
20
16
|
- !ruby/object:Gem::Dependency
|
@@ -25,8 +21,6 @@ dependencies:
|
|
25
21
|
requirements:
|
26
22
|
- - ">="
|
27
23
|
- !ruby/object:Gem::Version
|
28
|
-
segments:
|
29
|
-
- 0
|
30
24
|
version: "0"
|
31
25
|
type: :runtime
|
32
26
|
version_requirements: *id001
|
@@ -38,8 +32,6 @@ dependencies:
|
|
38
32
|
requirements:
|
39
33
|
- - ">="
|
40
34
|
- !ruby/object:Gem::Version
|
41
|
-
segments:
|
42
|
-
- 0
|
43
35
|
version: "0"
|
44
36
|
type: :runtime
|
45
37
|
version_requirements: *id002
|
@@ -51,24 +43,31 @@ dependencies:
|
|
51
43
|
requirements:
|
52
44
|
- - ">="
|
53
45
|
- !ruby/object:Gem::Version
|
54
|
-
segments:
|
55
|
-
- 0
|
56
46
|
version: "0"
|
57
47
|
type: :runtime
|
58
48
|
version_requirements: *id003
|
59
49
|
- !ruby/object:Gem::Dependency
|
60
|
-
name:
|
50
|
+
name: pr_geohash
|
61
51
|
prerelease: false
|
62
52
|
requirement: &id004 !ruby/object:Gem::Requirement
|
63
53
|
none: false
|
64
54
|
requirements:
|
65
55
|
- - ">="
|
66
56
|
- !ruby/object:Gem::Version
|
67
|
-
segments:
|
68
|
-
- 0
|
69
57
|
version: "0"
|
70
|
-
type: :
|
58
|
+
type: :runtime
|
71
59
|
version_requirements: *id004
|
60
|
+
- !ruby/object:Gem::Dependency
|
61
|
+
name: rspec
|
62
|
+
prerelease: false
|
63
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
64
|
+
none: false
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: "0"
|
69
|
+
type: :development
|
70
|
+
version_requirements: *id005
|
72
71
|
description: Simple wrapper for persisting objects to JasonDB
|
73
72
|
email:
|
74
73
|
- michaelj@jasondb.com
|
@@ -122,21 +121,17 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
122
121
|
requirements:
|
123
122
|
- - ">="
|
124
123
|
- !ruby/object:Gem::Version
|
125
|
-
segments:
|
126
|
-
- 0
|
127
124
|
version: "0"
|
128
125
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
129
126
|
none: false
|
130
127
|
requirements:
|
131
128
|
- - ">="
|
132
129
|
- !ruby/object:Gem::Version
|
133
|
-
segments:
|
134
|
-
- 0
|
135
130
|
version: "0"
|
136
131
|
requirements: []
|
137
132
|
|
138
133
|
rubyforge_project:
|
139
|
-
rubygems_version: 1.
|
134
|
+
rubygems_version: 1.5.0
|
140
135
|
signing_key:
|
141
136
|
specification_version: 3
|
142
137
|
summary: Simple wrapper for persisting objects to JasonDB
|