acts_as_hashish 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,6 +2,7 @@ require 'redis'
2
2
  require 'json'
3
3
  require 'timeout'
4
4
  require 'acts_as_hashish'
5
+ require 'acts_as_hashish/private_class_methods'
5
6
  require 'acts_as_hashish/version'
6
7
  require 'acts_as_hashish/configuration'
7
8
  require 'acts_as_hashish/hashish'
@@ -9,68 +9,25 @@ module Hashish
9
9
 
10
10
  @options = options
11
11
  extend ClassMethods
12
+ extend PrivateClassMethods
12
13
  end
13
14
 
14
15
  module ClassMethods
15
-
16
- private
17
- def get_hashish_key(item)
18
- key = @options[:key]
19
- key_value = key.is_a?(Proc) ? key.call(item) : item[key]
20
- end
21
16
 
22
- def remove_hashish_metadata(key)
23
- prefix = @options[:key_prefix]
24
- Hashish.redis_connection.smembers("#{prefix}#INDEXES").each do |member|
25
- Hashish.redis_connection.zrem(member, "#{prefix}@#{key}")
26
- Hashish.redis_connection.srem("#{prefix}#INDEXES", member) if Hashish.redis_connection.zcard(member) == 0
17
+ def hashish_rebuild(data = nil)
18
+ hashish_wait_on_lock do
19
+ data ||= hashish_list(:page_size => 0)
20
+ hashish_flush!
27
21
  end
28
- Hashish.redis_connection.smembers("#{prefix}#SORTERS").each do |member|
29
- if member =~ /^#{prefix}\$[\w]+@#{key}$/
30
- Hashish.redis_connection.del(member)
31
- Hashish.redis_connection.srem("#{prefix}#SORTERS", member)
32
- end
33
- end
34
- end
35
-
36
- def add_hashish_metadata(name, category)
37
- prefix = @options[:key_prefix]
38
- Hashish.redis_connection.sadd("#{prefix}##{category}", name)
39
- end
40
-
41
- def redis_keys
42
- Hashish.redis_connection.keys("#{@options[:key_prefix]}*").inject({}){|h,x| h[x] = Hashish.redis_connection.type(x);h}
43
- end
44
-
45
- def wait_on_lock(timeout = 0)
46
- lock_key = "#{@options[:key_prefix]}#MUTEX_LOCK"
47
22
  begin
48
- Timeout::timeout(timeout) do
49
- while Hashish.redis_connection.incr(lock_key) != 1
50
- sleep(1)
51
- end
52
- end
53
23
  yield if block_given?
54
24
  ensure
55
- Hashish.redis_connection.del(lock_key)
56
- end
57
- end
58
-
59
- public
60
- def hashish_rebuild
61
- temp = nil
62
- wait_on_lock do
63
- temp = hashish_list(:page_size => 0)
64
- hashish_flush!
65
- end
66
- yield if block_given?
67
- temp.each do |item|
68
- hashish_insert(item)
25
+ hashish_insert(data, Time.now.to_i)
69
26
  end
70
27
  end
71
28
 
72
29
  def hashish_flush!
73
- Hashish.redis_connection.keys("#{@options[:key_prefix]}*").each{|x| Hashish.redis_connection.del(x)}
30
+ hashish_redis_keys.each{|x| Hashish.redis_connection.del(x)}
74
31
  end
75
32
 
76
33
  def hashish_length
@@ -78,43 +35,23 @@ module Hashish
78
35
  end
79
36
 
80
37
  def hashish_delete(key = nil)
81
- key ||= get_hashish_key(hashish_list.first)
38
+ key ||= hashish_get_key(hashish_list.first)
82
39
  prefix = @options[:key_prefix]
83
40
  Hashish.redis_connection.zrem("#{prefix}*", "#{prefix}@#{key}")
84
- remove_hashish_metadata("#{key}")
41
+ hashish_remove_metadata("#{key}")
85
42
  Hashish.redis_connection.del("#{prefix}@#{key}")
86
43
  end
87
44
 
