splash 0.0.1.alpha → 0.0.1.beta
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +5 -0
- data/lib/splash.rb +22 -26
- data/lib/splash/acts_as_collection.rb +3 -2
- data/lib/splash/acts_as_scope.rb +97 -33
- data/lib/splash/acts_as_scope_root.rb +2 -1
- data/lib/splash/annotated.rb +2 -1
- data/lib/splash/application.rb +2 -1
- data/lib/splash/attribute.rb +39 -21
- data/lib/splash/attributed_struct.rb +2 -1
- data/lib/splash/callbacks.rb +37 -0
- data/lib/splash/collection.rb +14 -11
- data/lib/splash/connection.rb +2 -1
- data/lib/splash/constraint.rb +3 -5
- data/lib/splash/constraint/all.rb +2 -1
- data/lib/splash/constraint/any.rb +2 -1
- data/lib/splash/constraint/in.rb +2 -1
- data/lib/splash/constraint/not_nil.rb +2 -1
- data/lib/splash/created_at.rb +16 -0
- data/lib/splash/document.rb +43 -15
- data/lib/splash/embed.rb +29 -9
- data/lib/splash/has_attributes.rb +68 -37
- data/lib/splash/has_collection.rb +79 -0
- data/lib/splash/has_constraint.rb +2 -1
- data/lib/splash/map_reduce.rb +124 -0
- data/lib/splash/matcher.rb +160 -0
- data/lib/splash/namespace.rb +149 -15
- data/lib/splash/password.rb +2 -1
- data/lib/splash/persister.rb +22 -62
- data/lib/splash/query_interface.rb +28 -6
- data/lib/splash/saveable.rb +5 -104
- data/lib/splash/scope.rb +16 -3
- data/lib/splash/scope/map_reduce_interface.rb +33 -0
- data/lib/splash/scope/options.rb +16 -6
- data/lib/splash/updated_at.rb +15 -0
- data/lib/splash/validates.rb +3 -1
- data/lib/splash/validator.rb +2 -1
- data/lib/splash/writeback.rb +46 -0
- data/lib/standart_extensions/array.rb +9 -0
- data/lib/standart_extensions/bson.rb +122 -0
- data/lib/standart_extensions/class.rb +11 -0
- data/lib/{splash/standart_extensions → standart_extensions}/hash.rb +6 -1
- data/lib/{splash/standart_extensions → standart_extensions}/module.rb +17 -3
- data/lib/standart_extensions/object.rb +13 -0
- data/splash.gemspec +17 -0
- metadata +20 -16
- data/lib/splash/scope_delegator.rb +0 -14
- data/lib/splash/scope_options.rb +0 -31
- data/lib/splash/standart_extensions/object.rb +0 -11
- data/lib/splash/standart_extensions/string.rb +0 -5
- data/spec/helper.rb +0 -15
- data/spec/lib/annotated_spec.rb +0 -87
- data/spec/lib/collection_spec.rb +0 -64
- data/spec/lib/has_attributes_spec.rb +0 -43
- data/spec/lib/has_constraints_spec.rb +0 -53
- data/spec/lib/inheritance_spec.rb +0 -69
data/Gemfile
ADDED
data/lib/splash.rb
CHANGED
@@ -1,35 +1,31 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
1
2
|
if defined? Splash
|
2
3
|
raise "Splash included twice!"
|
3
4
|
end
|
4
5
|
|
6
|
+
Dir[File.join(File.dirname(__FILE__),"/standart_extensions/*.rb")].each do |path|
|
7
|
+
require path
|
8
|
+
end
|
9
|
+
|
10
|
+
class NotGivenClass
|
11
|
+
class << self
|
12
|
+
def instance
|
13
|
+
return (@instance ||= self.new)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
NotGiven = NotGivenClass.instance
|
18
|
+
class NotGivenClass
|
19
|
+
class << self
|
20
|
+
undef :new, :allocate
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
5
24
|
module Splash
|
6
25
|
|
7
|
-
DIR = File.dirname(__FILE__)
|
8
26
|
|
9
|
-
autoload :ActsAsCollection,DIR+"/splash/acts_as_collection"
|
10
|
-
autoload :ActsAsScope,DIR+"/splash/acts_as_scope"
|
11
|
-
autoload :ActsAsScopeRoot,DIR+"/splash/acts_as_scope_root"
|
12
|
-
autoload :Annotated,DIR+"/splash/annotated"
|
13
|
-
autoload :Scope,DIR+"/splash/scope"
|
14
|
-
autoload :Entity,DIR+"/splash/entity"
|
15
|
-
autoload :Validates,DIR+"/splash/validates"
|
16
|
-
autoload :Saveable,DIR+"/splash/saveable"
|
17
|
-
autoload :HasAttributes,DIR+"/splash/has_attributes"
|
18
|
-
autoload :NameSpace,DIR+"/splash/namespace"
|
19
|
-
autoload :Persister, DIR+"/splash/persister"
|
20
|
-
autoload :Lazy,DIR+"/splash/lazy"
|
21
|
-
autoload :QueryInterface,DIR+"/splash/query_interface"
|
22
|
-
autoload :Embed,DIR+"/splash/embed"
|
23
|
-
autoload :Document,DIR+"/splash/document"
|
24
|
-
autoload :Collection,DIR+"/splash/collection"
|
25
|
-
autoload :ScopeDelegator,DIR+"/splash/scope_delegator"
|
26
|
-
autoload :Attribute, DIR+"/splash/attribute"
|
27
|
-
autoload :HasConstraint, DIR+"/splash/has_constraint"
|
28
|
-
autoload :Constraint, DIR+"/splash/constraint"
|
29
|
-
autoload :AttributedStruct, DIR+"/splash/attributed_struct"
|
30
|
-
autoload :Password, DIR+"/splash/password"
|
31
27
|
|
32
|
-
|
33
|
-
|
34
|
-
|
28
|
+
|
29
|
+
autoload_all File.join(File.dirname(__FILE__),'splash')
|
30
|
+
|
35
31
|
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
1
2
|
module Splash::ActsAsCollection
|
2
3
|
|
3
4
|
include Enumerable
|
@@ -46,10 +47,10 @@ module Splash::ActsAsCollection
|
|
46
47
|
end
|
47
48
|
|
48
49
|
def accepts?(object)
|
49
|
-
return object
|
50
|
+
return object.kind_of? collection_class
|
50
51
|
end
|
51
52
|
|
52
53
|
def include?(object)
|
53
54
|
accepts?(object) && super
|
54
55
|
end
|
55
|
-
end
|
56
|
+
end
|
data/lib/splash/acts_as_scope.rb
CHANGED
@@ -1,6 +1,44 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
1
2
|
module Splash
|
2
3
|
module ActsAsScope
|
4
|
+
|
5
|
+
module ArraylikeAccess
|
6
|
+
def [](*args)
|
7
|
+
if args.size == 1
|
8
|
+
# range
|
9
|
+
if args.first.kind_of? Range
|
10
|
+
range = args.first
|
11
|
+
offset = range.first.to_int
|
12
|
+
last = range.last.to_int
|
13
|
+
if last == -1 and !range.exclude_end?
|
14
|
+
return query( :skip => offset )
|
15
|
+
end
|
16
|
+
if last < -1
|
17
|
+
raise "ranges with negative ends are not supported ( except -1 for no limit )"
|
18
|
+
end
|
19
|
+
limit = ( last - offset ) - ( range.exclude_end? ? 1 : 0 )
|
20
|
+
return query( :limit => limit, :skip => offset )
|
21
|
+
else
|
22
|
+
# id query
|
23
|
+
return query( :conditions => {'_id'=>args.first} ).first
|
24
|
+
end
|
25
|
+
elsif args.size == 2
|
26
|
+
offset = args[0].to_int
|
27
|
+
limit = args[1].to_int
|
28
|
+
return query( :limit => limit, :skip => offset )
|
29
|
+
end
|
30
|
+
raise "bag arguments #{args.inspect}, expected a range or a limit and an offset"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
module HashlikeAccess
|
35
|
+
def [](key)
|
36
|
+
return query( :conditions => {'_id'=>key} ).first.value
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
3
40
|
include QueryInterface
|
41
|
+
include Scope::MapReduceInterface
|
4
42
|
|
5
43
|
|
6
44
|
# the following methods have to be defined
|
@@ -26,8 +64,16 @@ module Splash
|
|
26
64
|
end
|
27
65
|
|
28
66
|
def each(&block)
|
29
|
-
|
30
|
-
|
67
|
+
a = block.arity
|
68
|
+
if a == 1
|
69
|
+
self.clone.scope_cursor.each do |o|
|
70
|
+
yield Saveable.load(o,self.scope_root)
|
71
|
+
end
|
72
|
+
elsif a == 2
|
73
|
+
self.clone.scope_cursor.each do |o|
|
74
|
+
l = Saveable.load(o,self.scope_root)
|
75
|
+
yield(l._id,l.value)
|
76
|
+
end
|
31
77
|
end
|
32
78
|
self
|
33
79
|
end
|
@@ -40,6 +86,14 @@ module Splash
|
|
40
86
|
return result
|
41
87
|
end
|
42
88
|
|
89
|
+
def to_h
|
90
|
+
result = {}
|
91
|
+
each do |key,value|
|
92
|
+
result[key]=value
|
93
|
+
end
|
94
|
+
return result
|
95
|
+
end
|
96
|
+
|
43
97
|
def has_next?
|
44
98
|
scope_cursor.has_next?
|
45
99
|
end
|
@@ -47,11 +101,11 @@ module Splash
|
|
47
101
|
def next_document
|
48
102
|
nd = scope_cursor.next_document
|
49
103
|
return nil if nd.nil?
|
50
|
-
return Saveable.load(nd,self)
|
104
|
+
return Saveable.load(nd,self.scope_root)
|
51
105
|
end
|
52
106
|
|
53
107
|
def first
|
54
|
-
self.
|
108
|
+
self.limit(1).next_document
|
55
109
|
end
|
56
110
|
|
57
111
|
def clone
|
@@ -62,26 +116,6 @@ module Splash
|
|
62
116
|
scope_cursor.next_document
|
63
117
|
end
|
64
118
|
|
65
|
-
def inspect
|
66
|
-
scope_options.inspect
|
67
|
-
end
|
68
|
-
|
69
|
-
=begin
|
70
|
-
def finish!
|
71
|
-
self.scope_cursor
|
72
|
-
self
|
73
|
-
end
|
74
|
-
|
75
|
-
def finished?
|
76
|
-
!@scope_cursor.nil?
|
77
|
-
end
|
78
|
-
|
79
|
-
def reset!
|
80
|
-
self.unset_scope_cursor
|
81
|
-
self
|
82
|
-
end
|
83
|
-
=end
|
84
|
-
|
85
119
|
def count
|
86
120
|
self.clone.scope_cursor.count
|
87
121
|
end
|
@@ -91,15 +125,33 @@ module Splash
|
|
91
125
|
end
|
92
126
|
|
93
127
|
def <<(object)
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
128
|
+
@scope_options.writeback(object)
|
129
|
+
if scope_root?
|
130
|
+
super(object)
|
131
|
+
else
|
132
|
+
scope_root.<<(object)
|
133
|
+
warn "object #{object} was writen to scope #{self} but won't be findable" unless complies_with?(object)
|
134
|
+
return object
|
135
|
+
end
|
98
136
|
end
|
99
137
|
|
138
|
+
def complies_with?(object)
|
139
|
+
@scope_options.selector.matches?(object)
|
140
|
+
end
|
141
|
+
|
142
|
+
def explain
|
143
|
+
self.scope_root.collection.find(*find_options).explain()
|
144
|
+
end
|
145
|
+
|
146
|
+
def update(*args)
|
147
|
+
options = find_options
|
148
|
+
self.scope_root.collection.update(options[0],*args)
|
149
|
+
end
|
150
|
+
|
100
151
|
protected
|
152
|
+
|
101
153
|
def scope_cursor()
|
102
|
-
@scope_cursor ||= find!
|
154
|
+
@scope_cursor ||= find!
|
103
155
|
end
|
104
156
|
|
105
157
|
def unset_scope_cursor()
|
@@ -110,9 +162,21 @@ module Splash
|
|
110
162
|
@scope_options = scope_options.merge(options)
|
111
163
|
end
|
112
164
|
|
113
|
-
def find!
|
114
|
-
|
115
|
-
self.scope_root.collection.find(selector,options)
|
165
|
+
def find!
|
166
|
+
self.scope_root.collection.find(*find_options)
|
116
167
|
end
|
168
|
+
|
169
|
+
def update!(*args)
|
170
|
+
|
171
|
+
end
|
172
|
+
|
173
|
+
def find_options
|
174
|
+
selector,options = scope_options.selector,scope_options.options
|
175
|
+
if self.scope_root.kind_of? Splash::Saveable
|
176
|
+
selector["Type"]=self.scope_root.to_s
|
177
|
+
end
|
178
|
+
return [selector,options]
|
179
|
+
end
|
180
|
+
|
117
181
|
end
|
118
|
-
end
|
182
|
+
end
|
data/lib/splash/annotated.rb
CHANGED
data/lib/splash/application.rb
CHANGED
data/lib/splash/attribute.rb
CHANGED
@@ -1,45 +1,63 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
1
2
|
class Splash::Attribute
|
2
3
|
|
3
|
-
include ::Humanized
|
4
4
|
include Splash::HasConstraint
|
5
5
|
|
6
|
-
|
6
|
+
NIL_LAMBDA = lambda{ nil }
|
7
7
|
|
8
|
-
|
9
|
-
|
8
|
+
attr_accessor :persister, :type
|
9
|
+
|
10
|
+
def default(fn=nil,*args,&block)
|
11
|
+
if block_given?
|
12
|
+
@default_block = block
|
13
|
+
elsif !fn.nil?
|
14
|
+
@default_block = lambda{ self.send(fn,*args) }
|
15
|
+
else
|
16
|
+
type.instance_eval &@default_block
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def initialize(t=Object,&block)
|
21
|
+
self.type = t
|
22
|
+
@default_block = NIL_LAMBDA
|
10
23
|
instance_eval &block if block_given?
|
11
24
|
end
|
12
25
|
|
13
26
|
def type= t
|
14
|
-
@persister =
|
27
|
+
@persister = t.persister
|
15
28
|
@type = t
|
16
29
|
end
|
17
30
|
|
18
|
-
def persisted_by(
|
19
|
-
@persister =
|
31
|
+
def persisted_by(p)
|
32
|
+
@persister = p
|
20
33
|
end
|
21
34
|
|
35
|
+
# persisting interface
|
22
36
|
def read(value)
|
23
|
-
|
24
|
-
@persister.read(value)
|
37
|
+
@persister.from_saveable(value)
|
25
38
|
end
|
26
39
|
|
27
40
|
def write(value)
|
28
|
-
|
29
|
-
@persister.write(value)
|
41
|
+
@persister.to_saveable(value)
|
30
42
|
end
|
31
43
|
|
32
|
-
|
33
|
-
|
34
|
-
|
44
|
+
# type interface
|
45
|
+
def missing
|
46
|
+
self.default
|
35
47
|
end
|
36
48
|
|
37
|
-
def
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
49
|
+
def writeable?
|
50
|
+
true
|
51
|
+
end
|
52
|
+
|
53
|
+
def initial_value
|
54
|
+
return type.initial_value if type && type.respond_to?(:initial_value)
|
55
|
+
::NotGiven
|
56
|
+
end
|
57
|
+
|
58
|
+
def before_write(value)
|
59
|
+
return type.before_write(value) if type && type.respond_to?(:before_write)
|
60
|
+
value
|
43
61
|
end
|
44
62
|
|
45
|
-
end
|
63
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
module Splash::Callbacks
|
3
|
+
|
4
|
+
protected
|
5
|
+
def run_callbacks(name,*args)
|
6
|
+
regex = Regexp.new("^#{Regexp.escape name.to_s}"_)
|
7
|
+
self.methods.each do |meth|
|
8
|
+
if meth.to_s ~= regex
|
9
|
+
self.send(meth,*args)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def with_callbacks(name,*args)
|
15
|
+
run_callbacks('before_' + name.to_s,*args)
|
16
|
+
result = yield
|
17
|
+
run_callbacks('after_' + name.to_s,*args)
|
18
|
+
return result
|
19
|
+
end
|
20
|
+
|
21
|
+
module ClassMethods
|
22
|
+
|
23
|
+
def with_callbacks(fn)
|
24
|
+
def ___callbacked()
|
25
|
+
|
26
|
+
end
|
27
|
+
alias_method(fn +'_without_callbacks',fn)
|
28
|
+
|
29
|
+
self.define_method(fn+'_with_callback') do
|
30
|
+
fn
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
define_annotation :with_callbacks
|
35
|
+
|
36
|
+
|
37
|
+
end
|
data/lib/splash/collection.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
1
2
|
class Splash::Collection < Array
|
2
3
|
include Splash::ActsAsCollection
|
3
4
|
|
@@ -17,36 +18,38 @@ class Splash::Collection < Array
|
|
17
18
|
end
|
18
19
|
|
19
20
|
|
20
|
-
class Persister
|
21
|
+
class Persister
|
21
22
|
|
22
|
-
|
23
|
+
attr_accessor :entry_persister
|
24
|
+
|
25
|
+
def from_saveable(val)
|
23
26
|
return nil if val.nil?
|
24
|
-
nu
|
27
|
+
nu=@base_class.new
|
25
28
|
val.inject(nu){|memo,e|
|
26
|
-
memo << @
|
29
|
+
memo << @entry_persister.from_saveable(e)
|
27
30
|
memo
|
28
31
|
}
|
29
32
|
end
|
30
33
|
|
31
|
-
def
|
34
|
+
def to_saveable(val)
|
32
35
|
return nil if val.nil?
|
33
36
|
val.inject([]){|memo,e|
|
34
|
-
memo << @
|
37
|
+
memo << @entry_persister.to_saveable(e)
|
35
38
|
memo
|
36
39
|
}
|
37
40
|
end
|
38
41
|
|
39
|
-
def
|
40
|
-
@
|
41
|
-
|
42
|
+
def initialize(klass, entry_persister)
|
43
|
+
@base_class = klass
|
44
|
+
@entry_persister = entry_persister
|
42
45
|
end
|
43
46
|
|
44
47
|
end
|
45
48
|
|
46
49
|
class << self
|
47
50
|
def persister
|
48
|
-
return Splash::Collection::Persister
|
51
|
+
return Splash::Collection::Persister.new(self, @collection_class.persister)
|
49
52
|
end
|
50
53
|
end
|
51
54
|
|
52
|
-
end
|
55
|
+
end
|