splash 0.0.1.alpha → 0.0.1.beta
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 +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
|