88
- def hashish_insert(o, t = Time.now.to_i)
89
- wait_on_lock do
90
- data = o.to_json
91
- prefix = @options[:key_prefix]
92
- key = get_hashish_key(o)
93
- raise "Error: Computed data key as '#{key}'. Only alphanumeric characters allowed!" unless key.to_s =~ /^[\w]+$/
94
- Hashish.redis_connection.multi do
95
- Hashish.redis_connection.zadd("#{prefix}*", t , "#{prefix}@#{key}")
96
- # Hashish.redis_connection.zremrangebyrank("#{prefix}:", 0, -(@options[:max_size] + 1)) if @options[:max_size]
97
- @options[:indexes].each do |index_field, index|
98
- index_value = index.is_a?(Proc) ? index.call(o) : o[index]
99
- if index_value.is_a?(Array)
100
- index_value.each do |i|
101
- Hashish.redis_connection.zadd("#{prefix}!#{index_field}=#{i}", t, "#{prefix}@#{key}") if i.is_a?(String)
102
- add_hashish_metadata("#{prefix}!#{index_field}=#{i}", 'INDEXES')
103
- end
104
- else
105
- Hashish.redis_connection.zadd("#{prefix}!#{index_field}=#{index_value}", t, "#{prefix}@#{key}")
106
- add_hashish_metadata("#{prefix}!#{index_field}=#{index_value}", 'INDEXES')
107
- end
108
- end
109
- @options[:sorters].each do |sort_field, sort|
110
- sort_value = sort.is_a?(Proc) ? sort.call(o) : o[sort]
111
- Hashish.redis_connection.set("#{prefix}$#{sort_field}@#{key}", sort_value)
112
- add_hashish_metadata("#{prefix}$#{sort_field}@#{key}", 'SORTERS')
113
- end
114
- Hashish.redis_connection.set("#{prefix}@#{key}", data)
45
+ def hashish_insert(data, t = Time.now.to_i)
46
+ if data.is_a?(Array)
47
+ data.each do |d|
48
+ hashish_single_insert(d, t)
115
49
  end
50
+ elsif data.is_a?(Hash)
51
+ hashish_single_insert(data, t)
52
+ else
53
+ raise "Data must be of type Hash or Array of Hash"
116
54
  end
117
- true
118
55
  end
119
56
 
120
57
  def hashish_list(options = {})
@@ -178,7 +115,7 @@ module Hashish
178
115
  result = nil
179
116
  if sort_by
180
117
  custom_sort_key = "#{@options[:key_prefix]}#CUSTOM_SORT##{seq}"
181
- Hashish.redis_connection.sort(result_key, :by => "*:#{sort_by}",:get => '*', :store => custom_sort_key, :order => sort_order)
118
+ Hashish.redis_connection.sort(result_key, :by => "*$#{sort_by}",:get => '*', :store => custom_sort_key, :order => sort_order)
182
119
  Hashish.redis_connection.expire(custom_sort_key, Hashish.redis_search_keys_ttl * 60)
183
120
  result = Hashish.redis_connection.lrange(custom_sort_key, offset, limit -1)
184
121
  else
