supermodel 0.0.5 → 0.0.6
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 +1 -0
- data/README +18 -7
- data/VERSION +1 -1
- data/lib/supermodel/base.rb +9 -3
- data/lib/supermodel/{persist.rb → marshal.rb} +4 -4
- data/lib/supermodel/redis.rb +162 -0
- data/lib/supermodel/scriber.rb +5 -1
- data/lib/supermodel.rb +4 -3
- data/supermodel.gemspec +3 -2
- metadata +3 -2
data/.gitignore
CHANGED
data/README
CHANGED
@@ -10,7 +10,8 @@ Supports:
|
|
10
10
|
* Callbacks
|
11
11
|
* Observers
|
12
12
|
* Dirty (Changes)
|
13
|
-
*
|
13
|
+
* Ruby Marshalling to disk
|
14
|
+
* Redis
|
14
15
|
|
15
16
|
Examples:
|
16
17
|
|
@@ -37,15 +38,25 @@ You can use a random ID rather than the object ID:
|
|
37
38
|
t = Test.create(:name => "test")
|
38
39
|
t.id #=> "7ee935377bb4aecc54ad4f9126"
|
39
40
|
|
40
|
-
You can
|
41
|
+
You can marshal objects to disk on startup/shutdown
|
41
42
|
|
42
43
|
class Test < SuperModel::Base
|
43
|
-
include SuperModel::
|
44
|
+
include SuperModel::Marshal::Model
|
44
45
|
end
|
45
46
|
|
46
|
-
SuperModel::
|
47
|
-
SuperModel::
|
47
|
+
SuperModel::Marshal.path = "dump.db"
|
48
|
+
SuperModel::Marshal.load
|
48
49
|
|
49
50
|
at_exit {
|
50
|
-
SuperModel::
|
51
|
-
}
|
51
|
+
SuperModel::Marshal.dump
|
52
|
+
}
|
53
|
+
|
54
|
+
You can use Redis, you need the Redis gem installed:
|
55
|
+
|
56
|
+
require "redis"
|
57
|
+
class Test < SuperModel::Redis
|
58
|
+
attributes :name
|
59
|
+
indexes :name
|
60
|
+
end
|
61
|
+
|
62
|
+
Test.find_or_create_by_name("foo")
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.6
|
data/lib/supermodel/base.rb
CHANGED
@@ -57,7 +57,7 @@ module SuperModel
|
|
57
57
|
# Removes all records and executes
|
58
58
|
# destory callbacks.
|
59
59
|
def destroy_all
|
60
|
-
|
60
|
+
all.each {|r| r.destroy }
|
61
61
|
end
|
62
62
|
|
63
63
|
# Removes all records without executing
|
@@ -74,13 +74,17 @@ module SuperModel
|
|
74
74
|
rec.save && rec
|
75
75
|
end
|
76
76
|
|
77
|
+
def find_by_attribute(name, value) #:nodoc:
|
78
|
+
records.find {|r| r.name == value }
|
79
|
+
end
|
80
|
+
|
77
81
|
def method_missing(method_symbol, *args) #:nodoc:
|
78
82
|
method_name = method_symbol.to_s
|
79
83
|
|
80
84
|
if method_name =~ /^find_by_(\w+)!/
|
81
85
|
send("find_by_#{$1}", *args) || raise(UnknownRecord)
|
82
86
|
elsif method_name =~ /^find_by_(\w+)/
|
83
|
-
|
87
|
+
find_by_attribute($1, args.first)
|
84
88
|
elsif method_name =~ /^find_or_create_by_(\w+)/
|
85
89
|
send("find_by_#{$1}", *args) || create($1 => args.first)
|
86
90
|
else
|
@@ -156,7 +160,9 @@ module SuperModel
|
|
156
160
|
end
|
157
161
|
|
158
162
|
def load(attributes) #:nodoc:
|
159
|
-
|
163
|
+
attributes.each {|(name, value)|
|
164
|
+
self.send("#{name}=".to_sym, value)
|
165
|
+
}
|
160
166
|
end
|
161
167
|
|
162
168
|
def update_attribute(name, value)
|
@@ -2,7 +2,7 @@ require "tempfile"
|
|
2
2
|
require "fileutils"
|
3
3
|
|
4
4
|
module SuperModel
|
5
|
-
module
|
5
|
+
module Marshal
|
6
6
|
def path
|
7
7
|
@path || raise("Provide a path")
|
8
8
|
end
|
@@ -20,7 +20,7 @@ module SuperModel
|
|
20
20
|
return unless File.exist?(path)
|
21
21
|
records = []
|
22
22
|
File.open(path, "rb") {|file|
|
23
|
-
records = Marshal.load(file)
|
23
|
+
records = ::Marshal.load(file)
|
24
24
|
}
|
25
25
|
records.each {|r| r.class.records << r }
|
26
26
|
true
|
@@ -31,7 +31,7 @@ module SuperModel
|
|
31
31
|
tmp_file = Tempfile.new("rbdump")
|
32
32
|
tmp_file.binmode
|
33
33
|
records = klasses.map {|k| k.records }.flatten
|
34
|
-
Marshal.dump(records, tmp_file)
|
34
|
+
::Marshal.dump(records, tmp_file)
|
35
35
|
# Atomic serialization - so we never corrupt the db
|
36
36
|
FileUtils.mv(tmp_file.path, path)
|
37
37
|
true
|
@@ -41,7 +41,7 @@ module SuperModel
|
|
41
41
|
|
42
42
|
module Model
|
43
43
|
def self.included(base)
|
44
|
-
|
44
|
+
Marshal.klasses << base
|
45
45
|
end
|
46
46
|
|
47
47
|
def marshal_dump
|
@@ -0,0 +1,162 @@
|
|
1
|
+
module SuperModel
|
2
|
+
class Redis < Base
|
3
|
+
class << self
|
4
|
+
def redis
|
5
|
+
@redis ||= ::Redis.new
|
6
|
+
end
|
7
|
+
|
8
|
+
def indexes(*indexes)
|
9
|
+
@known_indexes = indexes.map(&:to_s)
|
10
|
+
end
|
11
|
+
|
12
|
+
def known_indexes
|
13
|
+
@known_indexes ||= []
|
14
|
+
end
|
15
|
+
|
16
|
+
def serialize(*attributes)
|
17
|
+
@serialized_attributes = attributes.map(&:to_s)
|
18
|
+
end
|
19
|
+
|
20
|
+
def serialized_attributes
|
21
|
+
@serialized_attributes ||= []
|
22
|
+
end
|
23
|
+
|
24
|
+
def redis_key(*args)
|
25
|
+
args.unshift(self.name.downcase)
|
26
|
+
args.join(":")
|
27
|
+
end
|
28
|
+
|
29
|
+
def find(id)
|
30
|
+
if redis.set_member?(redis_key, id)
|
31
|
+
res = self.new(:id => id)
|
32
|
+
res.redis_get
|
33
|
+
res
|
34
|
+
else
|
35
|
+
raise(UnknownRecord)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def first
|
40
|
+
all.first
|
41
|
+
end
|
42
|
+
|
43
|
+
def last
|
44
|
+
all.last
|
45
|
+
end
|
46
|
+
|
47
|
+
def count
|
48
|
+
redis.set_count(redis_key)
|
49
|
+
end
|
50
|
+
|
51
|
+
def all
|
52
|
+
from_ids(redis.set_members(redis_key))
|
53
|
+
end
|
54
|
+
|
55
|
+
def delete_all
|
56
|
+
raise "Not implemented"
|
57
|
+
end
|
58
|
+
|
59
|
+
def find_by_attribute(key, value)
|
60
|
+
item_ids = redis.set_members(redis_key(key, value))
|
61
|
+
return if item_ids.empty?
|
62
|
+
res = self.new(:id => item_ids.first)
|
63
|
+
res.redis_get
|
64
|
+
res
|
65
|
+
end
|
66
|
+
|
67
|
+
protected
|
68
|
+
def from_ids(ids)
|
69
|
+
ids.map do |id|
|
70
|
+
res = self.new(:id => id)
|
71
|
+
res.redis_get
|
72
|
+
res
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def destroy
|
78
|
+
return if new?
|
79
|
+
|
80
|
+
destroy_indexes
|
81
|
+
redis.set_delete(self.class.redis_key, self.id)
|
82
|
+
|
83
|
+
attributes.keys.each do |key|
|
84
|
+
redis.delete(redis_key(key))
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
protected
|
89
|
+
def destroy_indexes
|
90
|
+
known_indexes.each do |index|
|
91
|
+
old_attribute = changes[index].try(:first) || send(index)
|
92
|
+
redis.set_delete(self.class.redis_key(index, old_attribute), id)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def create_indexes
|
97
|
+
known_indexes.each do |index|
|
98
|
+
new_attribute = send(index)
|
99
|
+
redis.set_add(self.class.redis_key(index, new_attribute), id)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def generate_id
|
104
|
+
redis.incr(self.class.redis_key(:uid))
|
105
|
+
end
|
106
|
+
|
107
|
+
def known_indexes
|
108
|
+
attributes.keys & self.class.known_indexes
|
109
|
+
end
|
110
|
+
|
111
|
+
def redis
|
112
|
+
self.class.redis
|
113
|
+
end
|
114
|
+
|
115
|
+
def redis_key(*args)
|
116
|
+
self.class.redis_key(id, *args)
|
117
|
+
end
|
118
|
+
|
119
|
+
def serialized_attributes
|
120
|
+
self.class.serialized_attributes
|
121
|
+
end
|
122
|
+
|
123
|
+
def serialize_attribute(key, value)
|
124
|
+
return value unless serialized_attributes.include?(key)
|
125
|
+
value.to_json
|
126
|
+
end
|
127
|
+
|
128
|
+
def deserialize_attribute(key, value)
|
129
|
+
return value unless serialized_attributes.include?(key)
|
130
|
+
JSON.parse(value)
|
131
|
+
end
|
132
|
+
|
133
|
+
def redis_set
|
134
|
+
attributes.each do |(key, value)|
|
135
|
+
redis.set(redis_key(key), serialize_attribute(key, value))
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def redis_get
|
140
|
+
known_attributes.each do |key|
|
141
|
+
result = deserialize_attribute(key, redis.get(redis_key(key)))
|
142
|
+
send("#{key}=", result)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
public :redis_get
|
146
|
+
|
147
|
+
def create
|
148
|
+
self.id ||= generate_id
|
149
|
+
redis_set
|
150
|
+
create_indexes
|
151
|
+
redis.set_add(self.class.redis_key, self.id)
|
152
|
+
save_previous_changes
|
153
|
+
end
|
154
|
+
|
155
|
+
def update
|
156
|
+
destroy_indexes
|
157
|
+
redis_set
|
158
|
+
create_indexes
|
159
|
+
save_previous_changes
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
data/lib/supermodel/scriber.rb
CHANGED
data/lib/supermodel.rb
CHANGED
@@ -22,12 +22,13 @@ module SuperModel
|
|
22
22
|
class InvalidRecord < SuperModelError; end
|
23
23
|
end
|
24
24
|
|
25
|
-
|
25
|
+
$:.unshift(File.dirname(__FILE__))
|
26
26
|
|
27
27
|
require "supermodel/callbacks"
|
28
28
|
require "supermodel/observing"
|
29
|
-
require "supermodel/
|
29
|
+
require "supermodel/marshal"
|
30
30
|
require "supermodel/random_id"
|
31
31
|
require "supermodel/scriber"
|
32
32
|
require "supermodel/validations"
|
33
|
-
require "supermodel/base"
|
33
|
+
require "supermodel/base"
|
34
|
+
require "supermodel/redis"
|
data/supermodel.gemspec
CHANGED
@@ -5,7 +5,7 @@
|
|
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.6"
|
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"]
|
@@ -24,9 +24,10 @@ Gem::Specification.new do |s|
|
|
24
24
|
"lib/supermodel.rb",
|
25
25
|
"lib/supermodel/base.rb",
|
26
26
|
"lib/supermodel/callbacks.rb",
|
27
|
+
"lib/supermodel/marshal.rb",
|
27
28
|
"lib/supermodel/observing.rb",
|
28
|
-
"lib/supermodel/persist.rb",
|
29
29
|
"lib/supermodel/random_id.rb",
|
30
|
+
"lib/supermodel/redis.rb",
|
30
31
|
"lib/supermodel/scriber.rb",
|
31
32
|
"lib/supermodel/validations.rb",
|
32
33
|
"supermodel.gemspec"
|
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.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alex MacCaw
|
@@ -39,9 +39,10 @@ files:
|
|
39
39
|
- lib/supermodel.rb
|
40
40
|
- lib/supermodel/base.rb
|
41
41
|
- lib/supermodel/callbacks.rb
|
42
|
+
- lib/supermodel/marshal.rb
|
42
43
|
- lib/supermodel/observing.rb
|
43
|
-
- lib/supermodel/persist.rb
|
44
44
|
- lib/supermodel/random_id.rb
|
45
|
+
- lib/supermodel/redis.rb
|
45
46
|
- lib/supermodel/scriber.rb
|
46
47
|
- lib/supermodel/validations.rb
|
47
48
|
- supermodel.gemspec
|