supermodel 0.0.6 → 0.0.8
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 +2 -2
- data/VERSION +1 -1
- data/lib/supermodel/base.rb +35 -19
- data/lib/supermodel/marshal.rb +5 -3
- data/lib/supermodel/redis.rb +109 -90
- data/lib/supermodel.rb +0 -1
- data/supermodel.gemspec +5 -6
- metadata +3 -4
- data/lib/supermodel/scriber.rb +0 -80
data/Rakefile
CHANGED
@@ -7,8 +7,8 @@ begin
|
|
7
7
|
gemspec.homepage = "http://github.com/maccman/supermodel"
|
8
8
|
gemspec.description = "In memory DB using ActiveModel"
|
9
9
|
gemspec.authors = ["Alex MacCaw"]
|
10
|
-
gemspec.add_dependency("activemodel")
|
10
|
+
gemspec.add_dependency("activemodel", ">= 3.0.0.beta")
|
11
11
|
end
|
12
12
|
rescue LoadError
|
13
13
|
puts "Jeweler not available. Install it with: sudo gem install jeweler"
|
14
|
-
end
|
14
|
+
end
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.8
|
data/lib/supermodel/base.rb
CHANGED
@@ -1,24 +1,26 @@
|
|
1
1
|
module SuperModel
|
2
2
|
class Base
|
3
3
|
include ActiveModel::Dirty
|
4
|
-
|
4
|
+
class_inheritable_array :known_attributes
|
5
|
+
self.known_attributes = []
|
6
|
+
|
5
7
|
class << self
|
6
8
|
attr_accessor_with_default(:primary_key, 'id') #:nodoc:
|
7
|
-
|
9
|
+
|
8
10
|
def attributes(*attributes)
|
9
|
-
|
10
|
-
end
|
11
|
-
|
12
|
-
def known_attributes
|
13
|
-
@known_attributes ||= []
|
11
|
+
self.known_attributes += attributes.map(&:to_s)
|
14
12
|
end
|
15
13
|
|
16
14
|
def records
|
17
15
|
@records ||= []
|
18
16
|
end
|
19
17
|
|
18
|
+
def find_by_attribute(name, value) #:nodoc:
|
19
|
+
records.find {|r| r.send(name) == value }
|
20
|
+
end
|
21
|
+
|
20
22
|
def raw_find(id) #:nodoc:
|
21
|
-
|
23
|
+
find_by_attribute(:id, id) || raise(UnknownRecord)
|
22
24
|
end
|
23
25
|
|
24
26
|
# Find record by ID, or raise.
|
@@ -46,8 +48,8 @@ module SuperModel
|
|
46
48
|
records.dup
|
47
49
|
end
|
48
50
|
|
49
|
-
def update(id,
|
50
|
-
find(id).
|
51
|
+
def update(id, atts)
|
52
|
+
find(id).update_attributes(atts)
|
51
53
|
end
|
52
54
|
|
53
55
|
def destroy(id)
|
@@ -74,10 +76,6 @@ module SuperModel
|
|
74
76
|
rec.save && rec
|
75
77
|
end
|
76
78
|
|
77
|
-
def find_by_attribute(name, value) #:nodoc:
|
78
|
-
records.find {|r| r.name == value }
|
79
|
-
end
|
80
|
-
|
81
79
|
def method_missing(method_symbol, *args) #:nodoc:
|
82
80
|
method_name = method_symbol.to_s
|
83
81
|
|
@@ -94,12 +92,14 @@ module SuperModel
|
|
94
92
|
end
|
95
93
|
|
96
94
|
attr_accessor :attributes
|
95
|
+
attr_writer :new_record
|
97
96
|
|
98
97
|
def known_attributes
|
99
98
|
self.class.known_attributes + self.attributes.keys.map(&:to_s)
|
100
99
|
end
|
101
100
|
|
102
101
|
def initialize(attributes = {})
|
102
|
+
@new_record = true
|
103
103
|
@attributes = {}.with_indifferent_access
|
104
104
|
load(attributes)
|
105
105
|
end
|
@@ -114,7 +114,7 @@ module SuperModel
|
|
114
114
|
end
|
115
115
|
|
116
116
|
def new?
|
117
|
-
|
117
|
+
@new_record || false
|
118
118
|
end
|
119
119
|
alias :new_record? :new?
|
120
120
|
|
@@ -143,7 +143,8 @@ module SuperModel
|
|
143
143
|
|
144
144
|
def dup
|
145
145
|
self.class.new.tap do |base|
|
146
|
-
base.attributes =
|
146
|
+
base.attributes = attributes
|
147
|
+
base.new_record = new_record?
|
147
148
|
end
|
148
149
|
end
|
149
150
|
|
@@ -193,8 +194,12 @@ module SuperModel
|
|
193
194
|
end
|
194
195
|
end
|
195
196
|
|
196
|
-
def
|
197
|
+
def raw_destroy
|
197
198
|
self.class.records.delete(self)
|
199
|
+
end
|
200
|
+
|
201
|
+
def destroy
|
202
|
+
raw_destroy
|
198
203
|
self
|
199
204
|
end
|
200
205
|
|
@@ -211,16 +216,27 @@ module SuperModel
|
|
211
216
|
object_id
|
212
217
|
end
|
213
218
|
|
219
|
+
def raw_create
|
220
|
+
self.class.records << self.dup
|
221
|
+
end
|
222
|
+
|
214
223
|
def create
|
215
224
|
self.id ||= generate_id
|
216
|
-
self.
|
225
|
+
self.new_record = false
|
226
|
+
raw_create
|
217
227
|
save_previous_changes
|
228
|
+
self.id
|
218
229
|
end
|
219
230
|
|
220
|
-
def
|
231
|
+
def raw_update
|
221
232
|
item = self.class.raw_find(id)
|
222
233
|
item.load(attributes)
|
234
|
+
end
|
235
|
+
|
236
|
+
def update
|
237
|
+
raw_update
|
223
238
|
save_previous_changes
|
239
|
+
true
|
224
240
|
end
|
225
241
|
|
226
242
|
def save_previous_changes
|
data/lib/supermodel/marshal.rb
CHANGED
@@ -45,11 +45,13 @@ module SuperModel
|
|
45
45
|
end
|
46
46
|
|
47
47
|
def marshal_dump
|
48
|
-
|
48
|
+
serializable_hash
|
49
49
|
end
|
50
50
|
|
51
|
-
def marshal_load(
|
52
|
-
|
51
|
+
def marshal_load(atts)
|
52
|
+
# Can't call load, since class
|
53
|
+
# isn't setup properly
|
54
|
+
@attributes = atts
|
53
55
|
end
|
54
56
|
end
|
55
57
|
end
|
data/lib/supermodel/redis.rb
CHANGED
@@ -1,36 +1,43 @@
|
|
1
1
|
module SuperModel
|
2
|
-
|
3
|
-
|
4
|
-
def
|
5
|
-
|
2
|
+
module Redis
|
3
|
+
module ClassMethods
|
4
|
+
def self.extended(base)
|
5
|
+
base.class_eval do
|
6
|
+
class_inheritable_array :indexed_attributes
|
7
|
+
self.indexed_attributes = []
|
8
|
+
class_inheritable_array :serialized_attributes
|
9
|
+
self.serialized_attributes = []
|
10
|
+
end
|
6
11
|
end
|
7
12
|
|
8
|
-
def
|
9
|
-
@
|
13
|
+
def namespace
|
14
|
+
@namespace ||= self.name.downcase
|
10
15
|
end
|
11
16
|
|
12
|
-
def
|
13
|
-
@
|
17
|
+
def namespace=(namespace)
|
18
|
+
@namespace = namespace
|
14
19
|
end
|
15
20
|
|
16
|
-
def
|
17
|
-
@
|
21
|
+
def redis
|
22
|
+
@redis ||= ::Redis.new
|
18
23
|
end
|
19
24
|
|
20
|
-
def
|
21
|
-
|
25
|
+
def indexes(*indexes)
|
26
|
+
self.indexed_attributes += indexes.map(&:to_s)
|
27
|
+
end
|
28
|
+
|
29
|
+
def serialize(*attributes)
|
30
|
+
self.serialized_attributes += attributes.map(&:to_s)
|
22
31
|
end
|
23
32
|
|
24
33
|
def redis_key(*args)
|
25
|
-
args.unshift(self.
|
34
|
+
args.unshift(self.namespace)
|
26
35
|
args.join(":")
|
27
36
|
end
|
28
37
|
|
29
38
|
def find(id)
|
30
39
|
if redis.set_member?(redis_key, id)
|
31
|
-
|
32
|
-
res.redis_get
|
33
|
-
res
|
40
|
+
existing(:id => id)
|
34
41
|
else
|
35
42
|
raise(UnknownRecord)
|
36
43
|
end
|
@@ -59,104 +66,116 @@ module SuperModel
|
|
59
66
|
def find_by_attribute(key, value)
|
60
67
|
item_ids = redis.set_members(redis_key(key, value))
|
61
68
|
return if item_ids.empty?
|
62
|
-
|
63
|
-
res.redis_get
|
64
|
-
res
|
69
|
+
existing(:id => item_ids.first)
|
65
70
|
end
|
66
71
|
|
67
72
|
protected
|
68
73
|
def from_ids(ids)
|
69
|
-
ids.map
|
70
|
-
res = self.new(:id => id)
|
71
|
-
res.redis_get
|
72
|
-
res
|
73
|
-
end
|
74
|
+
ids.map {|id| existing(:id => id) }
|
74
75
|
end
|
75
|
-
end
|
76
76
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
attributes.keys.each do |key|
|
84
|
-
redis.delete(redis_key(key))
|
85
|
-
end
|
77
|
+
def existing(atts = {})
|
78
|
+
item = self.new(atts)
|
79
|
+
item.new_record = false
|
80
|
+
item.redis_get
|
81
|
+
item
|
82
|
+
end
|
86
83
|
end
|
87
84
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
redis.set_delete(self.class.redis_key(index, old_attribute), id)
|
93
|
-
end
|
85
|
+
module InstanceMethods
|
86
|
+
# Redis integers are stored as strings
|
87
|
+
def id
|
88
|
+
super.try(:to_i)
|
94
89
|
end
|
95
90
|
|
96
|
-
def
|
97
|
-
|
98
|
-
|
99
|
-
|
91
|
+
def raw_destroy
|
92
|
+
return if new?
|
93
|
+
|
94
|
+
destroy_indexes
|
95
|
+
redis.set_delete(self.class.redis_key, self.id)
|
96
|
+
|
97
|
+
attributes.keys.each do |key|
|
98
|
+
redis.delete(redis_key(key))
|
100
99
|
end
|
101
100
|
end
|
102
101
|
|
103
|
-
|
104
|
-
|
105
|
-
|
102
|
+
protected
|
103
|
+
def destroy_indexes
|
104
|
+
indexed_attributes.each do |index|
|
105
|
+
old_attribute = changes[index].try(:first) || send(index)
|
106
|
+
redis.set_delete(self.class.redis_key(index, old_attribute), id)
|
107
|
+
end
|
108
|
+
end
|
106
109
|
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
+
def create_indexes
|
111
|
+
indexed_attributes.each do |index|
|
112
|
+
new_attribute = send(index)
|
113
|
+
redis.set_add(self.class.redis_key(index, new_attribute), id)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def generate_id
|
118
|
+
redis.incr(self.class.redis_key(:uid))
|
119
|
+
end
|
120
|
+
|
121
|
+
def indexed_attributes
|
122
|
+
attributes.keys & self.class.indexed_attributes
|
123
|
+
end
|
110
124
|
|
111
|
-
|
112
|
-
|
113
|
-
|
125
|
+
def redis
|
126
|
+
self.class.redis
|
127
|
+
end
|
114
128
|
|
115
|
-
|
116
|
-
|
117
|
-
|
129
|
+
def redis_key(*args)
|
130
|
+
self.class.redis_key(id, *args)
|
131
|
+
end
|
118
132
|
|
119
|
-
|
120
|
-
|
121
|
-
|
133
|
+
def serialized_attributes
|
134
|
+
self.class.serialized_attributes
|
135
|
+
end
|
122
136
|
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
137
|
+
def serialize_attribute(key, value)
|
138
|
+
return value unless serialized_attributes.include?(key)
|
139
|
+
value.to_json
|
140
|
+
end
|
127
141
|
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
142
|
+
def deserialize_attribute(key, value)
|
143
|
+
return value unless serialized_attributes.include?(key)
|
144
|
+
value && JSON.parse(value)
|
145
|
+
end
|
132
146
|
|
133
|
-
|
134
|
-
|
135
|
-
|
147
|
+
def redis_set
|
148
|
+
serializable_hash.each do |(key, value)|
|
149
|
+
redis.set(redis_key(key), serialize_attribute(key, value))
|
150
|
+
end
|
136
151
|
end
|
137
|
-
end
|
138
152
|
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
153
|
+
def redis_get
|
154
|
+
known_attributes.each do |key|
|
155
|
+
result = deserialize_attribute(key, redis.get(redis_key(key)))
|
156
|
+
send("#{key}=", result)
|
157
|
+
end
|
143
158
|
end
|
144
|
-
|
145
|
-
public :redis_get
|
159
|
+
public :redis_get
|
146
160
|
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
save_previous_changes
|
153
|
-
end
|
161
|
+
def raw_create
|
162
|
+
redis_set
|
163
|
+
create_indexes
|
164
|
+
redis.set_add(self.class.redis_key, self.id)
|
165
|
+
end
|
154
166
|
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
167
|
+
def raw_update
|
168
|
+
destroy_indexes
|
169
|
+
redis_set
|
170
|
+
create_indexes
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
module Model
|
175
|
+
def self.included(base)
|
176
|
+
base.send :include, InstanceMethods
|
177
|
+
base.send :extend, ClassMethods
|
160
178
|
end
|
179
|
+
end
|
161
180
|
end
|
162
|
-
end
|
181
|
+
end
|
data/lib/supermodel.rb
CHANGED
data/supermodel.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{supermodel}
|
8
|
-
s.version = "0.0.
|
8
|
+
s.version = "0.0.8"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Alex MacCaw"]
|
12
|
-
s.date = %q{2010-02-
|
12
|
+
s.date = %q{2010-02-10}
|
13
13
|
s.description = %q{In memory DB using ActiveModel}
|
14
14
|
s.email = %q{info@eribium.org}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -28,7 +28,6 @@ Gem::Specification.new do |s|
|
|
28
28
|
"lib/supermodel/observing.rb",
|
29
29
|
"lib/supermodel/random_id.rb",
|
30
30
|
"lib/supermodel/redis.rb",
|
31
|
-
"lib/supermodel/scriber.rb",
|
32
31
|
"lib/supermodel/validations.rb",
|
33
32
|
"supermodel.gemspec"
|
34
33
|
]
|
@@ -43,12 +42,12 @@ Gem::Specification.new do |s|
|
|
43
42
|
s.specification_version = 3
|
44
43
|
|
45
44
|
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
46
|
-
s.add_runtime_dependency(%q<activemodel>, [">= 0"])
|
45
|
+
s.add_runtime_dependency(%q<activemodel>, [">= 3.0.0.beta"])
|
47
46
|
else
|
48
|
-
s.add_dependency(%q<activemodel>, [">= 0"])
|
47
|
+
s.add_dependency(%q<activemodel>, [">= 3.0.0.beta"])
|
49
48
|
end
|
50
49
|
else
|
51
|
-
s.add_dependency(%q<activemodel>, [">= 0"])
|
50
|
+
s.add_dependency(%q<activemodel>, [">= 3.0.0.beta"])
|
52
51
|
end
|
53
52
|
end
|
54
53
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: supermodel
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alex MacCaw
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2010-02-
|
12
|
+
date: 2010-02-10 00:00:00 +00:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -20,7 +20,7 @@ dependencies:
|
|
20
20
|
requirements:
|
21
21
|
- - ">="
|
22
22
|
- !ruby/object:Gem::Version
|
23
|
-
version:
|
23
|
+
version: 3.0.0.beta
|
24
24
|
version:
|
25
25
|
description: In memory DB using ActiveModel
|
26
26
|
email: info@eribium.org
|
@@ -43,7 +43,6 @@ files:
|
|
43
43
|
- lib/supermodel/observing.rb
|
44
44
|
- lib/supermodel/random_id.rb
|
45
45
|
- lib/supermodel/redis.rb
|
46
|
-
- lib/supermodel/scriber.rb
|
47
46
|
- lib/supermodel/validations.rb
|
48
47
|
- supermodel.gemspec
|
49
48
|
has_rdoc: true
|
data/lib/supermodel/scriber.rb
DELETED
@@ -1,80 +0,0 @@
|
|
1
|
-
module SuperModel
|
2
|
-
module Scriber
|
3
|
-
class Observer
|
4
|
-
include Singleton
|
5
|
-
|
6
|
-
class << self
|
7
|
-
def disabled?
|
8
|
-
@disabled
|
9
|
-
end
|
10
|
-
|
11
|
-
def disable(&block)
|
12
|
-
@disabled = true
|
13
|
-
yield
|
14
|
-
@disabled = false
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
def after_create(rec)
|
19
|
-
rec.class.record(:create, rec.attributes)
|
20
|
-
end
|
21
|
-
|
22
|
-
def after_update(rec)
|
23
|
-
changed_to = rec.previous_changes.inject({}) {|hash, (key, (from, to))|
|
24
|
-
hash[key] = to
|
25
|
-
hash
|
26
|
-
}
|
27
|
-
rec.class.record(:update, changed_to)
|
28
|
-
end
|
29
|
-
|
30
|
-
def after_destroy
|
31
|
-
rec.class.record(:destroy, rec.id)
|
32
|
-
end
|
33
|
-
|
34
|
-
def update(observed_method, object) #:nodoc:
|
35
|
-
return if self.class.disabled?
|
36
|
-
send(observed_method, object) if respond_to?(observed_method)
|
37
|
-
end
|
38
|
-
|
39
|
-
def observed_class_inherited(subclass) #:nodoc:
|
40
|
-
subclass.add_observer(self)
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
def klasses
|
45
|
-
@klasses ||= []
|
46
|
-
end
|
47
|
-
module_function :klasses
|
48
|
-
|
49
|
-
module Model
|
50
|
-
def self.included(base)
|
51
|
-
Scriber.klasses << base
|
52
|
-
base.extend ClassMethods
|
53
|
-
base.add_observer(Observer.instance)
|
54
|
-
end
|
55
|
-
|
56
|
-
module ClassMethods
|
57
|
-
def scribe_play(type, data) #:nodoc:
|
58
|
-
Observer.disable do
|
59
|
-
case type
|
60
|
-
when :create then create(data)
|
61
|
-
when :destroy then destroy(data)
|
62
|
-
when :update then update(data)
|
63
|
-
else
|
64
|
-
method = "scribe_play_#{type}"
|
65
|
-
send(method) if respond_to?(method)
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
def record(type, data = nil)
|
71
|
-
::Scriber.record(
|
72
|
-
:klass => self,
|
73
|
-
:type => type,
|
74
|
-
:data => data
|
75
|
-
)
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
79
|
-
end
|
80
|
-
end
|