redis_object 1.0 → 1.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/.coveralls.yml +1 -0
- data/.gitignore +2 -0
- data/.travis.yml +5 -0
- data/Gemfile +4 -0
- data/README.markdown +24 -15
- data/Rakefile +8 -0
- data/lib/redis_object.rb +11 -1
- data/lib/redis_object/base.rb +210 -60
- data/lib/redis_object/collection.rb +130 -100
- data/lib/redis_object/defaults.rb +21 -8
- data/lib/redis_object/{history.rb → experimental/history.rb} +0 -0
- data/lib/redis_object/ext/filters.rb +34 -16
- data/lib/redis_object/ext/script_cache.rb +92 -0
- data/lib/redis_object/ext/shardable.rb +18 -0
- data/lib/redis_object/ext/triggers.rb +75 -13
- data/lib/redis_object/ext/view_caching.rb +258 -0
- data/lib/redis_object/ext/views.rb +102 -0
- data/lib/redis_object/indices.rb +44 -39
- data/lib/redis_object/inheritance_tracking.rb +23 -0
- data/lib/redis_object/keys.rb +4 -4
- data/lib/redis_object/storage.rb +30 -1
- data/lib/redis_object/storage/adapter.rb +6 -3
- data/lib/redis_object/storage/redis.rb +98 -3
- data/lib/redis_object/timestamps.rb +42 -21
- data/lib/redis_object/types.rb +172 -30
- data/lib/redis_object/version.rb +1 -1
- data/redis_object.gemspec +1 -0
- data/spec/adapter_spec.rb +43 -0
- data/spec/base_spec.rb +41 -6
- data/spec/benchmark_spec.rb +46 -0
- data/spec/collections_spec.rb +144 -0
- data/spec/defaults_spec.rb +56 -0
- data/spec/filters_spec.rb +29 -0
- data/spec/indices_spec.rb +45 -0
- data/spec/rename_class_spec.rb +96 -0
- data/spec/spec_helper.rb +32 -1
- data/spec/timestamp_spec.rb +28 -0
- data/spec/trigger_spec.rb +51 -0
- data/spec/types_spec.rb +103 -0
- data/spec/view_caching_spec.rb +130 -0
- data/spec/views_spec.rb +72 -0
- metadata +111 -116
- data/doc/Object.html +0 -185
- data/doc/Seabright.html +0 -181
- data/doc/Seabright/Adapter.html +0 -442
- data/doc/Seabright/Collection.html +0 -797
- data/doc/Seabright/Collections.html +0 -635
- data/doc/Seabright/Collections/ClassMethods.html +0 -212
- data/doc/Seabright/ExternalIndex.html +0 -217
- data/doc/Seabright/History.html +0 -382
- data/doc/Seabright/History/ClassMethods.html +0 -276
- data/doc/Seabright/Indices.html +0 -324
- data/doc/Seabright/Indices/ClassMethods.html +0 -348
- data/doc/Seabright/Keys.html +0 -314
- data/doc/Seabright/Keys/ClassMethods.html +0 -276
- data/doc/Seabright/ObjectBase.html +0 -852
- data/doc/Seabright/ObjectBase/ClassMethods.html +0 -677
- data/doc/Seabright/RedisObject.html +0 -230
- data/doc/Seabright/References.html +0 -280
- data/doc/Seabright/Storage.html +0 -252
- data/doc/Seabright/Storage/ClassMethods.html +0 -276
- data/doc/Seabright/Storage/MySQL.html +0 -442
- data/doc/Seabright/Storage/Redis.html +0 -218
- data/doc/Seabright/Template.html +0 -212
- data/doc/Seabright/Template/ClassMethods.html +0 -166
- data/doc/Seabright/Timestamps.html +0 -292
- data/doc/Seabright/Timestamps/ClassMethods.html +0 -214
- data/doc/Seabright/Types.html +0 -410
- data/doc/Seabright/Types/ClassMethods.html +0 -308
- data/doc/created.rid +0 -17
- data/doc/images/add.png +0 -0
- data/doc/images/brick.png +0 -0
- data/doc/images/brick_link.png +0 -0
- data/doc/images/bug.png +0 -0
- data/doc/images/bullet_black.png +0 -0
- data/doc/images/bullet_toggle_minus.png +0 -0
- data/doc/images/bullet_toggle_plus.png +0 -0
- data/doc/images/date.png +0 -0
- data/doc/images/delete.png +0 -0
- data/doc/images/find.png +0 -0
- data/doc/images/loadingAnimation.gif +0 -0
- data/doc/images/macFFBgHack.png +0 -0
- data/doc/images/package.png +0 -0
- data/doc/images/page_green.png +0 -0
- data/doc/images/page_white_text.png +0 -0
- data/doc/images/page_white_width.png +0 -0
- data/doc/images/plugin.png +0 -0
- data/doc/images/ruby.png +0 -0
- data/doc/images/tag_blue.png +0 -0
- data/doc/images/tag_green.png +0 -0
- data/doc/images/transparent.png +0 -0
- data/doc/images/wrench.png +0 -0
- data/doc/images/wrench_orange.png +0 -0
- data/doc/images/zoom.png +0 -0
- data/doc/index.html +0 -125
- data/doc/js/darkfish.js +0 -153
- data/doc/js/jquery.js +0 -18
- data/doc/js/navigation.js +0 -142
- data/doc/js/search.js +0 -94
- data/doc/js/search_index.js +0 -1
- data/doc/js/searcher.js +0 -228
- data/doc/rdoc.css +0 -543
- data/doc/table_of_contents.html +0 -394
data/.coveralls.yml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
repo_token: 8vq1j1WGB56M8h1zI6TeuK7x3HVJ1K8l4
|
data/.gitignore
CHANGED
data/.travis.yml
ADDED
data/Gemfile
CHANGED
data/README.markdown
CHANGED
@@ -1,14 +1,20 @@
|
|
1
1
|
# RedisObject
|
2
2
|
RedisObject is a fast and simple-to-use object persistence layer for Ruby.
|
3
3
|
|
4
|
+
[](https://travis-ci.org/remotezygote/RedisObject)
|
5
|
+
[](https://coveralls.io/r/remotezygote/RedisObject?branch=master)
|
6
|
+
|
4
7
|
## Prerequisites
|
5
|
-
You'll need [Redis](http://redis.io).
|
8
|
+
You'll need [Redis](http://redis.io). Other storage adapters are in the works. Maybe.
|
6
9
|
|
7
10
|
|
8
11
|
## Installation
|
9
|
-
It's hosted on [rubygems.org][rubygems].
|
10
12
|
|
11
|
-
|
13
|
+
gem install redis_object
|
14
|
+
|
15
|
+
Or, you can add it to your Gemfile:
|
16
|
+
|
17
|
+
gem 'redis_object'
|
12
18
|
|
13
19
|
|
14
20
|
## Usage
|
@@ -51,7 +57,7 @@ end
|
|
51
57
|
## 'Collections'
|
52
58
|
Object relationships are stored in collections of objects attached to other objects. To 'collect' an object onto another, you simply call `reference` to reference the objects (also aliased to the concat operator `<<`).
|
53
59
|
|
54
|
-
Collections are automatically created, and can be access by their plural, lower-case name to gather all of the items in a collection (returns
|
60
|
+
Collections are automatically created, and can be access by their plural, lower-case name to gather all of the items in a collection (returns an Enumerable `Collection` object), or by its singular lower-case name to just get one somewhat randomly (useful for 1 -> 1 style relationships).
|
55
61
|
|
56
62
|
Example:
|
57
63
|
|
@@ -82,19 +88,19 @@ john.address
|
|
82
88
|
# }
|
83
89
|
```
|
84
90
|
|
85
|
-
You may
|
91
|
+
You may notice that the type of object, its basic storage key, and some timestamps are automatically created and updated appropriately.
|
86
92
|
|
87
93
|
It is important to note that collections inherit any indices of its underlying object type. See Indices below for examples.
|
88
94
|
|
89
95
|
## Types
|
90
96
|
A few types of data can be specified for certain fields. The types supported are:
|
91
97
|
|
92
|
-
Date
|
93
|
-
Number
|
94
|
-
Float
|
95
|
-
Bool
|
96
|
-
Array
|
97
|
-
JSON (store any data that can be JSON-encoded - it will be automatically encoded/decoded when stored/accessed)
|
98
|
+
* Date
|
99
|
+
* Number
|
100
|
+
* Float
|
101
|
+
* Bool
|
102
|
+
* Array
|
103
|
+
* JSON (store any data that can be JSON-encoded - it will be automatically encoded/decoded when stored/accessed)
|
98
104
|
|
99
105
|
These types are also used for scoring when keeping field indices. If no type is specified, String is used, and no scoring is possible at this time.
|
100
106
|
|
@@ -113,7 +119,7 @@ john.verified # false
|
|
113
119
|
|
114
120
|
TODO: Add verified? and verified! -style methods automagically for boolean fields.
|
115
121
|
|
116
|
-
You can
|
122
|
+
You can add your own custom types by defining filter methods for getting and setting a field, and can define a scoring function if you would like to index fields of your type.
|
117
123
|
|
118
124
|
Example:
|
119
125
|
|
@@ -148,7 +154,7 @@ end
|
|
148
154
|
TODO: Make defining custom formats easier - no need to define class methods for this - could have helper function for it like `custom_format :bool, :get => :format_boolean` or similar.
|
149
155
|
|
150
156
|
## Indices
|
151
|
-
Any field that can be scored can store a sidecar index by that score. These indices can
|
157
|
+
Any field that can be scored can store a sidecar index by that score. These indices can be used to index items in a collection (internally, it is a simple Redis set intersection, so it is very fast). Timestamps are indexed by default for any object, so out of the box you can do:
|
152
158
|
|
153
159
|
```ruby
|
154
160
|
Person.indexed(:created_at) # all Person objects, oldest first
|
@@ -160,11 +166,14 @@ Person.indexed(:updated_at, -1, true) do |person|
|
|
160
166
|
end
|
161
167
|
```
|
162
168
|
|
163
|
-
Accessing indexed items always returns an Enumerator, so first/last/each/count/etc. are
|
169
|
+
Accessing indexed items always returns an Enumerator, so first/last/each/count/etc. are usable anywhere and will access objects only when iterated.
|
170
|
+
|
171
|
+
## Named Views
|
172
|
+
`TODO: Add some damn View documentation.`
|
164
173
|
|
165
174
|
## Links
|
166
175
|
Redis: [http://redis.io](http://redis.io)
|
167
176
|
RedisObject Code: [https://github.com/remotezygote/RedisObject](https://github.com/remotezygote/RedisObject)
|
168
177
|
|
169
178
|
|
170
|
-
[rubygems]: http://rubygems.org/gems/redis_object
|
179
|
+
[rubygems]: http://rubygems.org/gems/redis_object
|
data/Rakefile
CHANGED
data/lib/redis_object.rb
CHANGED
@@ -4,7 +4,9 @@ require 'yajl'
|
|
4
4
|
|
5
5
|
require "redis_object/storage"
|
6
6
|
|
7
|
+
require "redis_object/ext/script_cache"
|
7
8
|
require "redis_object/base"
|
9
|
+
require "redis_object/inheritance_tracking"
|
8
10
|
require "redis_object/storage"
|
9
11
|
require "redis_object/keys"
|
10
12
|
require "redis_object/types"
|
@@ -12,20 +14,28 @@ require "redis_object/defaults"
|
|
12
14
|
require "redis_object/collection"
|
13
15
|
require "redis_object/indices"
|
14
16
|
require "redis_object/timestamps"
|
15
|
-
require "redis_object/history"
|
17
|
+
require "redis_object/experimental/history"
|
18
|
+
require "redis_object/ext/views"
|
19
|
+
require "redis_object/ext/view_caching"
|
16
20
|
require "redis_object/ext/triggers"
|
21
|
+
require "redis_object/ext/filters"
|
17
22
|
require "redis_object/ext/benchmark"
|
18
23
|
|
19
24
|
module Seabright
|
20
25
|
class RedisObject
|
21
26
|
|
27
|
+
include Seabright::Filters
|
22
28
|
include Seabright::ObjectBase
|
29
|
+
include Seabright::InheritanceTracking
|
30
|
+
include Seabright::CachedScripts
|
23
31
|
include Seabright::Storage
|
24
32
|
include Seabright::Keys
|
25
33
|
include Seabright::Types
|
26
34
|
include Seabright::DefaultValues
|
27
35
|
include Seabright::Collections
|
28
36
|
include Seabright::Indices
|
37
|
+
include Seabright::Views
|
38
|
+
include Seabright::ViewCaching
|
29
39
|
include Seabright::Timestamps
|
30
40
|
include Seabright::History
|
31
41
|
include Seabright::Triggers
|
data/lib/redis_object/base.rb
CHANGED
@@ -3,11 +3,11 @@ module Seabright
|
|
3
3
|
|
4
4
|
def initialize(ident={})
|
5
5
|
if ident && (ident.class == String || (ident.class == Symbol && (ident = ident.to_s)))# && ident.gsub!(/.*:/,'') && ident.length > 0
|
6
|
-
load(ident)
|
6
|
+
load(ident.dup)
|
7
7
|
elsif ident && ident.class == Hash
|
8
8
|
ident[id_sym] ||= generate_id
|
9
9
|
if load(ident[id_sym])
|
10
|
-
mset(ident)
|
10
|
+
mset(ident.dup)
|
11
11
|
end
|
12
12
|
end
|
13
13
|
self
|
@@ -18,33 +18,17 @@ module Seabright
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def generate_id
|
21
|
-
|
22
|
-
while self.class.exists?(v) do
|
23
|
-
puts "[RedisObject] Collision at id: #{v}" if Debug.verbose?
|
24
|
-
v = new_id
|
25
|
-
end
|
26
|
-
puts "[RedisObject] Reserving key: #{v}" if Debug.verbose?
|
27
|
-
reserve(v)
|
28
|
-
v
|
21
|
+
self.class.generate_id
|
29
22
|
end
|
30
23
|
|
31
24
|
def reserve(k)
|
32
|
-
|
25
|
+
self.class.reserve(k)
|
33
26
|
end
|
34
27
|
|
35
28
|
def to_json
|
36
29
|
Yajl::Encoder.encode(actual)
|
37
30
|
end
|
38
31
|
|
39
|
-
def dump
|
40
|
-
require "utf8_utils"
|
41
|
-
out = ["puts \"Creating: #{id}\""]
|
42
|
-
s_id = id.gsub(/\W/,"_")
|
43
|
-
out << "a#{s_id} = #{self.class.cname}.new(#{actual.to_s.tidy_bytes})"
|
44
|
-
out << "a#{s_id}.save"
|
45
|
-
out.join("\n")
|
46
|
-
end
|
47
|
-
|
48
32
|
def id
|
49
33
|
@id || get(id_sym) || set(id_sym, generate_id)
|
50
34
|
end
|
@@ -58,7 +42,7 @@ module Seabright
|
|
58
42
|
set(:class, self.class.name)
|
59
43
|
set(id_sym,id.gsub(/.*:/,''))
|
60
44
|
set(:key, key)
|
61
|
-
store.sadd(self.class.
|
45
|
+
store.sadd(self.class.plname, key)
|
62
46
|
store.del(reserve_key)
|
63
47
|
end
|
64
48
|
|
@@ -79,7 +63,7 @@ module Seabright
|
|
79
63
|
def dereference_all!
|
80
64
|
|
81
65
|
end
|
82
|
-
|
66
|
+
|
83
67
|
def raw
|
84
68
|
store.hgetall(hkey).inject({}) {|acc,(k,v)| acc[k.to_sym] = enforce_format(k,v); acc }
|
85
69
|
end
|
@@ -87,74 +71,163 @@ module Seabright
|
|
87
71
|
alias_method :actual, :raw
|
88
72
|
|
89
73
|
def get(k)
|
90
|
-
|
74
|
+
cached_hash_values[k.to_s] ||= Proc.new {|key|
|
75
|
+
if v = store.hget(hkey, key.to_s)
|
76
|
+
define_setter_getter(key)
|
77
|
+
end
|
78
|
+
v
|
79
|
+
}.call(k)
|
80
|
+
end
|
81
|
+
|
82
|
+
def [](k)
|
83
|
+
get(k)
|
91
84
|
end
|
92
|
-
alias_method :[], :get
|
93
85
|
|
94
86
|
def is_set?(k)
|
95
87
|
store.hexists(hkey, k.to_s)
|
96
88
|
end
|
97
89
|
|
98
90
|
def mset(dat)
|
99
|
-
# dat.each do |k,v|
|
100
|
-
# set(k,v)
|
101
|
-
# end
|
102
91
|
store.hmset(hkey, *(dat.inject([]){|acc,(k,v)| acc + [k,v] }))
|
92
|
+
cached_hash_values.merge!(dat)
|
93
|
+
dat.each do |k,v|
|
94
|
+
define_setter_getter(k)
|
95
|
+
end
|
103
96
|
dat
|
104
97
|
end
|
105
98
|
|
99
|
+
def define_setter_getter(key)
|
100
|
+
define_access(key) do
|
101
|
+
get(key)
|
102
|
+
end
|
103
|
+
define_access("#{key.to_s}=") do |val|
|
104
|
+
set(key,val)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def undefine_setter_getter(key)
|
109
|
+
undefine_access(key)
|
110
|
+
undefine_access("#{key.to_s}=")
|
111
|
+
end
|
112
|
+
|
106
113
|
def set(k,v)
|
107
|
-
store.hset(hkey, k.to_s
|
114
|
+
store.hset(hkey, k.to_s, v.to_s)
|
115
|
+
cached_hash_values[k.to_s] = v
|
116
|
+
define_setter_getter(k)
|
108
117
|
v
|
109
118
|
end
|
110
|
-
alias_method :[]=, :set
|
111
119
|
|
112
|
-
def
|
113
|
-
store.
|
120
|
+
def setnx(k,v)
|
121
|
+
if success = store.hsetnx(hkey, k.to_s, v.to_s)
|
122
|
+
cached_hash_values[k.to_s] = v
|
123
|
+
define_setter_getter(k)
|
124
|
+
end
|
125
|
+
success
|
126
|
+
end
|
127
|
+
|
128
|
+
def []=(k,v)
|
129
|
+
set(k,v)
|
114
130
|
end
|
115
131
|
|
116
132
|
def unset(*k)
|
117
|
-
store.hdel(hkey
|
133
|
+
store.hdel(hkey, k.map(&:to_s))
|
134
|
+
k.each do |ky|
|
135
|
+
cached_hash_values.delete ky.to_s
|
136
|
+
undefine_setter_getter(ky)
|
137
|
+
end
|
118
138
|
end
|
119
|
-
# alias_method :delete, :unset
|
120
139
|
|
121
140
|
private
|
122
141
|
|
142
|
+
SetPattern = /=$/.freeze
|
143
|
+
|
123
144
|
def method_missing(sym, *args, &block)
|
124
|
-
|
145
|
+
super if sym == :class
|
146
|
+
if sym.to_s =~ SetPattern
|
147
|
+
return super if args.size > 1
|
148
|
+
set(sym.to_s.gsub(SetPattern,'').to_sym,*args)
|
149
|
+
else
|
150
|
+
return super if !args.empty?
|
151
|
+
get(sym)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
def id_sym(cls=self.class.cname)
|
156
|
+
"#{cls.split('::').last.downcase}_id".to_sym
|
125
157
|
end
|
126
158
|
|
127
|
-
def
|
128
|
-
|
159
|
+
def load_all_hash_values
|
160
|
+
@cached_hash_values = store.hgetall(hkey)
|
161
|
+
cached_hash_values.keys.dup.each do |key|
|
162
|
+
next if key == "class"
|
163
|
+
define_setter_getter(key)
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
def cached_hash_values
|
168
|
+
@cached_hash_values ||= {}
|
169
|
+
end
|
170
|
+
|
171
|
+
def define_access(key,&block)
|
172
|
+
return if self.respond_to?(key.to_sym)
|
173
|
+
metaclass = class << self; self; end
|
174
|
+
metaclass.send(:define_method, key.to_sym, &block)
|
175
|
+
end
|
176
|
+
|
177
|
+
def undefine_access(key)
|
178
|
+
return unless self.respond_to?(key.to_sym)
|
179
|
+
metaclass = class << self; self; end
|
180
|
+
metaclass.send(:remove_method, key.to_sym)
|
129
181
|
end
|
130
182
|
|
131
183
|
module ClassMethods
|
132
184
|
|
185
|
+
def generate_id
|
186
|
+
v = new_id
|
187
|
+
while exists?(v) do
|
188
|
+
puts "[RedisObject] Collision at id: #{v}" if Debug.verbose?
|
189
|
+
v = new_id
|
190
|
+
end
|
191
|
+
puts "[RedisObject] Reserving key: #{v}" if Debug.verbose?
|
192
|
+
reserve(v)
|
193
|
+
v
|
194
|
+
end
|
195
|
+
|
196
|
+
def reserve(k)
|
197
|
+
store.set(reserve_key(k),Time.now.to_s)
|
198
|
+
end
|
199
|
+
|
133
200
|
def new_id(complexity = 8)
|
134
201
|
rand(36**complexity).to_s(36)
|
135
202
|
end
|
136
203
|
|
137
204
|
def cname
|
138
|
-
|
205
|
+
self.name
|
139
206
|
end
|
140
207
|
|
141
208
|
def plname
|
142
|
-
|
209
|
+
cname.pluralize
|
143
210
|
end
|
144
211
|
|
145
212
|
def all
|
146
213
|
Enumerator.new do |y|
|
147
214
|
store.smembers(plname).each do |member|
|
148
|
-
if a =
|
215
|
+
if a = find_by_key(hkey(member))
|
149
216
|
y << a
|
150
217
|
else
|
151
218
|
puts "[#{name}] Object listed but not found: #{member}" if DEBUG
|
152
|
-
|
219
|
+
store.srem(plname,member)
|
153
220
|
end
|
154
221
|
end
|
155
222
|
end
|
156
223
|
end
|
157
224
|
|
225
|
+
def recollect!
|
226
|
+
store.keys("#{name}:*_h").each do |ky|
|
227
|
+
store.sadd(plname,ky.gsub(/_h$/,''))
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
158
231
|
def first
|
159
232
|
if m = store.smembers(plname)
|
160
233
|
self.grab(m.first)
|
@@ -169,25 +242,95 @@ module Seabright
|
|
169
242
|
end
|
170
243
|
end
|
171
244
|
|
245
|
+
RedisObject::ScriptSources::Matcher = "local itms = redis.call('SMEMBERS',KEYS[1])
|
246
|
+
local out = {}
|
247
|
+
local val
|
248
|
+
local pattern
|
249
|
+
for i, v in ipairs(itms) do
|
250
|
+
val = redis.call('HGET',v..'_h',ARGV[1])
|
251
|
+
if ARGV[2]:find('^pattern:') then
|
252
|
+
pattern = ARGV[2]:gsub('^pattern:','')
|
253
|
+
if val:match(pattern) ~= nil then
|
254
|
+
table.insert(out,itms[i])
|
255
|
+
end
|
256
|
+
else
|
257
|
+
if val == ARGV[2] then
|
258
|
+
table.insert(out,itms[i])
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end
|
262
|
+
return out".gsub(/\t/,'').freeze
|
263
|
+
|
264
|
+
RedisObject::ScriptSources::MultiMatcher = "local itms = redis.call('SMEMBERS',KEYS[1])
|
265
|
+
local out = {}
|
266
|
+
local matchers = {}
|
267
|
+
local matcher = {}
|
268
|
+
local mod
|
269
|
+
for i=1,#ARGV do
|
270
|
+
mod = i % 2
|
271
|
+
if mod == 1 then
|
272
|
+
matcher[1] = ARGV[i]
|
273
|
+
else
|
274
|
+
matcher[2] = ARGV[i]
|
275
|
+
table.insert(matchers,matcher)
|
276
|
+
matcher = {}
|
277
|
+
end
|
278
|
+
end
|
279
|
+
local val
|
280
|
+
local good
|
281
|
+
local pattern
|
282
|
+
for i, v in ipairs(itms) do
|
283
|
+
good = true
|
284
|
+
for n=1,#matchers do
|
285
|
+
val = redis.call('HGET',v..'_h',matchers[n][1])
|
286
|
+
if val then
|
287
|
+
if matchers[n][2]:find('^pattern:') then
|
288
|
+
pattern = matchers[n][2]:gsub('^pattern:','')
|
289
|
+
if val:match(pattern) then
|
290
|
+
good = good
|
291
|
+
else
|
292
|
+
good = false
|
293
|
+
end
|
294
|
+
else
|
295
|
+
if val ~= matchers[n][2] then
|
296
|
+
good = false
|
297
|
+
end
|
298
|
+
end
|
299
|
+
else
|
300
|
+
good = false
|
301
|
+
end
|
302
|
+
end
|
303
|
+
if good == true then
|
304
|
+
table.insert(out,itms[i])
|
305
|
+
end
|
306
|
+
end
|
307
|
+
return out".gsub(/\t/,'').freeze
|
308
|
+
|
172
309
|
def match(pkt)
|
173
310
|
Enumerator.new do |y|
|
174
|
-
each do |
|
175
|
-
|
176
|
-
y << i
|
177
|
-
end
|
311
|
+
run_script(pkt.keys.count > 1 ? :MultiMatcher : :Matcher,[plname],pkt.flatten.map{|i| i.is_a?(Regexp) ? convert_regex_to_lua(i) : i.to_s }).each do |k|
|
312
|
+
y << find(k)
|
178
313
|
end
|
179
314
|
end
|
180
315
|
end
|
181
316
|
|
317
|
+
def convert_regex_to_lua(reg)
|
318
|
+
"pattern:#{reg.source.gsub("\\","")}"
|
319
|
+
end
|
320
|
+
|
182
321
|
def grab(ident)
|
183
|
-
|
184
|
-
|
185
|
-
|
322
|
+
case ident
|
323
|
+
when String, Symbol
|
324
|
+
return store.exists(self.hkey(ident.to_s)) ? self.new(ident.to_s) : nil
|
325
|
+
when Hash
|
186
326
|
return match(ident)
|
187
327
|
end
|
188
328
|
nil
|
189
329
|
end
|
190
|
-
|
330
|
+
|
331
|
+
def find(ident)
|
332
|
+
grab(ident)
|
333
|
+
end
|
191
334
|
|
192
335
|
def exists?(k)
|
193
336
|
store.exists(self.hkey(k)) || store.exists(self.reserve_key(k))
|
@@ -199,13 +342,13 @@ module Seabright
|
|
199
342
|
obj
|
200
343
|
end
|
201
344
|
|
202
|
-
def dump
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
end
|
345
|
+
# def dump
|
346
|
+
# out = []
|
347
|
+
# each do |obj|
|
348
|
+
# out << obj.dump
|
349
|
+
# end
|
350
|
+
# out.join("\n")
|
351
|
+
# end
|
209
352
|
|
210
353
|
def use_dbnum(db=0)
|
211
354
|
@dbnum = db
|
@@ -217,8 +360,7 @@ module Seabright
|
|
217
360
|
|
218
361
|
def find_by_key(k)
|
219
362
|
if store.exists(k) && (cls = store.hget(k,:class))
|
220
|
-
|
221
|
-
return deep_const_get(cls.to_sym).new(o_id)
|
363
|
+
return deep_const_get(cls.to_sym).new(store.hget(k,id_sym(cls)))
|
222
364
|
end
|
223
365
|
nil
|
224
366
|
end
|
@@ -244,8 +386,16 @@ module Seabright
|
|
244
386
|
true
|
245
387
|
end
|
246
388
|
|
247
|
-
def id_sym(cls=
|
248
|
-
"#{
|
389
|
+
def id_sym(cls=cname)
|
390
|
+
"#{cls.split('::').last.downcase}_id".to_sym
|
391
|
+
end
|
392
|
+
|
393
|
+
def describe
|
394
|
+
all_keys.inject({}) do |acc,(k,v)|
|
395
|
+
acc[k.to_sym] ||= [:string, 0]
|
396
|
+
acc[k.to_sym][1] += 1
|
397
|
+
acc
|
398
|
+
end
|
249
399
|
end
|
250
400
|
|
251
401
|
end
|
@@ -255,4 +405,4 @@ module Seabright
|
|
255
405
|
end
|
256
406
|
|
257
407
|
end
|
258
|
-
end
|
408
|
+
end
|