thingtank 0.0.1
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/.document +5 -0
- data/Gemfile +15 -0
- data/LICENSE.txt +20 -0
- data/README.md +329 -0
- data/Rakefile +45 -0
- data/VERSION +1 -0
- data/examples/bear_julius.rb +50 -0
- data/examples/first_marriage.rb +81 -0
- data/examples/immortal_julius.rb +25 -0
- data/examples/marriage_improvement.rb +120 -0
- data/examples/second_marriage.rb +78 -0
- data/lib/couchrest/extensions/view.rb +17 -0
- data/lib/thingtank/callbacks.rb +32 -0
- data/lib/thingtank/dependencies.rb +94 -0
- data/lib/thingtank/fakebase.rb +66 -0
- data/lib/thingtank/force_update.rb +24 -0
- data/lib/thingtank/instance_methods.rb +45 -0
- data/lib/thingtank/role.rb +110 -0
- data/lib/thingtank/role_handling.rb +198 -0
- data/lib/thingtank/shared_methods.rb +63 -0
- data/lib/thingtank/shortcuts.rb +36 -0
- data/lib/thingtank/thingtank.rb +21 -0
- data/lib/thingtank.rb +27 -0
- data/test/examples/test_bear_julius.rb +15 -0
- data/test/examples/test_first_marriage.rb +20 -0
- data/test/examples/test_immortal_julius.rb +16 -0
- data/test/examples/test_marriage_improvement.rb +22 -0
- data/test/examples/test_second_marriage.rb +18 -0
- data/test/helper.rb +118 -0
- data/test/test_fakebase.rb +389 -0
- data/test/test_thingtank.rb +282 -0
- data/test/test_views.rb +80 -0
- metadata +172 -0
@@ -0,0 +1,63 @@
|
|
1
|
+
class ThingTank
|
2
|
+
module SharedMethods
|
3
|
+
def self.included(klass)
|
4
|
+
klass.class_eval do
|
5
|
+
|
6
|
+
# only export the changed properties
|
7
|
+
def changed_to_role_hash(exclude_roles=false)
|
8
|
+
skips = skip_keys(exclude_roles)
|
9
|
+
hsh = {}
|
10
|
+
changes.each do |key,arr|
|
11
|
+
_old, _new = arr
|
12
|
+
unless skips.include? key
|
13
|
+
hsh[key] = _new
|
14
|
+
end
|
15
|
+
end
|
16
|
+
hsh
|
17
|
+
end
|
18
|
+
|
19
|
+
def skip_keys(exclude_roles=false)
|
20
|
+
arr = %w|_id _rev type update_me updated_at created_at|
|
21
|
+
arr << 'roles' if exclude_roles
|
22
|
+
arr
|
23
|
+
end
|
24
|
+
|
25
|
+
def to_role_hash(exclude_roles=false)
|
26
|
+
hsh = to_hash
|
27
|
+
skip_keys(exclude_roles).each{ |k| hsh.delete k }
|
28
|
+
hsh
|
29
|
+
end
|
30
|
+
|
31
|
+
def nth_role(klass, key, n, &code)
|
32
|
+
orig_role = to_role(klass, key)
|
33
|
+
list = [orig_role].flatten
|
34
|
+
role = case n
|
35
|
+
when :last
|
36
|
+
list.last
|
37
|
+
when :first
|
38
|
+
list.first
|
39
|
+
else
|
40
|
+
list[n]
|
41
|
+
end
|
42
|
+
if code
|
43
|
+
code.call(role)
|
44
|
+
role.flush_to_doc
|
45
|
+
end
|
46
|
+
if orig_role.is_a?(Array)
|
47
|
+
role._role_doc.dependencies.refresh_parent
|
48
|
+
end
|
49
|
+
role
|
50
|
+
end
|
51
|
+
|
52
|
+
def last_role(klass, key, &code)
|
53
|
+
nth_role(klass, key, :last, &code)
|
54
|
+
end
|
55
|
+
|
56
|
+
def first_role(klass, key, &code)
|
57
|
+
nth_role(klass, key, :first, &code)
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
class ThingTank
|
2
|
+
module Shortcuts
|
3
|
+
def self.included(klass)
|
4
|
+
klass.class_eval do
|
5
|
+
|
6
|
+
def >(klass_or_hash)
|
7
|
+
case klass_or_hash
|
8
|
+
when Array
|
9
|
+
last_role(klass_or_hash.first, klass_or_hash.last)
|
10
|
+
else
|
11
|
+
to_role(klass_or_hash)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def <(klass_or_hash)
|
16
|
+
case klass_or_hash
|
17
|
+
when Array
|
18
|
+
first_role(klass_or_hash.first, klass_or_hash.last)
|
19
|
+
else
|
20
|
+
to_role(klass_or_hash)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def << (arr)
|
25
|
+
klass, key, code= arr.flatten
|
26
|
+
if code
|
27
|
+
add_role(klass, key, &code)
|
28
|
+
else
|
29
|
+
add_role(klass, key)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'couchrest'
|
2
|
+
require 'couchrest_model'
|
3
|
+
|
4
|
+
class ThingTank < CouchRest::Model::Base
|
5
|
+
|
6
|
+
mass_assign_any_attribute true # should always allow to set non defined arbitrary properties
|
7
|
+
timestamps!
|
8
|
+
|
9
|
+
def role_view_by(klass, *keys)
|
10
|
+
opts = keys.pop if keys.last.is_a?(Hash)
|
11
|
+
opts ||= {}
|
12
|
+
opts[:guards] ||= []
|
13
|
+
# there is no "inArray" like function in couchdb, see http://stackoverflow.com/questions/3740464/i-have-to-write-every-function-i-need-for-couchdb
|
14
|
+
opts[:guards] << "((doc['roles'] !== undefined) && (function (item,arr) { for(p=0;p<arr.length;p++) if (item == arr[p]) return true; return false;})('#{klass.to_s}',doc['roles']))"
|
15
|
+
view_by(*keys, opts)
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
|
data/lib/thingtank.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require_relative File.join('thingtank', 'thingtank.rb')
|
2
|
+
require_relative File.join('couchrest', 'extensions', 'view.rb')
|
3
|
+
require_relative File.join('thingtank', 'dependencies.rb')
|
4
|
+
require_relative File.join('thingtank', 'callbacks.rb')
|
5
|
+
require_relative File.join('thingtank', 'force_update.rb')
|
6
|
+
require_relative File.join('thingtank', 'shared_methods.rb')
|
7
|
+
require_relative File.join('thingtank', 'instance_methods.rb')
|
8
|
+
require_relative File.join('thingtank', 'shortcuts.rb')
|
9
|
+
require_relative File.join('thingtank', 'role_handling.rb')
|
10
|
+
require_relative File.join('thingtank', 'role.rb')
|
11
|
+
require_relative File.join('thingtank', 'fakebase.rb')
|
12
|
+
|
13
|
+
# TODO:
|
14
|
+
# role validator
|
15
|
+
|
16
|
+
class ThingTank
|
17
|
+
|
18
|
+
include ThingTank::ForceUpdate
|
19
|
+
include ThingTank::SharedMethods
|
20
|
+
include ThingTank::InstanceMethods
|
21
|
+
include ThingTank::RoleHandling
|
22
|
+
include ThingTank::Shortcuts
|
23
|
+
include ThingTank::Callbacks
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'helper'
|
2
|
+
require 'first_marriage'
|
3
|
+
|
4
|
+
|
5
|
+
describe "with first marriage" do
|
6
|
+
|
7
|
+
before do
|
8
|
+
reset_test_db!
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should make the first marriage" do
|
12
|
+
test_first_marriage()
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should make the first marriage with shortcuts" do
|
16
|
+
test_first_marriage_shortcuts()
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require_relative File.join('..', 'helper')
|
2
|
+
require 'marriage_improvement'
|
3
|
+
|
4
|
+
describe "with improved marriage" do
|
5
|
+
|
6
|
+
before do
|
7
|
+
reset_test_db!
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should make the improved marriage" do
|
11
|
+
test_improved_marriage()
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should make the improved marriage with shortcuts" do
|
15
|
+
test_improved_marriage_shortcuts()
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should divorce properly" do
|
19
|
+
test_improved_marriage_divorce()
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'helper'
|
2
|
+
require 'second_marriage'
|
3
|
+
|
4
|
+
describe "second marriage" do
|
5
|
+
|
6
|
+
before do
|
7
|
+
reset_test_db!
|
8
|
+
end
|
9
|
+
|
10
|
+
it "make a second marriage" do
|
11
|
+
test_second_marriage
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should make a second marriage after conny died" do
|
15
|
+
test_second_marriage_after_conny_died()
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
data/test/helper.rb
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
begin
|
4
|
+
Bundler.setup(:default, :development)
|
5
|
+
rescue Bundler::BundlerError => e
|
6
|
+
$stderr.puts e.message
|
7
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
8
|
+
exit e.status_code
|
9
|
+
end
|
10
|
+
|
11
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
12
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
13
|
+
#$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib', 'thingtank'))
|
14
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'examples'))
|
15
|
+
require 'thingtank'
|
16
|
+
|
17
|
+
require 'minitest/autorun'
|
18
|
+
|
19
|
+
unless defined?(COUCHHOST)
|
20
|
+
COUCHHOST = ENV['COUCH_POTATO_TEST_DB']
|
21
|
+
db_config = CouchRest.parse(ENV['COUCH_POTATO_TEST_DB'])
|
22
|
+
db_config.delete(:doc)
|
23
|
+
protocol, host = db_config.delete(:host).split('://')
|
24
|
+
username, *host = host.split(':')
|
25
|
+
password, host = host.join(':').split('@')
|
26
|
+
host, port = host.split(':')
|
27
|
+
DB_CONFIG = db_config.merge :protocol => protocol, :host => host, :username => username, :port => port, :password => password
|
28
|
+
#p [COUCHHOST, DB_CONFIG]
|
29
|
+
|
30
|
+
DB = CouchRest.database COUCHHOST
|
31
|
+
end
|
32
|
+
|
33
|
+
CouchRest::Model::Base.configure do |config|
|
34
|
+
config.connection = DB_CONFIG
|
35
|
+
end
|
36
|
+
|
37
|
+
require 'ruby-debug'
|
38
|
+
|
39
|
+
class ThingTank
|
40
|
+
use_database "test_potato"
|
41
|
+
end
|
42
|
+
|
43
|
+
def reset_test_db!
|
44
|
+
ThingTank.database.recreate! rescue nil
|
45
|
+
ThingTank.database
|
46
|
+
end
|
47
|
+
|
48
|
+
def create(hsh={})
|
49
|
+
doc = ThingTank.create hsh
|
50
|
+
doc.save
|
51
|
+
doc.reload
|
52
|
+
doc
|
53
|
+
end
|
54
|
+
|
55
|
+
def new(hsh={})
|
56
|
+
ThingTank.new hsh
|
57
|
+
end
|
58
|
+
|
59
|
+
def load(id)
|
60
|
+
"ThingTank".constantize.new(ThingTank.database.get(id), :directly_set_attributes => true) # same as ThingTank.get id
|
61
|
+
end
|
62
|
+
|
63
|
+
class Check < ThingTank::Role
|
64
|
+
property :a
|
65
|
+
property :c
|
66
|
+
property :check_saved
|
67
|
+
property :check_updated
|
68
|
+
property :check_created
|
69
|
+
property :check_destroyed
|
70
|
+
property :shared
|
71
|
+
|
72
|
+
def ping
|
73
|
+
"pong"
|
74
|
+
end
|
75
|
+
|
76
|
+
def access_other_role
|
77
|
+
checker = database.to_role(Checker)
|
78
|
+
checker["checker1"] = "I was here"
|
79
|
+
end
|
80
|
+
|
81
|
+
def set_properties_we_don_t_have
|
82
|
+
self["ooops"] = "got it"
|
83
|
+
end
|
84
|
+
|
85
|
+
def set_properties_of_doc
|
86
|
+
_doc["ooops"] = "got it"
|
87
|
+
end
|
88
|
+
|
89
|
+
before_save do
|
90
|
+
self["check_saved"] = true
|
91
|
+
end
|
92
|
+
|
93
|
+
before_update do
|
94
|
+
self["check_updated"] = true
|
95
|
+
end
|
96
|
+
|
97
|
+
before_create do
|
98
|
+
self["check_created"] = true
|
99
|
+
end
|
100
|
+
|
101
|
+
before_destroy do
|
102
|
+
self["check_destroyed"] = true
|
103
|
+
#p :check_destroyed
|
104
|
+
true
|
105
|
+
end
|
106
|
+
|
107
|
+
validates_presence_of :a
|
108
|
+
end
|
109
|
+
|
110
|
+
class Checker < ThingTank::Role
|
111
|
+
property :shared
|
112
|
+
property :checker1
|
113
|
+
|
114
|
+
end
|
115
|
+
|
116
|
+
class Testmodel < CouchRest::Model::Base
|
117
|
+
end
|
118
|
+
|