splash 0.0.1.alpha
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +19 -0
- data/lib/splash/acts_as_collection.rb +55 -0
- data/lib/splash/acts_as_scope.rb +118 -0
- data/lib/splash/acts_as_scope_root.rb +10 -0
- data/lib/splash/annotated.rb +34 -0
- data/lib/splash/application.rb +36 -0
- data/lib/splash/attribute.rb +45 -0
- data/lib/splash/attributed_struct.rb +8 -0
- data/lib/splash/collection.rb +52 -0
- data/lib/splash/connection.rb +26 -0
- data/lib/splash/constraint/all.rb +24 -0
- data/lib/splash/constraint/any.rb +13 -0
- data/lib/splash/constraint/in.rb +13 -0
- data/lib/splash/constraint/not_nil.rb +9 -0
- data/lib/splash/constraint.rb +62 -0
- data/lib/splash/document.rb +38 -0
- data/lib/splash/embed.rb +37 -0
- data/lib/splash/has_attributes.rb +146 -0
- data/lib/splash/has_constraint.rb +9 -0
- data/lib/splash/namespace.rb +67 -0
- data/lib/splash/password.rb +31 -0
- data/lib/splash/persister.rb +66 -0
- data/lib/splash/query_interface.rb +84 -0
- data/lib/splash/saveable.rb +141 -0
- data/lib/splash/scope/options.rb +58 -0
- data/lib/splash/scope.rb +46 -0
- data/lib/splash/scope_delegator.rb +14 -0
- data/lib/splash/scope_options.rb +31 -0
- data/lib/splash/standart_extensions/hash.rb +45 -0
- data/lib/splash/standart_extensions/module.rb +73 -0
- data/lib/splash/standart_extensions/object.rb +11 -0
- data/lib/splash/standart_extensions/string.rb +5 -0
- data/lib/splash/validates.rb +75 -0
- data/lib/splash/validator.rb +24 -0
- data/lib/splash.rb +35 -0
- data/spec/helper.rb +15 -0
- data/spec/lib/annotated_spec.rb +87 -0
- data/spec/lib/collection_spec.rb +64 -0
- data/spec/lib/has_attributes_spec.rb +43 -0
- data/spec/lib/has_constraints_spec.rb +53 -0
- data/spec/lib/inheritance_spec.rb +69 -0
- metadata +139 -0
data/Rakefile
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'rake/gempackagetask'
|
4
|
+
gem 'rspec'
|
5
|
+
require 'spec/version'
|
6
|
+
require 'spec/rake/spectask'
|
7
|
+
require 'spec/ruby'
|
8
|
+
|
9
|
+
task :default => [:spec]
|
10
|
+
|
11
|
+
spec = Gem::Specification.load "splash.gemspec"
|
12
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
13
|
+
pkg.need_zip = true
|
14
|
+
pkg.need_tar = true
|
15
|
+
end
|
16
|
+
|
17
|
+
Spec::Rake::SpecTask.new('spec') do |t|
|
18
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
19
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Splash::ActsAsCollection
|
2
|
+
|
3
|
+
include Enumerable
|
4
|
+
|
5
|
+
def self.of(klass)
|
6
|
+
m = Module.new
|
7
|
+
s = self
|
8
|
+
m.class_eval do
|
9
|
+
include(s)
|
10
|
+
end
|
11
|
+
m.collection_class = klass
|
12
|
+
return m
|
13
|
+
end
|
14
|
+
|
15
|
+
class << self
|
16
|
+
def included(base)
|
17
|
+
if base.kind_of? Class
|
18
|
+
base.extend(ClassMethods)
|
19
|
+
else
|
20
|
+
base.extend(SubModuleMethods)
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
module SubModuleMethods
|
27
|
+
attr_accessor :collection_class
|
28
|
+
|
29
|
+
def included(base)
|
30
|
+
base.extend(ClassMethods)
|
31
|
+
s = self
|
32
|
+
base.instance_eval do
|
33
|
+
@collection_class = s.collection_class
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
module ClassMethods
|
39
|
+
attr_reader :collection_class
|
40
|
+
end
|
41
|
+
|
42
|
+
def create(*args,&block)
|
43
|
+
object=self.class.collection_class.new(*args,&block)
|
44
|
+
self << object
|
45
|
+
return object
|
46
|
+
end
|
47
|
+
|
48
|
+
def accepts?(object)
|
49
|
+
return object === collection_class
|
50
|
+
end
|
51
|
+
|
52
|
+
def include?(object)
|
53
|
+
accepts?(object) && super
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
module Splash
|
2
|
+
module ActsAsScope
|
3
|
+
include QueryInterface
|
4
|
+
|
5
|
+
|
6
|
+
# the following methods have to be defined
|
7
|
+
# when including this Module:
|
8
|
+
# - collection
|
9
|
+
# - scope_root
|
10
|
+
|
11
|
+
|
12
|
+
def scope_options
|
13
|
+
@scope_options ||= Splash::Scope::Options.new
|
14
|
+
end
|
15
|
+
|
16
|
+
def query(options)
|
17
|
+
Scope.new(self,scope_options.merge(options))
|
18
|
+
end
|
19
|
+
|
20
|
+
def dup
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
def all
|
25
|
+
clone
|
26
|
+
end
|
27
|
+
|
28
|
+
def each(&block)
|
29
|
+
self.clone.scope_cursor.each do |o|
|
30
|
+
yield Saveable.load(o,self)
|
31
|
+
end
|
32
|
+
self
|
33
|
+
end
|
34
|
+
|
35
|
+
def to_a
|
36
|
+
result = []
|
37
|
+
each do |object|
|
38
|
+
result << object
|
39
|
+
end
|
40
|
+
return result
|
41
|
+
end
|
42
|
+
|
43
|
+
def has_next?
|
44
|
+
scope_cursor.has_next?
|
45
|
+
end
|
46
|
+
|
47
|
+
def next_document
|
48
|
+
nd = scope_cursor.next_document
|
49
|
+
return nil if nd.nil?
|
50
|
+
return Saveable.load(nd,self)
|
51
|
+
end
|
52
|
+
|
53
|
+
def first
|
54
|
+
self.clone.limit(1).next_document
|
55
|
+
end
|
56
|
+
|
57
|
+
def clone
|
58
|
+
return Scope.new(self.scope_root,scope_options.dup)
|
59
|
+
end
|
60
|
+
|
61
|
+
def next_raw_document
|
62
|
+
scope_cursor.next_document
|
63
|
+
end
|
64
|
+
|
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
|
+
def count
|
86
|
+
self.clone.scope_cursor.count
|
87
|
+
end
|
88
|
+
|
89
|
+
def scope_root?
|
90
|
+
false
|
91
|
+
end
|
92
|
+
|
93
|
+
def <<(object)
|
94
|
+
end
|
95
|
+
|
96
|
+
def scoped_methods(*modules,&block)
|
97
|
+
|
98
|
+
end
|
99
|
+
|
100
|
+
protected
|
101
|
+
def scope_cursor()
|
102
|
+
@scope_cursor ||= find!(scope_options.selector,scope_options.options)
|
103
|
+
end
|
104
|
+
|
105
|
+
def unset_scope_cursor()
|
106
|
+
@scope_cursor=nil
|
107
|
+
end
|
108
|
+
|
109
|
+
def query!(options)
|
110
|
+
@scope_options = scope_options.merge(options)
|
111
|
+
end
|
112
|
+
|
113
|
+
def find!(selector,options)
|
114
|
+
selector["Type"]=self.scope_root.to_s
|
115
|
+
self.scope_root.collection.find(selector,options)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Splash::Annotated
|
2
|
+
|
3
|
+
class << self
|
4
|
+
def included(base)
|
5
|
+
base.extend(ClassMethods)
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
|
10
|
+
module ClassMethods
|
11
|
+
|
12
|
+
def method_added(meth)
|
13
|
+
apply_annotations(meth)
|
14
|
+
super
|
15
|
+
end
|
16
|
+
|
17
|
+
def apply_annotations(meth)
|
18
|
+
return if @annotations.nil?
|
19
|
+
@annotations.each do |(fn,args,block)|
|
20
|
+
args.unshift(meth)
|
21
|
+
self.send(fn,*args,&block)
|
22
|
+
end
|
23
|
+
@annotations=[]
|
24
|
+
return nil
|
25
|
+
end
|
26
|
+
|
27
|
+
def included(base)
|
28
|
+
included_modules.each do |mod|
|
29
|
+
mod.included(base)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Splash
|
2
|
+
module Application
|
3
|
+
class << self
|
4
|
+
def respond(request)
|
5
|
+
|
6
|
+
|
7
|
+
|
8
|
+
end
|
9
|
+
|
10
|
+
|
11
|
+
def call(env)
|
12
|
+
t='<form action="" method="post">
|
13
|
+
<p>
|
14
|
+
<input id="openid_identifier" name="openid[identifier][id]" type="text" />
|
15
|
+
</p>
|
16
|
+
|
17
|
+
<p>
|
18
|
+
<input name="commit" type="submit" value="Sign in" />
|
19
|
+
</p>
|
20
|
+
</form>'
|
21
|
+
request=Rack::Request.new(env)
|
22
|
+
if resp = env["rack.openid.response"]
|
23
|
+
if resp.status == :missing
|
24
|
+
return [401, {"WWW-Authenticate" => "OpenID identifier=\"#{request["openid_identifier"]}\""}, []]
|
25
|
+
else
|
26
|
+
env["rack.session"]["user"]=resp.identity_url
|
27
|
+
return [200,{'Content-Type' => 'text/html'},'<html>Welcome!<pre>'+(env.to_yaml)+'</pre></html>']
|
28
|
+
end
|
29
|
+
elsif request["openid_identifier"]
|
30
|
+
return [401, {"WWW-Authenticate" => "OpenID identifier=\"#{request["openid_identifier"]}\""}, []]
|
31
|
+
end
|
32
|
+
return [200,{'Content-Type' => 'text/html'},'<html>'+t+'<pre>'+(request.to_yaml)+'</pre></html>']
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
class Splash::Attribute
|
2
|
+
|
3
|
+
include ::Humanized
|
4
|
+
include Splash::HasConstraint
|
5
|
+
|
6
|
+
attr_accessor :persister, :type, :default
|
7
|
+
|
8
|
+
def initialize(t=nil,&block)
|
9
|
+
self.type=t if t
|
10
|
+
instance_eval &block if block_given?
|
11
|
+
end
|
12
|
+
|
13
|
+
def type= t
|
14
|
+
@persister = Splash::HasAttributes.get_persister(t)
|
15
|
+
@type = t
|
16
|
+
end
|
17
|
+
|
18
|
+
def persisted_by(*args,&block)
|
19
|
+
@persister = Splash::HasAttributes.get_persister(*args, &block)
|
20
|
+
end
|
21
|
+
|
22
|
+
def read(value)
|
23
|
+
return value unless @persister
|
24
|
+
@persister.read(value)
|
25
|
+
end
|
26
|
+
|
27
|
+
def write(value)
|
28
|
+
return value unless @persister
|
29
|
+
@persister.write(value)
|
30
|
+
end
|
31
|
+
|
32
|
+
def persisted_class
|
33
|
+
return Object unless @persister
|
34
|
+
@persister.persisted_class
|
35
|
+
end
|
36
|
+
|
37
|
+
def missing()
|
38
|
+
if self.default
|
39
|
+
self.default.clone
|
40
|
+
else
|
41
|
+
nil
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
class Splash::Collection < Array
|
2
|
+
include Splash::ActsAsCollection
|
3
|
+
|
4
|
+
COLLECTION_CLASSES = {}
|
5
|
+
|
6
|
+
def self.of(klass)
|
7
|
+
|
8
|
+
return COLLECTION_CLASSES[klass] if COLLECTION_CLASSES.key? klass
|
9
|
+
|
10
|
+
c = Class.new(self)
|
11
|
+
c.instance_eval do
|
12
|
+
@collection_class = klass
|
13
|
+
end
|
14
|
+
|
15
|
+
COLLECTION_CLASSES[klass] = c
|
16
|
+
return c
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
class Persister < Splash::Persister
|
21
|
+
|
22
|
+
def read(val)
|
23
|
+
return nil if val.nil?
|
24
|
+
nu=persisted_class.new
|
25
|
+
val.inject(nu){|memo,e|
|
26
|
+
memo << @persister.read(e)
|
27
|
+
memo
|
28
|
+
}
|
29
|
+
end
|
30
|
+
|
31
|
+
def write(val)
|
32
|
+
return nil if val.nil?
|
33
|
+
val.inject([]){|memo,e|
|
34
|
+
memo << @persister.write(e)
|
35
|
+
memo
|
36
|
+
}
|
37
|
+
end
|
38
|
+
|
39
|
+
def persist_class(col)
|
40
|
+
@persister=Splash::HasAttributes.get_persister(col.collection_class)
|
41
|
+
super
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
class << self
|
47
|
+
def persister
|
48
|
+
return Splash::Collection::Persister
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
class Splash::Connection
|
2
|
+
def initialize(host,db)
|
3
|
+
@host=host
|
4
|
+
@db=db
|
5
|
+
end
|
6
|
+
|
7
|
+
def get(id)
|
8
|
+
Net::HTTP.start("localhost", 5984){|http|
|
9
|
+
http.get('/splash/'+id)
|
10
|
+
}.body.parse_json
|
11
|
+
end
|
12
|
+
|
13
|
+
def put(id,val)
|
14
|
+
id = id.to_s
|
15
|
+
req=Net::HTTP::Put.new('/splash/'+id)
|
16
|
+
req.set_content_type("application/json")
|
17
|
+
Net::HTTP.start("localhost", 5984){|http|
|
18
|
+
http.request(req,val.to_json)
|
19
|
+
}.body
|
20
|
+
end
|
21
|
+
|
22
|
+
def uuid
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
class Splash::Constraint::All < Set
|
2
|
+
|
3
|
+
include Splash::Constraint
|
4
|
+
include Splash::ActsAsCollection.of(Splash::Constraint)
|
5
|
+
|
6
|
+
def accept?(value)
|
7
|
+
self.all? do |constr|
|
8
|
+
constr.accept?(value)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def not_accepting(value)
|
13
|
+
result = Splash::Constraint::All.new
|
14
|
+
self.each do |constr|
|
15
|
+
result << constr unless constr.accept?(value)
|
16
|
+
end
|
17
|
+
return result
|
18
|
+
end
|
19
|
+
|
20
|
+
def initialize
|
21
|
+
super("all!")
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module Splash::Constraint
|
2
|
+
|
3
|
+
attr_reader :description
|
4
|
+
|
5
|
+
autoload :Any, File.join( File.dirname(__FILE__), 'constraint/any' )
|
6
|
+
autoload :All, File.join( File.dirname(__FILE__), 'constraint/all' )
|
7
|
+
autoload :NotNil, File.join( File.dirname(__FILE__), 'constraint/not_nil' )
|
8
|
+
autoload :In, File.join( File.dirname(__FILE__), 'constraint/in' )
|
9
|
+
|
10
|
+
class Simple
|
11
|
+
|
12
|
+
include Splash::Constraint
|
13
|
+
|
14
|
+
def initialize(descr,&block)
|
15
|
+
@description = descr
|
16
|
+
@block = block
|
17
|
+
end
|
18
|
+
|
19
|
+
def accept?(value)
|
20
|
+
return @block.call(value)
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.new(*args,&block)
|
26
|
+
if self == Splash::Constraint
|
27
|
+
return Simple.new(*args,&block)
|
28
|
+
end
|
29
|
+
super
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.and(*args)
|
33
|
+
if args.length == 0
|
34
|
+
return Splash::Constraint::All.new
|
35
|
+
elsif args.length == 1
|
36
|
+
return args.first
|
37
|
+
else
|
38
|
+
result = Splash::Constraint::All.new
|
39
|
+
args.each do |constr|
|
40
|
+
if constr.kind_of? Splash::Constraint::All
|
41
|
+
result += constr
|
42
|
+
else
|
43
|
+
result << constr
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
return result
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def not_accepting(value)
|
52
|
+
return self unless self.accept?(value)
|
53
|
+
end
|
54
|
+
|
55
|
+
def initialize(descr)
|
56
|
+
@description = descr
|
57
|
+
super()
|
58
|
+
end
|
59
|
+
|
60
|
+
alias_method :to_s, :description
|
61
|
+
|
62
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Splash::Document
|
2
|
+
|
3
|
+
include Splash::Saveable
|
4
|
+
include Splash::HasAttributes
|
5
|
+
include Splash::Validates
|
6
|
+
|
7
|
+
class << self
|
8
|
+
def included(base)
|
9
|
+
included_modules.each do |mod|
|
10
|
+
mod.included(base)
|
11
|
+
end
|
12
|
+
|
13
|
+
dd = self
|
14
|
+
|
15
|
+
base.instance_eval do
|
16
|
+
include Splash::ActsAsCollection.of(base)
|
17
|
+
extend Splash::ActsAsScopeRoot
|
18
|
+
|
19
|
+
def included(base)
|
20
|
+
Splash::Document.included(base)
|
21
|
+
super(base)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def persister
|
27
|
+
Splash::Saveable::MultiPersister
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def initialize(args={})
|
32
|
+
self.attributes.load(args)
|
33
|
+
end
|
34
|
+
|
35
|
+
def to_saveable
|
36
|
+
attributes.raw
|
37
|
+
end
|
38
|
+
end
|
data/lib/splash/embed.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
module Splash::Embed
|
2
|
+
|
3
|
+
include Splash::HasAttributes
|
4
|
+
include Splash::Validates
|
5
|
+
|
6
|
+
class << self
|
7
|
+
def included(base)
|
8
|
+
base.extend(ClassMethods)
|
9
|
+
included_modules.each do |mod|
|
10
|
+
mod.included(base)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def define(&block)
|
15
|
+
c=Class.new()
|
16
|
+
mod = self
|
17
|
+
c.instance_eval do
|
18
|
+
include mod
|
19
|
+
end
|
20
|
+
c.class_eval(&block)
|
21
|
+
c
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
module ClassMethods
|
26
|
+
def persister
|
27
|
+
Splash::Saveable::EmbedPersister
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def initialize(args={})
|
32
|
+
self.attributes.load(args)
|
33
|
+
end
|
34
|
+
def to_saveable
|
35
|
+
attributes.raw
|
36
|
+
end
|
37
|
+
end
|