@@ -0,0 +1,85 @@
1
+ module Hashish
2
+ module PrivateClassMethods
3
+
4
+ private
5
+ def hashish_get_key(item)
6
+ key = @options[:key]
7
+ key_value = key.is_a?(Proc) ? key.call(item) : item[key]
8
+ end
9
+
10
+ def hashish_remove_metadata(key)
11
+ prefix = @options[:key_prefix]
12
+ Hashish.redis_connection.smembers("#{prefix}#INDEXES").each do |member|
13
+ Hashish.redis_connection.zrem(member, "#{prefix}@#{key}")
14
+ Hashish.redis_connection.srem("#{prefix}#INDEXES", member) if Hashish.redis_connection.zcard(member) == 0
15
+ end
16
+ Hashish.redis_connection.smembers("#{prefix}#SORTERS").each do |member|
17
+ if member =~ /^#{prefix}@#{key}\$.+$/
18
+ Hashish.redis_connection.del(member)
19
+ Hashish.redis_connection.srem("#{prefix}#SORTERS", member)
20
+ end
21
+ end
22
+ end
23
+
24
+ def hashish_add_metadata(name, category)
25
+ prefix = @options[:key_prefix]
26
+ Hashish.redis_connection.sadd("#{prefix}##{category}", name)
27
+ end
28
+
29
+ def hashish_wait_on_lock(timeout = 0)
30
+ lock_key = "#{@options[:key_prefix]}#MUTEX_LOCK"
31
+ begin
32
+ Timeout::timeout(timeout) do
33
+ while Hashish.redis_connection.incr(lock_key) != 1
34
+ sleep(1)
35
+ end
36
+ end
37
+ yield if block_given?
38
+ ensure
39
+ Hashish.redis_connection.del(lock_key)
40
+ end
41
+ end
42
+
43
+ def hashish_redis_keys
44
+ Hashish.redis_connection.keys("#{@options[:key_prefix]}*")
45
+ end
46
+
47
+ def hashish_single_insert(o, t)
48
+ raise "Data must be of type Hash or Array of Hash" unless o.is_a?(Hash)
49
+ hashish_wait_on_lock do
50
+ data = o.to_json
51
+ prefix = @options[:key_prefix]
52
+ key = hashish_get_key(o)
53
+ raise "Error: Computed data key as '#{key}'. Only alphanumeric characters and underscore allowed!" unless key.to_s =~ /^[\w_]+$/
54
+ Hashish.redis_connection.multi do
55
+ Hashish.redis_connection.zadd("#{prefix}*", t , "#{prefix}@#{key}")
56
+ # Hashish.redis_connection.zremrangebyrank("#{prefix}:", 0, -(@options[:max_size] + 1)) if @options[:max_size]
57
+ @options[:indexes].each do |index_field, index|
58
+ index_value = index.is_a?(Proc) ? index.call(o) : o[index]
59
+ if index_value.is_a?(Array)
60
+ index_value.each do |i|
61
+ if i.is_a?(String) and !i.empty?
62
+ Hashish.redis_connection.zadd("#{prefix}!#{index_field}=#{i}", t, "#{prefix}@#{key}")
63
+ hashish_add_metadata("#{prefix}!#{index_field}=#{i}", 'INDEXES')
64
+ end
65
+ end
66
+ elsif index_value.is_a?(String) and !index_value.empty?
67
+ Hashish.redis_connection.zadd("#{prefix}!#{index_field}=#{index_value}", t, "#{prefix}@#{key}")
68
+ hashish_add_metadata("#{prefix}!#{index_field}=#{index_value}", 'INDEXES')
69
+ end
70
+ end
71
+ @options[:sorters].each do |sort_field, sort|
72
+ sort_value = sort.is_a?(Proc) ? sort.call(o) : o[sort]
73
+ if sort_value # only if there is a sort_value
74
+ Hashish.redis_connection.set("#{prefix}@#{key}$#{sort_field}", sort_value)
75
+ hashish_add_metadata("#{prefix}@#{key}$#{sort_field}", 'SORTERS')
76
+ end
77
+ end
78
+ Hashish.redis_connection.set("#{prefix}@#{key}", data)
79
+ end
80
+ end
81
+ true
82
+ end
83
+
84
+ end
85
+ end
@@ -1,3 +1,3 @@
1
1
  module Hashish
2
- VERSION = '0.3.0'
2
+ VERSION = '0.4.0'
3
3
  end
@@ -1,12 +1,13 @@
1
1
  require 'spec_helper'
2
+ require 'set'
2
3
 
3
4
  describe Hashish do
4
5
 
5
6
  before :each do
6
- @sample_data_1 = {'id' => 1, 'name' => 'Joe'}
7
- @sample_data_2 = {'id' => 3, 'name' => 'Doe'}
8
- @sample_data_3 = {'id' => 2, 'name' => 'Moe'}
9
- @sample_data_4 = {'id' => 4, 'name' => 'Loe'}
7
+ @sample_data_1 = {'id' => 1, 'name' => 'Joe', 'location' => 'Lisbon'}
8
+ @sample_data_2 = {'id' => 3, 'name' => 'Doe', 'location' => 'London'}
9
+ @sample_data_3 = {'id' => 2, 'name' => 'Moe', 'location' => 'Mumbai'}
10
+ @sample_data_4 = {'id' => 4, 'name' => 'Loe', 'location' => 'Goa'}
10
11
 
11
12
  @primary_key = 'id'
12
13
 
@@ -23,7 +24,7 @@ describe Hashish do
23
24
 
24
25
  @options = SampleClass.instance_variable_get(:@options)
25
26
  end
26
-
27
+
27
28
  describe ".acts_as_hashish" do
28
29
  it "should hashify the class" do
29
30
  @options = SampleClass.instance_variable_get(:@options)
@@ -37,18 +38,18 @@ describe Hashish do
37
38
  describe ".hashish_insert" do
38
39
  it "should insert the data into the list" do
39
40
  SampleClass.hashish_insert(@sample_data_1)
