subledger 0.7.7
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/.gitignore +9 -0
- data/LICENSE.txt +12 -0
- data/README.md +136 -0
- data/Rakefile +5 -0
- data/bin/subledger +6 -0
- data/lib/subledger/actor.rb +32 -0
- data/lib/subledger/collection_name.rb +25 -0
- data/lib/subledger/domain/account.rb +168 -0
- data/lib/subledger/domain/balance.rb +102 -0
- data/lib/subledger/domain/book.rb +111 -0
- data/lib/subledger/domain/category.rb +157 -0
- data/lib/subledger/domain/control.rb +180 -0
- data/lib/subledger/domain/formatters.rb +31 -0
- data/lib/subledger/domain/identity.rb +159 -0
- data/lib/subledger/domain/journal_entry.rb +293 -0
- data/lib/subledger/domain/key.rb +113 -0
- data/lib/subledger/domain/line.rb +272 -0
- data/lib/subledger/domain/org.rb +110 -0
- data/lib/subledger/domain/report.rb +247 -0
- data/lib/subledger/domain/report_rendering.rb +233 -0
- data/lib/subledger/domain/roles/activatable.rb +11 -0
- data/lib/subledger/domain/roles/archivable.rb +11 -0
- data/lib/subledger/domain/roles/attributable.rb +14 -0
- data/lib/subledger/domain/roles/collectable.rb +175 -0
- data/lib/subledger/domain/roles/creatable.rb +58 -0
- data/lib/subledger/domain/roles/describable.rb +33 -0
- data/lib/subledger/domain/roles/describable_report_rendering.rb +50 -0
- data/lib/subledger/domain/roles/identifiable.rb +15 -0
- data/lib/subledger/domain/roles/postable.rb +54 -0
- data/lib/subledger/domain/roles/progressable.rb +11 -0
- data/lib/subledger/domain/roles/readable.rb +34 -0
- data/lib/subledger/domain/roles/restable.rb +69 -0
- data/lib/subledger/domain/roles/storable.rb +30 -0
- data/lib/subledger/domain/roles/timeable.rb +18 -0
- data/lib/subledger/domain/roles/updatable.rb +35 -0
- data/lib/subledger/domain/roles/versionable.rb +35 -0
- data/lib/subledger/domain/roles.rb +16 -0
- data/lib/subledger/domain/value/credit.rb +16 -0
- data/lib/subledger/domain/value/debit.rb +16 -0
- data/lib/subledger/domain/value/zero.rb +24 -0
- data/lib/subledger/domain/value.rb +111 -0
- data/lib/subledger/domain.rb +95 -0
- data/lib/subledger/exception_handler.rb +65 -0
- data/lib/subledger/interface/client.rb +295 -0
- data/lib/subledger/interface/dispatcher.rb +20 -0
- data/lib/subledger/interface.rb +2 -0
- data/lib/subledger/path.rb +106 -0
- data/lib/subledger/rest.rb +128 -0
- data/lib/subledger/server.rb +3 -0
- data/lib/subledger/store/api/errors.rb +95 -0
- data/lib/subledger/store/api/roles/activate.rb +21 -0
- data/lib/subledger/store/api/roles/archive.rb +21 -0
- data/lib/subledger/store/api/roles/balance.rb +39 -0
- data/lib/subledger/store/api/roles/categories.rb +51 -0
- data/lib/subledger/store/api/roles/collect.rb +58 -0
- data/lib/subledger/store/api/roles/create.rb +26 -0
- data/lib/subledger/store/api/roles/create_and_post.rb +35 -0
- data/lib/subledger/store/api/roles/create_identity.rb +39 -0
- data/lib/subledger/store/api/roles/create_line.rb +24 -0
- data/lib/subledger/store/api/roles/first_and_last_line.rb +31 -0
- data/lib/subledger/store/api/roles/post.rb +25 -0
- data/lib/subledger/store/api/roles/progress.rb +21 -0
- data/lib/subledger/store/api/roles/read.rb +19 -0
- data/lib/subledger/store/api/roles/reports.rb +77 -0
- data/lib/subledger/store/api/roles/update.rb +24 -0
- data/lib/subledger/store/api/store.rb +103 -0
- data/lib/subledger/store/api.rb +20 -0
- data/lib/subledger/store.rb +236 -0
- data/lib/subledger/supervisor.rb +21 -0
- data/lib/subledger/uuid.rb +52 -0
- data/lib/subledger/version.rb +4 -0
- data/lib/subledger.rb +234 -0
- data/spec/spec_helper.rb +77 -0
- data/spec/subledger_account_spec.rb +354 -0
- data/spec/subledger_book_spec.rb +130 -0
- data/spec/subledger_category_spec.rb +203 -0
- data/spec/subledger_control_spec.rb +43 -0
- data/spec/subledger_identity_spec.rb +47 -0
- data/spec/subledger_journal_entry_spec.rb +417 -0
- data/spec/subledger_key_spec.rb +43 -0
- data/spec/subledger_org_spec.rb +68 -0
- data/spec/subledger_report_spec.rb +295 -0
- data/spec/subledger_spec.rb +101 -0
- data/subledger.gemspec +52 -0
- metadata +205 -0
@@ -0,0 +1,175 @@
|
|
1
|
+
module Subledger
|
2
|
+
module Domain
|
3
|
+
module Roles
|
4
|
+
module Collectable
|
5
|
+
def self.included base
|
6
|
+
base.extend CollectableClass
|
7
|
+
end
|
8
|
+
|
9
|
+
module CollectableClass
|
10
|
+
|
11
|
+
def collect args, &block
|
12
|
+
limit = args[:limit] ||= 25 unless block_given?
|
13
|
+
|
14
|
+
validate args
|
15
|
+
|
16
|
+
store = args[:store]
|
17
|
+
client = args[:client]
|
18
|
+
anchor = args[:anchor]
|
19
|
+
action = args[:action]
|
20
|
+
collection_name = CollectionName.with_state( args.
|
21
|
+
merge :klass => self )
|
22
|
+
|
23
|
+
args[:collection_name] = collection_name
|
24
|
+
|
25
|
+
unless anchor
|
26
|
+
anchor = args[:anchor] = client.send collection_name, args
|
27
|
+
|
28
|
+
anchor.read if [:preceding, :following].include? action
|
29
|
+
end
|
30
|
+
|
31
|
+
validate_criterion args
|
32
|
+
|
33
|
+
if block_given?
|
34
|
+
collect_with_block args, &block
|
35
|
+
else
|
36
|
+
store.collect args
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
ACTION_MAP = { :before => :preceding,
|
43
|
+
:ending => :preceding,
|
44
|
+
:starting => :following,
|
45
|
+
:after => :following,
|
46
|
+
:preceding => :preceding,
|
47
|
+
:following => :following }
|
48
|
+
|
49
|
+
MAX_LIMIT = 100
|
50
|
+
|
51
|
+
def collect_with_block args
|
52
|
+
store = args[:store]
|
53
|
+
anchor = args[:anchor]
|
54
|
+
action = args[:action]
|
55
|
+
limit = args[:limit]
|
56
|
+
|
57
|
+
next_action = ACTION_MAP[ action ]
|
58
|
+
|
59
|
+
total = 0
|
60
|
+
|
61
|
+
store_limit = first_limit limit
|
62
|
+
|
63
|
+
while not ( finished_collecting? limit, total ) and
|
64
|
+
not ( collected = store.collect(
|
65
|
+
args.merge!(
|
66
|
+
:anchor => anchor,
|
67
|
+
:action => action,
|
68
|
+
:limit => store_limit ) ) ).empty?
|
69
|
+
|
70
|
+
collected.each do |item|
|
71
|
+
yield item
|
72
|
+
|
73
|
+
total += 1
|
74
|
+
end
|
75
|
+
|
76
|
+
action = next_action
|
77
|
+
anchor = collected.last
|
78
|
+
store_limit = next_limit limit, total
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def finished_collecting? limit, total
|
83
|
+
not limit.nil? and total >= limit
|
84
|
+
end
|
85
|
+
|
86
|
+
def first_limit limit
|
87
|
+
( limit.nil? or limit > MAX_LIMIT ) ? MAX_LIMIT : limit
|
88
|
+
end
|
89
|
+
|
90
|
+
def next_limit limit, total
|
91
|
+
limit.nil? ? MAX_LIMIT : calculated_limit( limit, total )
|
92
|
+
end
|
93
|
+
|
94
|
+
def calculated_limit limit,total
|
95
|
+
new_limit = limit - total
|
96
|
+
|
97
|
+
new_limit < MAX_LIMIT ? new_limit : MAX_LIMIT
|
98
|
+
end
|
99
|
+
|
100
|
+
def validate args
|
101
|
+
validate_action args
|
102
|
+
validate_limit args
|
103
|
+
validate_state args
|
104
|
+
end
|
105
|
+
|
106
|
+
ACTIONS = [ :before,
|
107
|
+
:ending,
|
108
|
+
:starting,
|
109
|
+
:after,
|
110
|
+
:preceding,
|
111
|
+
:following ]
|
112
|
+
|
113
|
+
def validate_action args
|
114
|
+
unless ACTIONS.include? args[:action]
|
115
|
+
raise CollectableError, ':action must be :before, :ending, :starting, :after, :preceding, or :following'
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def validate_limit args
|
120
|
+
limit = args[:limit]
|
121
|
+
|
122
|
+
if not limit.nil? and limit < 1
|
123
|
+
raise CollectableError, ':limit must be greater than zero or nil'
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
def validate_state args
|
128
|
+
state = args[:state]
|
129
|
+
|
130
|
+
if state.nil?
|
131
|
+
raise CollectableError, ':state is required'
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
COLLECTABLE_BY = { :building_report_renderings => :rendered_at,
|
136
|
+
:completed_report_renderings => :rendered_at,
|
137
|
+
|
138
|
+
:archived_accounts => :description,
|
139
|
+
:active_accounts => :description,
|
140
|
+
:archived_books => :description,
|
141
|
+
:active_books => :description,
|
142
|
+
:archived_categories => :description,
|
143
|
+
:active_categories => :description,
|
144
|
+
:archived_reports => :description,
|
145
|
+
:active_reports => :description,
|
146
|
+
|
147
|
+
:account_lines => :effective_at,
|
148
|
+
:active_journal_entries => :effective_at,
|
149
|
+
:archived_journal_entries => :effective_at,
|
150
|
+
:posting_journal_entries => :effective_at,
|
151
|
+
:posted_journal_entries => :effective_at,
|
152
|
+
|
153
|
+
:archived_lines => :order,
|
154
|
+
:active_lines => :order,
|
155
|
+
:posted_lines => :order,
|
156
|
+
|
157
|
+
:archived_controls => :id,
|
158
|
+
:active_controls => :id,
|
159
|
+
:archived_keys => :id,
|
160
|
+
:active_keys => :id }
|
161
|
+
|
162
|
+
def validate_criterion args
|
163
|
+
anchor = args[ :anchor ]
|
164
|
+
collection_name = args[ :collection_name ]
|
165
|
+
required_field = COLLECTABLE_BY[ collection_name ]
|
166
|
+
|
167
|
+
if anchor.send( required_field ).nil?
|
168
|
+
raise CollectableError, "#{required_field.inspect} is required"
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module Subledger
|
2
|
+
module Domain
|
3
|
+
module Roles
|
4
|
+
module Creatable
|
5
|
+
def self.included base
|
6
|
+
base.extend CreatableClass
|
7
|
+
end
|
8
|
+
|
9
|
+
module CreatableClass
|
10
|
+
def create args
|
11
|
+
validate_creatability args
|
12
|
+
|
13
|
+
creatable = args[:client].send active_klass.collection_name, args
|
14
|
+
|
15
|
+
args[:store].create creatable
|
16
|
+
end
|
17
|
+
|
18
|
+
def new_or_create args
|
19
|
+
id = args[:id]
|
20
|
+
|
21
|
+
if id.nil?
|
22
|
+
item = active_klass.create args
|
23
|
+
|
24
|
+
yield item
|
25
|
+
|
26
|
+
item
|
27
|
+
else
|
28
|
+
active_klass.new args
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def validate_creatability args
|
35
|
+
raise_unless_creatable args
|
36
|
+
validate_creatability_modules args
|
37
|
+
end
|
38
|
+
|
39
|
+
def validate_creatability_modules args
|
40
|
+
self.included_modules.each do |mod|
|
41
|
+
if mod.respond_to? :raise_unless_creatable
|
42
|
+
mod.raise_unless_creatable args
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def create
|
49
|
+
created = self.class.create self.attributes
|
50
|
+
|
51
|
+
initialize created.attributes
|
52
|
+
|
53
|
+
self
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Subledger
|
2
|
+
module Domain
|
3
|
+
module Roles
|
4
|
+
module Describable
|
5
|
+
attr_accessor :description, :reference
|
6
|
+
|
7
|
+
def self.raise_unless_creatable args
|
8
|
+
description = args[:description]
|
9
|
+
|
10
|
+
if description.nil? or not description.kind_of? String
|
11
|
+
raise DescribableError, ':description is required and must be a String'
|
12
|
+
end
|
13
|
+
|
14
|
+
reference = args[:reference]
|
15
|
+
|
16
|
+
if not reference.nil? and reference !~ URI.regexp
|
17
|
+
raise DescribableError, ':reference must be a URL'
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def describable args
|
24
|
+
description = args[:description]
|
25
|
+
@description = description.nil? ? nil : description.encode('UTF-8')
|
26
|
+
|
27
|
+
reference = args[:reference]
|
28
|
+
@reference = reference.nil? ? nil : reference.encode('UTF-8')
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Subledger
|
2
|
+
module Domain
|
3
|
+
module Roles
|
4
|
+
module DescribableReportRendering
|
5
|
+
attr_accessor :description, :reference
|
6
|
+
|
7
|
+
def self.raise_unless_creatable args
|
8
|
+
report = args[:report]
|
9
|
+
|
10
|
+
if report.nil? or not report.kind_of? Report
|
11
|
+
raise DescribableReportRenderingError, ':report is required and must be a Report'
|
12
|
+
end
|
13
|
+
|
14
|
+
description = report.description
|
15
|
+
|
16
|
+
if description.nil? or not description.kind_of? String
|
17
|
+
raise DescribableReportRenderingError, ':report :description is required and must be a String'
|
18
|
+
end
|
19
|
+
|
20
|
+
reference = report.reference
|
21
|
+
|
22
|
+
if not reference.nil? and reference !~ URI.regexp
|
23
|
+
raise DescribableReportRenderingError, ':report :reference must be a URL'
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def describable_report_rendering args
|
31
|
+
description = args[:description]
|
32
|
+
reference = args[:reference]
|
33
|
+
report = args[:report]
|
34
|
+
|
35
|
+
if description.nil?
|
36
|
+
@description = report.nil? ? nil : report.description
|
37
|
+
else
|
38
|
+
@description = description.encode('UTF-8')
|
39
|
+
end
|
40
|
+
|
41
|
+
if reference.nil?
|
42
|
+
@reference = report.nil? ? nil : report.reference
|
43
|
+
else
|
44
|
+
@reference = reference.encode('UTF-8')
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Subledger
|
2
|
+
module Domain
|
3
|
+
module Roles
|
4
|
+
module Postable
|
5
|
+
def post
|
6
|
+
validate_postability
|
7
|
+
|
8
|
+
from_db = read
|
9
|
+
|
10
|
+
from_store = store.post self
|
11
|
+
|
12
|
+
if from_db.kind_of? posted_klass
|
13
|
+
from_db
|
14
|
+
else
|
15
|
+
from_store
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def posting_klass
|
20
|
+
PostingJournalEntry
|
21
|
+
end
|
22
|
+
|
23
|
+
def posted_klass
|
24
|
+
PostedJournalEntry
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def validate_postability
|
30
|
+
case self
|
31
|
+
when ArchivedJournalEntry
|
32
|
+
raise PostableError, 'Cannot post an archived journal entry'
|
33
|
+
when ActiveJournalEntry
|
34
|
+
|
35
|
+
reason = if lines.length.zero?
|
36
|
+
'Cannot post a journal entry with no lines'
|
37
|
+
elsif not balanced?
|
38
|
+
'Cannot post an unbalanced journal entry'
|
39
|
+
end
|
40
|
+
|
41
|
+
unless reason.nil?
|
42
|
+
set_reason reason
|
43
|
+
raise PostableError, reason
|
44
|
+
end
|
45
|
+
when PostingJournalEntry
|
46
|
+
# All is fine
|
47
|
+
when PostedJournalEntry
|
48
|
+
# All is fine
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Subledger
|
2
|
+
module Domain
|
3
|
+
module Roles
|
4
|
+
module Readable
|
5
|
+
def self.included base
|
6
|
+
base.extend ReadableClass
|
7
|
+
end
|
8
|
+
|
9
|
+
module ReadableClass
|
10
|
+
def read args
|
11
|
+
unless args[:id]
|
12
|
+
raise ReadableError, 'Cannot read without :id'
|
13
|
+
end
|
14
|
+
|
15
|
+
readable = args[:client].send collection_name, args
|
16
|
+
|
17
|
+
args[:store].read readable
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def read
|
22
|
+
readable = self.class.read attributes
|
23
|
+
|
24
|
+
if self.class == readable.class
|
25
|
+
initialize readable.attributes
|
26
|
+
self
|
27
|
+
else
|
28
|
+
readable
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module Subledger
|
2
|
+
module Domain
|
3
|
+
module Roles
|
4
|
+
module Restable
|
5
|
+
def post_hash
|
6
|
+
hash = { }
|
7
|
+
|
8
|
+
self.class.post_keys.each do |key|
|
9
|
+
value = self.send key
|
10
|
+
|
11
|
+
hash[key] = translate( key, value ) unless exclude? value
|
12
|
+
end
|
13
|
+
|
14
|
+
hash
|
15
|
+
end
|
16
|
+
|
17
|
+
def patch_hash
|
18
|
+
hash = { }
|
19
|
+
|
20
|
+
self.class.patch_keys.each do |key|
|
21
|
+
value = self.send key
|
22
|
+
|
23
|
+
hash[key] = translate( key, value ) unless exclude? value
|
24
|
+
end
|
25
|
+
|
26
|
+
hash
|
27
|
+
end
|
28
|
+
|
29
|
+
def serializable_hash
|
30
|
+
entity = self.class::Entity.new self
|
31
|
+
|
32
|
+
hash = entity.serializable_hash
|
33
|
+
|
34
|
+
hash.each do |key, value|
|
35
|
+
hash.delete( key ) if exclude? value
|
36
|
+
end
|
37
|
+
|
38
|
+
hash
|
39
|
+
end
|
40
|
+
|
41
|
+
def to_json
|
42
|
+
MultiJson.dump serializable_hash
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
# TODO elimate this using serializable hash
|
48
|
+
def translate key, value
|
49
|
+
case key.to_s
|
50
|
+
when /at$/
|
51
|
+
value.iso8601(3)
|
52
|
+
when 'org', 'book', 'account', 'journal_entry', 'identity', 'report'
|
53
|
+
value.id
|
54
|
+
when 'value'
|
55
|
+
value.rest_hash
|
56
|
+
when 'normal_balance'
|
57
|
+
value.type
|
58
|
+
else
|
59
|
+
value
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def exclude? value
|
64
|
+
value.nil? or ( value.kind_of?( String ) and value.length.zero? )
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Subledger
|
2
|
+
module Domain
|
3
|
+
module Roles
|
4
|
+
module Storable
|
5
|
+
attr_reader :store, :client
|
6
|
+
|
7
|
+
def self.raise_unless_creatable args
|
8
|
+
store = args[:store]
|
9
|
+
|
10
|
+
if store.nil? or not store.kind_of? Store
|
11
|
+
raise StorableError, ':store is required and must be a Store'
|
12
|
+
end
|
13
|
+
|
14
|
+
client = args[:client]
|
15
|
+
|
16
|
+
if client.nil? or not client.kind_of? Interface::Client
|
17
|
+
raise StorableError, ':client is required and must be a Client'
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def storable args
|
24
|
+
@store = args[:store]
|
25
|
+
@client = args[:client]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Subledger
|
2
|
+
module Domain
|
3
|
+
module Roles
|
4
|
+
module Updatable
|
5
|
+
def self.included base
|
6
|
+
base.extend UpdatableClass
|
7
|
+
end
|
8
|
+
|
9
|
+
module UpdatableClass
|
10
|
+
def update args
|
11
|
+
client = args[:client]
|
12
|
+
|
13
|
+
updatable = client.send collection_name, args
|
14
|
+
|
15
|
+
args[:store].update updatable
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def update
|
20
|
+
updatable = dup
|
21
|
+
|
22
|
+
updatable.send :increment_version
|
23
|
+
|
24
|
+
args = updatable.attributes
|
25
|
+
|
26
|
+
updated = self.class.update args
|
27
|
+
|
28
|
+
initialize updated.attributes
|
29
|
+
|
30
|
+
self
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Subledger
|
2
|
+
module Domain
|
3
|
+
module Roles
|
4
|
+
module Versionable
|
5
|
+
def self.included base
|
6
|
+
base.extend VersionableClass
|
7
|
+
end
|
8
|
+
|
9
|
+
module VersionableClass
|
10
|
+
def self.raise_unless_creatable args
|
11
|
+
version = args[:version]
|
12
|
+
|
13
|
+
if version.nil? or not version.kind_of? Fixnum
|
14
|
+
raise VersionableError, ':version is required and must be a Fixnum'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
attr_reader :version
|
20
|
+
|
21
|
+
protected
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def versionable args
|
26
|
+
@version = args[:version] || 1
|
27
|
+
end
|
28
|
+
|
29
|
+
def increment_version
|
30
|
+
@version += 1
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'subledger/domain/roles/activatable'
|
2
|
+
require 'subledger/domain/roles/archivable'
|
3
|
+
require 'subledger/domain/roles/attributable'
|
4
|
+
require 'subledger/domain/roles/collectable'
|
5
|
+
require 'subledger/domain/roles/creatable'
|
6
|
+
require 'subledger/domain/roles/describable'
|
7
|
+
require 'subledger/domain/roles/describable_report_rendering'
|
8
|
+
require 'subledger/domain/roles/identifiable'
|
9
|
+
require 'subledger/domain/roles/postable'
|
10
|
+
require 'subledger/domain/roles/progressable'
|
11
|
+
require 'subledger/domain/roles/readable'
|
12
|
+
require 'subledger/domain/roles/restable'
|
13
|
+
require 'subledger/domain/roles/storable'
|
14
|
+
require 'subledger/domain/roles/timeable'
|
15
|
+
require 'subledger/domain/roles/updatable'
|
16
|
+
require 'subledger/domain/roles/versionable'
|