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.
Files changed (55) hide show
  1. data/Gemfile +5 -0
  2. data/lib/splash.rb +22 -26
  3. data/lib/splash/acts_as_collection.rb +3 -2
  4. data/lib/splash/acts_as_scope.rb +97 -33
  5. data/lib/splash/acts_as_scope_root.rb +2 -1
  6. data/lib/splash/annotated.rb +2 -1
  7. data/lib/splash/application.rb +2 -1
  8. data/lib/splash/attribute.rb +39 -21
  9. data/lib/splash/attributed_struct.rb +2 -1
  10. data/lib/splash/callbacks.rb +37 -0
  11. data/lib/splash/collection.rb +14 -11
  12. data/lib/splash/connection.rb +2 -1
  13. data/lib/splash/constraint.rb +3 -5
  14. data/lib/splash/constraint/all.rb +2 -1
  15. data/lib/splash/constraint/any.rb +2 -1
  16. data/lib/splash/constraint/in.rb +2 -1
  17. data/lib/splash/constraint/not_nil.rb +2 -1
  18. data/lib/splash/created_at.rb +16 -0
  19. data/lib/splash/document.rb +43 -15
  20. data/lib/splash/embed.rb +29 -9
  21. data/lib/splash/has_attributes.rb +68 -37
  22. data/lib/splash/has_collection.rb +79 -0
  23. data/lib/splash/has_constraint.rb +2 -1
  24. data/lib/splash/map_reduce.rb +124 -0
  25. data/lib/splash/matcher.rb +160 -0
  26. data/lib/splash/namespace.rb +149 -15
  27. data/lib/splash/password.rb +2 -1
  28. data/lib/splash/persister.rb +22 -62
  29. data/lib/splash/query_interface.rb +28 -6
  30. data/lib/splash/saveable.rb +5 -104
  31. data/lib/splash/scope.rb +16 -3
  32. data/lib/splash/scope/map_reduce_interface.rb +33 -0
  33. data/lib/splash/scope/options.rb +16 -6
  34. data/lib/splash/updated_at.rb +15 -0
  35. data/lib/splash/validates.rb +3 -1
  36. data/lib/splash/validator.rb +2 -1
  37. data/lib/splash/writeback.rb +46 -0
  38. data/lib/standart_extensions/array.rb +9 -0
  39. data/lib/standart_extensions/bson.rb +122 -0
  40. data/lib/standart_extensions/class.rb +11 -0
  41. data/lib/{splash/standart_extensions → standart_extensions}/hash.rb +6 -1
  42. data/lib/{splash/standart_extensions → standart_extensions}/module.rb +17 -3
  43. data/lib/standart_extensions/object.rb +13 -0
  44. data/splash.gemspec +17 -0
  45. metadata +20 -16
  46. data/lib/splash/scope_delegator.rb +0 -14
  47. data/lib/splash/scope_options.rb +0 -31
  48. data/lib/splash/standart_extensions/object.rb +0 -11
  49. data/lib/splash/standart_extensions/string.rb +0 -5
  50. data/spec/helper.rb +0 -15
  51. data/spec/lib/annotated_spec.rb +0 -87
  52. data/spec/lib/collection_spec.rb +0 -64
  53. data/spec/lib/has_attributes_spec.rb +0 -43
  54. data/spec/lib/has_constraints_spec.rb +0 -53
  55. data/spec/lib/inheritance_spec.rb +0 -69
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source 'http://rubygems.org/'
2
+
3
+ gem 'bson_ext'
4
+
5
+ gemspec
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
- end
33
- Dir[Splash::DIR+"/splash/standart_extensions/*.rb"].each do |path|
34
- require path
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 === collection_class
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
@@ -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
- self.clone.scope_cursor.each do |o|
30
- yield Saveable.load(o,self)
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.clone.limit(1).next_document
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
- end
95
-
96
- def scoped_methods(*modules,&block)
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!(scope_options.selector,scope_options.options)
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!(selector,options)
114
- selector["Type"]=self.scope_root.to_s
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
@@ -1,3 +1,4 @@
1
+ # -*- encoding : utf-8 -*-
1
2
  module Splash::ActsAsScopeRoot
2
3
  include Splash::ActsAsScope
3
4
 
@@ -7,4 +8,4 @@ module Splash::ActsAsScopeRoot
7
8
  def scope_root?
8
9
  true
9
10
  end
10
- end
11
+ end
@@ -1,3 +1,4 @@
1
+ # -*- encoding : utf-8 -*-
1
2
  module Splash::Annotated
2
3
 
3
4
  class << self
@@ -31,4 +32,4 @@ module Splash::Annotated
31
32
  end
32
33
 
33
34
  end
34
- end
35
+ end
@@ -1,3 +1,4 @@
1
+ # -*- encoding : utf-8 -*-
1
2
  module Splash
2
3
  module Application
3
4
  class << self
@@ -33,4 +34,4 @@ module Splash
33
34
  end
34
35
  end
35
36
  end
36
- end
37
+ end
@@ -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
- attr_accessor :persister, :type, :default
6
+ NIL_LAMBDA = lambda{ nil }
7
7
 
8
- def initialize(t=nil,&block)
9
- self.type=t if t
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 = Splash::HasAttributes.get_persister(t)
27
+ @persister = t.persister
15
28
  @type = t
16
29
  end
17
30
 
18
- def persisted_by(*args,&block)
19
- @persister = Splash::HasAttributes.get_persister(*args, &block)
31
+ def persisted_by(p)
32
+ @persister = p
20
33
  end
21
34
 
35
+ # persisting interface
22
36
  def read(value)
23
- return value unless @persister
24
- @persister.read(value)
37
+ @persister.from_saveable(value)
25
38
  end
26
39
 
27
40
  def write(value)
28
- return value unless @persister
29
- @persister.write(value)
41
+ @persister.to_saveable(value)
30
42
  end
31
43
 
32
- def persisted_class
33
- return Object unless @persister
34
- @persister.persisted_class
44
+ # type interface
45
+ def missing
46
+ self.default
35
47
  end
36
48
 
37
- def missing()
38
- if self.default
39
- self.default.clone
40
- else
41
- nil
42
- end
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
@@ -1,3 +1,4 @@
1
+ # -*- encoding : utf-8 -*-
1
2
  class Splash::AttributedStruct
2
3
 
3
4
  include Splash::HasAttributes
@@ -5,4 +6,4 @@ class Splash::AttributedStruct
5
6
  def initialize(attr={})
6
7
  self.attributes.load(attr)
7
8
  end
8
- end
9
+ 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
@@ -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 < Splash::Persister
21
+ class Persister
21
22
 
22
- def read(val)
23
+ attr_accessor :entry_persister
24
+
25
+ def from_saveable(val)
23
26
  return nil if val.nil?
24
- nu=persisted_class.new
27
+ nu=@base_class.new
25
28
  val.inject(nu){|memo,e|
26
- memo << @persister.read(e)
29
+ memo << @entry_persister.from_saveable(e)
27
30
  memo
28
31
  }
29
32
  end
30
33
 
31
- def write(val)
34
+ def to_saveable(val)
32
35
  return nil if val.nil?
33
36
  val.inject([]){|memo,e|
34
- memo << @persister.write(e)
37
+ memo << @entry_persister.to_saveable(e)
35
38
  memo
36
39
  }
37
40
  end
38
41
 
39
- def persist_class(col)
40
- @persister=Splash::HasAttributes.get_persister(col.collection_class)
41
- super
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