40
- Hashish.redis_connection.zscore("#{@options[:key_prefix]}*", "#{@options[:key_prefix]}@#{SampleClass.send(:get_hashish_key, @sample_data_1)}").should_not be_nil
41
+ Hashish.redis_connection.zscore("#{@options[:key_prefix]}*", "#{@options[:key_prefix]}@#{SampleClass.send(:hashish_get_key, @sample_data_1)}").should_not be_nil
41
42
  end
42
43
 
43
44
  it "should create appropriate indexes" do
44
45
  SampleClass.hashish_insert(@sample_data_1)
45
- Hashish.redis_connection.zscore("#{@options[:key_prefix]}!#{@index_name}=#{@sample_data_1[@index_value]}", "#{@options[:key_prefix]}@#{SampleClass.send(:get_hashish_key, @sample_data_1)}").should_not be_nil
46
- Hashish.redis_connection.zscore("#{@options[:key_prefix]}!#{@proc_index_name}=#{@proc_index_value.call(@sample_data_1)}", "#{@options[:key_prefix]}@#{SampleClass.send(:get_hashish_key, @sample_data_1)}").should_not be_nil
46
+ Hashish.redis_connection.zscore("#{@options[:key_prefix]}!#{@index_name}=#{@sample_data_1[@index_value]}", "#{@options[:key_prefix]}@#{SampleClass.send(:hashish_get_key, @sample_data_1)}").should_not be_nil
47
+ Hashish.redis_connection.zscore("#{@options[:key_prefix]}!#{@proc_index_name}=#{@proc_index_value.call(@sample_data_1)}", "#{@options[:key_prefix]}@#{SampleClass.send(:hashish_get_key, @sample_data_1)}").should_not be_nil
47
48
  end
48
49
 
49
50
  it "should create appropriate sorters" do
50
51
  SampleClass.hashish_insert(@sample_data_1)
51
- Hashish.redis_connection.get("#{@options[:key_prefix]}$#{@sorter_name}@#{SampleClass.send(:get_hashish_key, @sample_data_1)}").should == @sample_data_1[@sorter_value].to_s
52
+ Hashish.redis_connection.get("#{@options[:key_prefix]}@#{SampleClass.send(:hashish_get_key, @sample_data_1)}$#{@sorter_name}").should == @sample_data_1[@sorter_value].to_s
52
53
  end
53
54
  end
54
55
 
@@ -56,19 +57,108 @@ describe Hashish do
56
57
  it "should delete the data from the list" do
57
58
  SampleClass.hashish_insert(@sample_data_1)
58
59
  SampleClass.hashish_delete(@sample_data_1[@primary_key])
59
- Hashish.redis_connection.zscore("#{@options[:key_prefix]}:", "#{@options[:key_prefix]}:#{SampleClass.send(:get_hashish_key, @sample_data_1)}").should be_nil
60
- Hashish.redis_connection.exists("#{@options[:key_prefix]}:#{SampleClass.send(:get_hashish_key, @sample_data_1)}").should be_false
60
+ Hashish.redis_connection.zscore("#{@options[:key_prefix]}:", "#{@options[:key_prefix]}:#{SampleClass.send(:hashish_get_key, @sample_data_1)}").should be_nil
61
+ Hashish.redis_connection.exists("#{@options[:key_prefix]}:#{SampleClass.send(:hashish_get_key, @sample_data_1)}").should be_false
61
62
  end
62
63
 
63
64
  it "should delete appropriate sorters and indexes" do
64
65
  SampleClass.hashish_insert(@sample_data_1)
65
66
  SampleClass.hashish_delete(@sample_data_1[@primary_key])
66
- SampleClass.send(:redis_keys).should == {}
67
+ SampleClass.send(:hashish_redis_keys).should == []
67
68
  end
68
69
  end
69
70
 
70
71
  describe ".hashish_list" do
