relaxo-model 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md ADDED
@@ -0,0 +1,31 @@
1
+ Relaxo Model
2
+ ============
3
+
4
+ * Author: Samuel G. D. Williams (<http://www.oriontransfer.co.nz>)
5
+ * Copyright (C) 2010, 2011 Samuel G. D. Williams.
6
+ * Released under the MIT license.
7
+
8
+ Relaxo Model provides a framework for business logic on top of Relaxo/CouchDB. While it supports some traditional ORM style patterns, it is primary focus is to model business processes and logic.
9
+
10
+ License
11
+ -------
12
+
13
+ Copyright (c) 2010, 2011 Samuel G. D. Williams. <http://www.oriontransfer.co.nz>
14
+
15
+ Permission is hereby granted, free of charge, to any person obtaining a copy
16
+ of this software and associated documentation files (the "Software"), to deal
17
+ in the Software without restriction, including without limitation the rights
18
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
19
+ copies of the Software, and to permit persons to whom the Software is
20
+ furnished to do so, subject to the following conditions:
21
+
22
+ The above copyright notice and this permission notice shall be included in
23
+ all copies or substantial portions of the Software.
24
+
25
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
28
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
29
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
30
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
31
+ THE SOFTWARE.
@@ -0,0 +1,212 @@
1
+ # Copyright (c) 2012 Samuel G. D. Williams. <http://www.oriontransfer.co.nz>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ module Relaxo
22
+ module Model
23
+ module ClassMethods
24
+ DEFAULT_VIEW_OPTIONS = {:include_docs => true}
25
+
26
+ def self.extended(child)
27
+ child.instance_variable_set(:@properties, {})
28
+ child.instance_variable_set(:@relationships, {})
29
+
30
+ default_type = child.name.split('::').last.gsub(/(.)([A-Z])/,'\1_\2').downcase!
31
+ child.instance_variable_set(:@type, default_type)
32
+ end
33
+
34
+ def metaclass
35
+ class << self; self; end
36
+ end
37
+
38
+ attr :properties
39
+ attr :relationships
40
+
41
+ def view(name, path, *args)
42
+ options = Hash === args.last ? args.pop : DEFAULT_VIEW_OPTIONS
43
+ klass = args.pop || options[:class]
44
+
45
+ self.metaclass.send(:define_method, name) do |database, query = {}|
46
+ records = database.view(path, query.merge(options))
47
+ Recordset.new(database, records, klass)
48
+ end
49
+ end
50
+
51
+ def relationship(name, path, *args)
52
+ options = Hash === args.last ? args.pop : {}
53
+ klass = args.pop || options[:class]
54
+
55
+ @relationships[name] = options
56
+
57
+ self.send(:define_method, name) do |query = {}|
58
+ query = query.merge(options)
59
+
60
+ unless query.include? :key
61
+ query[:key] = self.id
62
+ end
63
+
64
+ Recordset.new(@database, @database.view(path, query), klass)
65
+ end
66
+ end
67
+
68
+ def property(name, klass = nil)
69
+ name = name.to_s
70
+
71
+ @properties[name] = klass
72
+
73
+ self.send(:define_method, name) do
74
+ if @changed.include? name
75
+ return @changed[name]
76
+ elsif @document.include? name
77
+ if klass
78
+ @changed[name] = klass.convert_from_document(@database, @document[name])
79
+ else
80
+ @changed[name] = @document[name]
81
+ end
82
+ else
83
+ nil
84
+ end
85
+ end
86
+
87
+ self.send(:define_method, "#{name}=") do |value|
88
+ @changed[name] = value
89
+ end
90
+ end
91
+
92
+ def create(database, properties)
93
+ instance = self.new(database, {'type' => @type})
94
+
95
+ properties.each do |key, value|
96
+ instance[key] = value
97
+ end
98
+
99
+ instance.after_create
100
+
101
+ return instance
102
+ end
103
+
104
+ def fetch(database, id)
105
+ instance = self.new(database, database.get(id).to_hash)
106
+
107
+ instance.after_fetch
108
+
109
+ return instance
110
+ end
111
+ end
112
+
113
+ module Base
114
+ def initialize(database, document = {})
115
+ # Raw key-value database
116
+ @document = document
117
+ @database = database
118
+ @changed = {}
119
+ end
120
+
121
+ attr :database
122
+
123
+ def id
124
+ @document[ID]
125
+ end
126
+
127
+ def rev
128
+ @document[REV]
129
+ end
130
+
131
+ def clear(key)
132
+ @changed.delete(key)
133
+ @document.delete(key)
134
+ end
135
+
136
+ def [] name
137
+ name = name.to_s
138
+
139
+ if self.class.properties.include? name
140
+ self.send(name)
141
+ else
142
+ raise KeyError.new(name)
143
+ end
144
+ end
145
+
146
+ def []= name, value
147
+ name = name.to_s
148
+
149
+ if self.class.properties.include? name
150
+ self.send("#{name}=", value)
151
+ else
152
+ raise KeyError.new(name)
153
+ end
154
+ end
155
+
156
+ # Update any calculations:
157
+ def before_save
158
+ end
159
+
160
+ def after_save
161
+ end
162
+
163
+ def save
164
+ before_save
165
+
166
+ return if @changed.size == 0 && self.id
167
+
168
+ # Flatten changed properties:
169
+ self.class.properties.each do |key, klass|
170
+ if @changed.include? key
171
+ if klass
172
+ @document[key] = klass.convert_to_document(@changed.delete(key))
173
+ else
174
+ @document[key] = @changed.delete(key)
175
+ end
176
+ end
177
+ end
178
+
179
+ # Non-specific properties, serialised by JSON:
180
+ @changed.each do |key, value|
181
+ @document[key] = value
182
+ end
183
+
184
+ @changed = {}
185
+ @database.save(@document)
186
+
187
+ after_save
188
+ end
189
+
190
+ def before_delete
191
+ end
192
+
193
+ def after_delete
194
+ end
195
+
196
+ def delete
197
+ before_delete
198
+
199
+ @database.delete(@document)
200
+
201
+ after_delete
202
+ end
203
+
204
+ def after_fetch
205
+ end
206
+
207
+ # Set any default values:
208
+ def after_create
209
+ end
210
+ end
211
+ end
212
+ end
@@ -0,0 +1,31 @@
1
+ # Copyright (c) 2012 Samuel G. D. Williams. <http://www.oriontransfer.co.nz>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ module Relaxo
22
+ module Model
23
+ module VERSION
24
+ MAJOR = 0
25
+ MINOR = 3
26
+ TINY = 0
27
+
28
+ STRING = [MAJOR, MINOR, TINY].join('.')
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,35 @@
1
+ # Copyright (c) 2012 Samuel G. D. Williams. <http://www.oriontransfer.co.nz>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ require 'relaxo/model/base'
22
+ require 'relaxo/recordset'
23
+ require 'relaxo/properties'
24
+
25
+ module Relaxo
26
+ module Model
27
+ def self.included(child)
28
+ # Include all available properties
29
+ child.send(:include, Relaxo::Properties)
30
+ child.send(:include, Relaxo::Model::Base)
31
+
32
+ child.send(:extend, Relaxo::Model::ClassMethods)
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,35 @@
1
+ # Copyright (c) 2012 Samuel G. D. Williams. <http://www.oriontransfer.co.nz>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ require 'money'
22
+
23
+ module Relaxo
24
+ module Properties
25
+ Attribute.for_class(Money) do
26
+ def convert_to_document(value)
27
+ [value.cents, value.currency.to_s]
28
+ end
29
+
30
+ def convert_from_document(database, value)
31
+ Money.new(value[0], value[1])
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,129 @@
1
+ # Copyright (c) 2012 Samuel G. D. Williams. <http://www.oriontransfer.co.nz>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ require 'date'
22
+
23
+ module Relaxo
24
+ module Properties
25
+ class Attribute
26
+ @@attributes = {}
27
+
28
+ def self.for_class(klass, &block)
29
+ @@attributes[klass] = Proc.new(&block)
30
+ end
31
+
32
+ def self.[] klass
33
+ self.new(klass)
34
+ end
35
+
36
+ def initialize(klass)
37
+ @klass = klass
38
+
39
+ self.instance_eval &@@attributes[klass]
40
+ end
41
+ end
42
+
43
+ Attribute.for_class(Integer) do
44
+ def convert_to_document(value)
45
+ value.to_i
46
+ end
47
+
48
+ def convert_from_document(database, value)
49
+ value.to_i
50
+ end
51
+ end
52
+
53
+ Attribute.for_class(Float) do
54
+ def convert_to_document(value)
55
+ value.to_f
56
+ end
57
+
58
+ def convert_from_document(database, value)
59
+ value.to_f
60
+ end
61
+ end
62
+
63
+ Attribute.for_class(Date) do
64
+ def convert_to_document(value)
65
+ value.iso8601
66
+ end
67
+
68
+ def convert_from_document(database, string)
69
+ Date.parse(string)
70
+ end
71
+ end
72
+
73
+ Attribute.for_class(DateTime) do
74
+ def convert_to_document(value)
75
+ value.iso8601
76
+ end
77
+
78
+ def convert_from_document(database, string)
79
+ DateTime.parse(string)
80
+ end
81
+ end
82
+
83
+ Attribute.for_class(String) do
84
+ def convert_to_document(value)
85
+ value.to_s
86
+ end
87
+
88
+ def convert_from_document(database, string)
89
+ string.to_s
90
+ end
91
+ end
92
+
93
+ class BelongsTo
94
+ def self.[] klass
95
+ self.new(klass)
96
+ end
97
+
98
+ def initialize(klass)
99
+ @klass = klass
100
+ end
101
+
102
+ def convert_to_document(value)
103
+ unless value.id
104
+ value.save
105
+ end
106
+
107
+ value.id
108
+ end
109
+
110
+ def convert_from_document(database, string)
111
+ @klass.fetch(database, string)
112
+ end
113
+ end
114
+
115
+ class Lookup
116
+ def self.[] klass
117
+ self.class.new(klass)
118
+ end
119
+
120
+ def initialize(klass)
121
+ @klass = klass
122
+ end
123
+
124
+ def new(database, id)
125
+ @klass.fetch(database, id)
126
+ end
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,61 @@
1
+
2
+ # Copyright (c) 2012 Samuel G. D. Williams. <http://www.oriontransfer.co.nz>
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ # of this software and associated documentation files (the "Software"), to deal
6
+ # in the Software without restriction, including without limitation the rights
7
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ # copies of the Software, and to permit persons to whom the Software is
9
+ # furnished to do so, subject to the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be included in
12
+ # all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
+ # THE SOFTWARE.
21
+
22
+ module Relaxo
23
+ class Recordset
24
+ include Enumerable
25
+
26
+ def initialize(database, view, klass = nil)
27
+ @database = database
28
+ @view = view
29
+
30
+ @klass = klass
31
+ end
32
+
33
+ attr :klass
34
+ attr :database
35
+
36
+ def count
37
+ @view["total_rows"]
38
+ end
39
+
40
+ def offset
41
+ @view["offset"]
42
+ end
43
+
44
+ def rows
45
+ @view["rows"]
46
+ end
47
+
48
+ def each(klass = nil, &block)
49
+ klass ||= @klass
50
+
51
+ if klass
52
+ rows.each do |row|
53
+ # If user specified :include_docs => true, row['doc'] contains the primary value:
54
+ yield klass.new(@database, row['doc'] || row['value'])
55
+ end
56
+ else
57
+ rows.each &block
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,21 @@
1
+ # Copyright (c) 2012 Samuel G. D. Williams. <http://www.oriontransfer.co.nz>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ require 'relaxo/model'
metadata ADDED
@@ -0,0 +1,84 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: relaxo-model
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Samuel Williams
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-07-11 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: relaxo
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: money
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ description:
47
+ email: samuel.williams@oriontransfer.co.nz
48
+ executables: []
49
+ extensions: []
50
+ extra_rdoc_files: []
51
+ files:
52
+ - lib/relaxo/model/base.rb
53
+ - lib/relaxo/model/version.rb
54
+ - lib/relaxo/model.rb
55
+ - lib/relaxo/properties/money.rb
56
+ - lib/relaxo/properties.rb
57
+ - lib/relaxo/recordset.rb
58
+ - lib/relaxo-model.rb
59
+ - README.md
60
+ homepage: http://www.oriontransfer.co.nz/gems/relaxo
61
+ licenses: []
62
+ post_install_message:
63
+ rdoc_options: []
64
+ require_paths:
65
+ - lib
66
+ required_ruby_version: !ruby/object:Gem::Requirement
67
+ none: false
68
+ requirements:
69
+ - - ! '>='
70
+ - !ruby/object:Gem::Version
71
+ version: '0'
72
+ required_rubygems_version: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ requirements: []
79
+ rubyforge_project:
80
+ rubygems_version: 1.8.23
81
+ signing_key:
82
+ specification_version: 3
83
+ summary: Relaxo Model is a high level business logic framework for CouchDB/Relaxo.
84
+ test_files: []