Permalink
Browse files

Refactor the key structure, @WIP.

  • Loading branch information...
1 parent 1eda0da commit c813f37cce9fc06a281764a3b0e8f30bfe959d99 @leehambley committed Mar 5, 2012
View
@@ -1,13 +1,13 @@
-require "autotest/restart"
+require 'autotest/restart'
class Autotest
- def get_to_green
- begin
- rerun_all_tests
- wait_for_changes unless all_good
- end until all_good
- end
+# def get_to_green
+# begin
+# rerun_all_tests
+# wait_for_changes unless all_good
+# end until all_good
+# end
end
View
@@ -118,28 +118,42 @@ TODO: Write usage instructions here
4. Push to the branch (`git push origin my-new-feature`)
5. Create new Pull Request
-## Example Redis Session
-``` ruby
+## Sample Key Structure
-object_class:emotion:object_id:target_class:target_id
-target_class:emotion:target_id:object_class:object_id
+Given the following example, the key
+structure would be:
+
+``` ruby
+class Recommendation
+ iclude Emotions::Emotive
+ emotions :like
+end
class User
- def emotion(emotion, target)
- Emotion.new({object: self, target: target, emotion: emotion})
- end
+ include Emotions::Emotional
end
-User.new(id: 123).like?(Show.new(id: 456))
-=> user:123:like:show:456
+User.find(123).like(Recommendation.find(789)
+User.find(123).like(Recommendation.find(987)
+
+User.find(321).like(Recommendation.find(789)
+```
+
+The resulting Redis structure would be something like this:
+
+``` text
+user:like:123:recommendation
+ "789" "2012-11-13 00:01:02 +01:00"
+ "987" "2011-02-01 00:03:01 +01:00"
-Show.new(id: 456).like_exists?(User.new(id: 123)
-=> show:456:like_by:user:123
+user:like:321:recommendation
+ "789" "2014-02-01 17:15:01 +01:00"
-User.new(id: 123).all_with_emotion(:like)
-=> KEYS user:123:like*
+recommendation:like:789:user
+ "123" "2012-11-13 00:01:02 +01:00"
+ "321" "2014-02-01 17:15:01 +01:00"
-User.new(id: 123).count_with_emotion(:like)
-=> KEYS user:123:like*
+recommendation:like:987:user
+ "123" "2011-02-01 00:03:01 +01:00"
```
View
@@ -9,10 +9,22 @@ namespace :test do
t.test_files = FileList['test/unit_test*.rb']
end
+ Rake::TestTask.new(:acceptance) do |t|
+ t.libs << "test"
+ t.test_files = FileList['test/acceptance_test*.rb']
+ end
+
+ Rake::TestTask.new(:integration) do |t|
+ t.libs << "test"
+ t.test_files = FileList['test/integration_test*.rb']
+ end
+
task :default do
- task(:units).execute
+ Rake::Task['test:units'].execute
+ Rake::Task['test:acceptance'].execute
+ Rake::Task['test:integration'].execute
end
end
-task :default => 'test:units'
+task :default => 'test:default'
View
@@ -19,6 +19,7 @@ Gem::Specification.new do |gem|
gem.add_dependency('redis')
gem.add_development_dependency('minitest')
+ gem.add_development_dependency('turn')
gem.add_development_dependency('daemon_controller')
end
View
@@ -9,82 +9,53 @@ class << self
end
module StringExtensions
+
def underscore(delimiter = ':')
c = dup
c.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
c.gsub!(/\:\:/, delimiter)
c.downcase!
c
end
+
+ end
+
+ module KeyBuilderExtensions
+
+ def generate_key(scope, id = nil)
+ cn = self.class.name.dup
+ cn.class.send(:include, StringExtensions)
+ [cn.underscore, scope, id].compact.join(':')
+ end
+
end
class KeyBuilder
- attr_reader :object, :target
- private :object, :target
- def initialize(object, extras = {})
- raise ArgumentError, "Object must not be nil" if object.nil?
- @object = object
- @emotion = extras.fetch(:emotion, nil)
- @target = extras.fetch(:target, nil)
- if (@emotion and @target.nil?) or (@target and @emotion.nil?)
- raise ArgumentError, "Cannot generate an emotion key without a target"
- end
+
+ def initialize(args)
+ @object = args.fetch(:object)
+ @target = args.fetch(:target, nil)
+ @emotion = args.fetch(:emotion)
end
+
def key
- if target
- [underscore_object_class_name, _object_id, emotion,
- underscore_target_class_name, target_id].compact.join(delimiter)
- else
- [underscore_object_class_name, _object_id].compact.join(delimiter)
+ object = @object.dup
+ object.class.send(:include, KeyBuilderExtensions)
+ key = object.generate_key(@emotion, object.id)
+ if @target
+ tcn = @target.class == Class ? @target.name.dup : @target.class.name.dup
+ tcn.class.send(:include, StringExtensions)
+ key += ":#{tcn.underscore}"
end
+ key
end
- private
- def emotion
- @emotion ? @emotion.to_s : nil
- end
- def underscore_emotion
- return nil unless emotion
- e = emotion.dup
- e.class.send(:include, StringExtensions)
- e.underscore(delimiter)
- end
- def _object_id
- object.id.to_s
- end
- def target_id
- target ? target.id.to_s : nil
- end
- def object_class_name
- object.class.name
- end
- def underscore_object_class_name
- cn = object_class_name.dup
- cn.class.send(:include, StringExtensions)
- cn.underscore(delimiter)
- end
- def target_class_name
- return nil unless target
- target.class.name
- end
- def underscore_target_class_name
- return nil unless target
- cn = target_class_name.dup
- cn.class.send(:include, StringExtensions)
- cn.underscore(delimiter)
- end
- def delimiter
- ':'
- end
+
end
class RedisBackend
attr_accessor :redis
- def key_exists?(key_name)
- redis.exists(key_name)
- end
-
def write_keys(key_hashes)
redis.multi do
key_hashes.each do |key_name, hash|
@@ -99,8 +70,20 @@ def write_key(key_name, hash)
end
end
- def read_key(key_name)
- Hash[reids.hgetall(key_name)]
+ def read_sub_key(key_name, key)
+ redis.hget(key_name, key)
+ end
+
+ def remove_sub_keys(key_pairs)
+ redis.multi do
+ key_pairs.each do |key_name, key|
+ redis.hdel(key_name, key.to_s)
+ end
+ end
+ end
+
+ def keys_matching(argument)
+ redis.keys(argument)
end
end
@@ -115,21 +98,26 @@ def initialize(args = {})
def persist(args = {time: Time.now})
backend.write_keys({
- target_key => {created_at: args.fetch(:time)},
- object_key => {created_at: args.fetch(:time)},
+ target_key => {object.id => args.fetch(:time)},
+ object_key => {target.id => args.fetch(:time)},
})
end
+ def remove
+ backend.remove_sub_keys([[target_key, object.id.to_s], [object_key, target.id.to_s]])
+ end
+
def object_key
- KeyBuilder.new(object, emotion: emotion, target: target).key
+ KeyBuilder.new(object: object, emotion: emotion, target: target).key
end
def target_key
- KeyBuilder.new(target, emotion: emotion, target: object).key
+ KeyBuilder.new(object: target, emotion: emotion, target: object).key
end
def exists?
- backend.key_exists?(target_key)
+ puts "Checking if #{target_key} #{target.id} exists"
+ backend.read_sub_key(target_key, target.id.to_s)
end
private
@@ -144,8 +132,6 @@ module Emotive
class << self
- attr_accessor :_emotions
-
def included(klass)
klass.send(:include, InstanceMethods)
klass.send(:extend, ClassMethods)
@@ -155,15 +141,36 @@ def included(klass)
module ClassMethods
def emotions(*emotions)
- emotions.each { |emotion| emotion(emotion) }
+ emotions.each { |emotion| register_emotion(emotion.to_sym) }
end
- def emotion(name)
-
+ def register_emotion(name)
+ @registered_emotions ||= Array.new
+ @registered_emotions << name
+ end
+ def registered_emotions
+ @registered_emotions
end
end
module InstanceMethods
+ def initialize(*args)
+ super
+ self.class.registered_emotions.each do |emotion|
+ self.class.send :define_method, :"#{emotion}_by" do |emotional|
+ Emotion.new(object: emotional, target: self, emotion: emotion).persist
+ end
+ self.class.send :define_method, :"cancel_#{emotion}_by" do |emotional|
+ e = Emotion.new(object: emotional, target: self, emotion: emotion)
+ end
+# self.class.send :define_method, :"#{emotion}_emotes" do
+# lookup_key_builder = KeyBuilder.new(object: self, emotion: emotion)
+# keys = Emotions.backend.keys_matching(lookup_key_builder.key + "*")
+# puts "REDIS HAS #{Emotions.backend.redis.get(keys)}"
+# end
+ end
+ end
+
end
end
Oops, something went wrong.

0 comments on commit c813f37

Please sign in to comment.