71
- it "should list the items from the list"
72
+ it "should return all the items from the list" do
73
+ test_data = [@sample_data_2, @sample_data_1, @sample_data_3]
74
+ test_data.each do |data|
75
+ SampleClass.hashish_insert(data)
76
+ end
77
+ test_data.each do |data|
78
+ SampleClass.hashish_list.include?(data).should be_true
79
+ end
80
+ end
81
+
82
+ it "should not return any items that are not from the list" do
83
+ test_data = [@sample_data_2, @sample_data_1, @sample_data_3]
84
+ test_data.each do |data|
85
+ SampleClass.hashish_insert(data)
86
+ end
87
+ SampleClass.hashish_list.include?(@sample_data_4).should be_false
88
+ end
89
+
90
+ context "when sort_by is not specified" do
91
+ it "should sort the items based on the insert time with no specified sorter" do
92
+ test_data = [@sample_data_2, @sample_data_1, @sample_data_3]
93
+ test_data.each do |data|
94
+ SampleClass.hashish_insert(data)
95
+ sleep(1) # avoid exact same time of insert (redis is quick!!!)
96
+ end
97
+ SampleClass.hashish_list.should == test_data
98
+ end
99
+ end
100
+
101
+ context "when sort_by is not specified and sort_order is DESC" do
102
+ it "should sort the items based on the insert time with no specified sorter" do
103
+ test_data = [@sample_data_2, @sample_data_1, @sample_data_3]
104
+ test_data.each do |data|
105
+ SampleClass.hashish_insert(data)
106
+ sleep(1) # avoid exact same time of insert (redis is quick!!!)
107
+ end
108
+ SampleClass.hashish_list(:sort_order => 'DESC').should == test_data.reverse
109
+ end
110
+ end
111
+
112
+ context "when sort_by is specified and sort_order is not specified" do
113
+ it "should sort the items based on the sorter with a specified sorter" do
114
+ test_data = [@sample_data_2, @sample_data_1, @sample_data_3]
115
+ test_data.each do |data|
116
+ SampleClass.hashish_insert(data)
117
+ end
118
+ SampleClass.hashish_list(:sort_by => @sorter_name).should == [@sample_data_1, @sample_data_3, @sample_data_2]
119
+ end
120
+ end
121
+
122
+ context "when sort_by is specified and sort_order is DESC" do
123
+ it "should sort the items based on the sorter with a specified sorter" do
124
+ test_data = [@sample_data_2, @sample_data_1, @sample_data_3]
125
+ test_data.each do |data|
126
+ SampleClass.hashish_insert(data)
127
+ end
128
+ SampleClass.hashish_list(:sort_by => @sorter_name, :sort_order => 'DESC').should == [@sample_data_1, @sample_data_3, @sample_data_2].reverse
129
+ end
130
+ end
131
+
132
+ context "when a filter is provided" do
133
+ it "should find items using indexes based on filters" do
134
+ test_data = [@sample_data_2, @sample_data_1, @sample_data_3]
135
+ test_data.each do |data|
136
+ SampleClass.hashish_insert(data)
137
+ end
138
+ SampleClass.hashish_list(:filters => {@index_name => 'Moe'}).should == [@sample_data_3]
139
+ end
140
+ end
141
+
142
+ context "when a multiple values for filter is provided (OR)" do
143
+ it "should find items using indexes based on multiple values for filters" do
144
+ test_data = [@sample_data_2, @sample_data_1, @sample_data_3]
145
+ test_data.each do |data|
146
+ SampleClass.hashish_insert(data)
147
+ end
148
+ SampleClass.hashish_list(:filters => {@index_name => ['Moe', 'Joe']}).should == [@sample_data_1, @sample_data_3]
149
+ end
150
+ end
151
+
152
+ context "when a multiple filters are provided (AND)" do
153
+ it "should find items using indexes based on multiple filters" do
154
+ test_data = [@sample_data_2, @sample_data_1, @sample_data_3]
155
+ test_data.each do |data|
156
+ SampleClass.hashish_insert(data)
157
+ end
158
+ SampleClass.hashish_list(:filters => {@index_name => 'Joe', @proc_index_name => ['1=>Joe']}).should == [@sample_data_1]
159
+ end
160
+ end
161
+
72
162
  end
73
163
 
74
164
  describe ".hashish_flush!" do
@@ -77,7 +167,7 @@ describe Hashish do
77
167
  SampleClass.hashish_insert(@sample_data_2)
78
168
  SampleClass.hashish_insert(@sample_data_3)
79
169
  SampleClass.hashish_flush!
80
- SampleClass.send(:redis_keys).should == {}
170
+ SampleClass.send(:hashish_redis_keys).should == []
81
171
  end
82
172
  end
83
173
 
@@ -90,24 +180,25 @@ describe Hashish do
90
180
  end
91
181
 
92
182
  describe ".hashish_rebuild" do
93
- it "should rebuild the list correctly" do
183
+ it "should build the list correctly" do
94
184
  SampleClass.hashish_insert(@sample_data_1)
