medea 0.6.6 → 0.6.7
Sign up to get free protection for your applications and to get access to all the features.
- 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
|