splash 0.0.1.alpha
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/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
|