95
185
  SampleClass.hashish_insert(@sample_data_2)
96
186
  SampleClass.hashish_insert(@sample_data_3)
97
- before = SampleClass.send(:redis_keys)
187
+ before = SampleClass.hashish_list
98
188
  SampleClass.hashish_rebuild
99
- after = SampleClass.send(:redis_keys)
189
+ after = SampleClass.hashish_list
100
190
  before.should == after
101
191
  end
192
+
102
193
  end
103
194
 
104
- describe ".wait_on_lock" do
195
+ describe ".hashish_wait_on_lock" do
105
196
  it "should avoid concurrency issues" do
106
197
  x = 0
107
198
  threads = []
108
199
  (0..1).each do |i|
109
200
  threads << Thread.new do
110
- SampleClass.send(:wait_on_lock) do
201
+ SampleClass.send(:hashish_wait_on_lock) do
111
202
  a = x + 1
112
203
  sleep(5)
113
204
  x = a
@@ -118,6 +209,6 @@ describe Hashish do
118
209
  x.should == 2
119
210
  end
120
211
  end
121
-
212
+
122
213
  end
123
214
 
@@ -16,7 +16,7 @@ RSpec.configure do |config|
16
16
 
17
17
  config.before(:all) do
18
18
  Hashish.configure do |configuration|
19
- configuration.redis_connection = Redis.new(:db => 15, :host => '172.16.54.24')
19
+ configuration.redis_connection = Redis.new(:db => 15, :host => '127.0.0.1')
20
20
  configuration.redis_namespace = 'hashish_test_namspace'
21
21
  end
22
22
  end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: acts_as_hashish
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.3.0
5
+ version: 0.4.0
6
6
  platform: ruby
7
7
  authors:
8
8
  - Schubert Cardozo
@@ -18,9 +18,9 @@ dependencies:
18
18
  requirement: &id001 !ruby/object:Gem::Requirement
19
19
  none: false
20
20
  requirements:
21
- - - ">="
21
+ - - ~>
22
22
  - !ruby/object:Gem::Version
23
- version: "0"
23
+ version: 3.0.2
24
24
  type: :runtime
25
25
  version_requirements: *id001
26
26
  - !ruby/object:Gem::Dependency
@@ -29,9 +29,9 @@ dependencies:
29
29
  requirement: &id002 !ruby/object:Gem::Requirement
30
30
  none: false
31
31
  requirements:
32
- - - ">="
32
+ - - ~>
33
33
  - !ruby/object:Gem::Version
34
- version: "0"
34
+ version: 1.6.6
35
35
  type: :runtime
36
36
  version_requirements: *id002
37
37
  - !ruby/object:Gem::Dependency
@@ -42,7 +42,7 @@ dependencies:
42
42
  requirements:
43
43
  - - ">="
44
44
  - !ruby/object:Gem::Version
45
- version: "0"
45
+ version: 10.0.3
46
46
  type: :development
47
47
  version_requirements: *id003
48
48
  - !ruby/object:Gem::Dependency
@@ -53,7 +53,7 @@ dependencies:
53
53
  requirements:
54
54
  - - ">="
55
55
  - !ruby/object:Gem::Version
56
- version: "0"
56
+ version: 2.11.0
57
57
  type: :development
58
58
  version_requirements: *id004
59
59
  - !ruby/object:Gem::Dependency
@@ -64,10 +64,10 @@ dependencies:
64
64
  requirements:
65
65
  - - ">="
66
66
  - !ruby/object:Gem::Version
67
- version: "0"
67
+ version: 0.12.7
68
68
  type: :development
69
69
  version_requirements: *id005
70
- description: A sortable and searchable list backed by Redis
70
+ description: A sortable and searchable list backed by Redis. You can use it as a quick actionable workflow queue which you can search/sort and paginate thorough
71
71
  email:
72
72
  - cardozoschubert@gmail.com
73
73
  executables: []
@@ -79,6 +79,7 @@ extra_rdoc_files: []
79
79
  files:
80
80
  - lib/acts_as_hashish/configuration.rb
81
81
  - lib/acts_as_hashish/hashish.rb
82
+ - lib/acts_as_hashish/private_class_methods.rb
82
83
  - lib/acts_as_hashish/version.rb
83
84
  - lib/acts_as_hashish.rb
84
85
  - spec/hashish_spec.rb