hari 0.0.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.
Files changed (40) hide show
  1. data/.gitignore +4 -0
  2. data/Gemfile +3 -0
  3. data/LICENSE +22 -0
  4. data/README.md +0 -0
  5. data/Rakefile +1 -0
  6. data/hari.gemspec +38 -0
  7. data/lib/hari/configuration/redis.rb +33 -0
  8. data/lib/hari/configuration.rb +12 -0
  9. data/lib/hari/entity/property/builder.rb +25 -0
  10. data/lib/hari/entity/property.rb +24 -0
  11. data/lib/hari/entity/repository.rb +75 -0
  12. data/lib/hari/entity/serialization/boolean.rb +43 -0
  13. data/lib/hari/entity/serialization/date.rb +21 -0
  14. data/lib/hari/entity/serialization/datetime.rb +21 -0
  15. data/lib/hari/entity/serialization/float.rb +19 -0
  16. data/lib/hari/entity/serialization/integer.rb +28 -0
  17. data/lib/hari/entity/serialization/string.rb +17 -0
  18. data/lib/hari/entity/serialization/time.rb +21 -0
  19. data/lib/hari/entity/serialization.rb +42 -0
  20. data/lib/hari/entity.rb +77 -0
  21. data/lib/hari/errors.rb +17 -0
  22. data/lib/hari/node/queries.rb +7 -0
  23. data/lib/hari/node.rb +16 -0
  24. data/lib/hari/relationship/linked_list.rb +22 -0
  25. data/lib/hari/relationship/sorted_set.rb +22 -0
  26. data/lib/hari/relationship.rb +72 -0
  27. data/lib/hari/scripts.rb +26 -0
  28. data/lib/hari/version.rb +3 -0
  29. data/lib/hari.rb +20 -0
  30. data/spec/hari/entity/repository_spec.rb +22 -0
  31. data/spec/hari/entity/serialization/boolean_spec.rb +32 -0
  32. data/spec/hari/entity/serialization/date_spec.rb +23 -0
  33. data/spec/hari/entity/serialization/datetime_spec.rb +23 -0
  34. data/spec/hari/entity/serialization/float_spec.rb +19 -0
  35. data/spec/hari/entity/serialization/integer_spec.rb +18 -0
  36. data/spec/hari/entity/serialization/string_spec.rb +13 -0
  37. data/spec/hari/entity/serialization/time_spec.rb +14 -0
  38. data/spec/hari/entity/serialization_spec.rb +24 -0
  39. data/spec/spec_helper.rb +10 -0
  40. metadata +256 -0
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ Gemfile.lock
3
+ .bundle
4
+ *.rdb
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'http://rubygems.org/'
2
+
3
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Victor Rodrigues
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
File without changes
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require 'bundler/gem_tasks'
data/hari.gemspec ADDED
@@ -0,0 +1,38 @@
1
+ # coding: utf-8
2
+
3
+ lib = File.expand_path('../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+
6
+ require 'hari/version'
7
+
8
+ Gem::Specification.new do |s|
9
+ s.name = 'hari'
10
+ s.version = Hari::VERSION
11
+ s.summary = 'Hari is a graph library on top of Redis + Lua scripts'
12
+ s.description = <<-MD
13
+ Hari is a graph library on top of Redis database + Lua scripts
14
+ MD
15
+
16
+ s.author = 'Victor Rodrigues'
17
+ s.email = 'victorc.rodrigues@gmail.com'
18
+ s.homepage = 'http://github.com/rodrigues/hari'
19
+
20
+ s.license = 'MIT'
21
+
22
+ s.files = `git ls-files`.split($/)
23
+ s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
24
+ s.test_files = s.files.grep(%r{^(test|spec|features)/})
25
+ s.require_paths = ['lib']
26
+
27
+ s.add_dependency 'redis', '~> 3.0'
28
+ s.add_dependency 'redis-namespace', '~> 1.2'
29
+ s.add_dependency 'hiredis', '~> 0.4'
30
+ s.add_dependency 'activemodel', '~> 3.2'
31
+ s.add_dependency 'activesupport', '~> 3.2'
32
+ s.add_dependency 'yajl-ruby', '~> 1.1'
33
+
34
+ s.add_development_dependency 'bundler', '~> 1.3'
35
+ s.add_development_dependency 'rspec', '~> 2.13'
36
+ s.add_development_dependency 'rake', '~> 10.0'
37
+ s.add_development_dependency 'pry'
38
+ end
@@ -0,0 +1,33 @@
1
+ module Hari
2
+ module Configuration
3
+ module Redis
4
+
5
+ def redis
6
+ @redis || begin
7
+ self.redis = 'localhost:6379'
8
+ @redis
9
+ end
10
+ end
11
+
12
+ def redis=(server)
13
+ @redis = redis_namespace(server)
14
+ end
15
+
16
+ private
17
+
18
+ def redis_namespace(server)
19
+ return server if server.kind_of?(::Redis::Namespace)
20
+
21
+ ::Redis::Namespace.new :hari, redis_server(server)
22
+ end
23
+
24
+ def redis_server(server)
25
+ return server unless server.kind_of?(::String)
26
+
27
+ host, port = server.split(':')
28
+ ::Redis.new host: host, port: port
29
+ end
30
+
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,12 @@
1
+ require 'hari/configuration/redis'
2
+
3
+ module Hari
4
+ module Configuration
5
+ include Redis
6
+
7
+ def configure
8
+ yield self if block_given?
9
+ end
10
+
11
+ end
12
+ end
@@ -0,0 +1,25 @@
1
+ module Hari
2
+ class Entity
3
+ class Property
4
+ module Builder
5
+
6
+ def property(name, options = {})
7
+ attr_accessor name
8
+ validates_presence_of name if options[:required]
9
+
10
+ self.properties << Property.new(name, options)
11
+ end
12
+
13
+ def properties(*args)
14
+ options = args.extract_options!
15
+ args.each { |name| property name, options }
16
+
17
+ @properties ||= begin
18
+ self == Hari::Entity ? [] : Hari::Entity.properties.dup
19
+ end
20
+ end
21
+
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,24 @@
1
+ require 'hari/entity/property/builder'
2
+
3
+ module Hari
4
+ class Entity
5
+ class Property
6
+
7
+ attr_accessor :name, :serializer, :options
8
+
9
+ def initialize(name, options = {})
10
+ @name, @options = name.to_s, options
11
+ @serializer = options.delete(:type) || Serialization::String
12
+ end
13
+
14
+ def serialize(value)
15
+ serializer.serialize(value, name: name)
16
+ end
17
+
18
+ def desserialize(value)
19
+ serializer.desserialize(value, name: name)
20
+ end
21
+
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,75 @@
1
+ module Hari
2
+ class Entity
3
+ module Repository
4
+ extend ActiveSupport::Concern
5
+
6
+ def create_or_update
7
+ run_callbacks(:save) { new? ? create : update }
8
+ end
9
+
10
+ alias save create_or_update
11
+
12
+ def create
13
+ run_callbacks :create do
14
+ fail Hari::ValidationsFailed, self unless valid?
15
+
16
+ @id ||= generate_id
17
+ self.created_at = Time.now
18
+ self.updated_at = Time.now
19
+ persist
20
+ end
21
+
22
+ self
23
+ end
24
+
25
+ def update
26
+ run_callbacks :update do
27
+ fail Hari::ValidationsFailed, self unless valid?
28
+
29
+ self.updated_at = Time.now.utc.iso8601
30
+ persist
31
+ end
32
+
33
+ self
34
+ end
35
+
36
+ def persist
37
+ Hari.redis.set id, to_json
38
+ end
39
+
40
+ def delete
41
+ run_callbacks :destroy do
42
+ Hari.redis.del id
43
+ @destroyed = true
44
+ end
45
+
46
+ self
47
+ end
48
+
49
+ alias destroy delete
50
+
51
+ module ClassMethods
52
+
53
+ def create(attrs = {})
54
+ new(attrs).save
55
+ end
56
+
57
+ def find(*args)
58
+ options = args.extract_options!
59
+ args.flatten!
60
+ args.one? ? find_one(args[0], options) : find_many(args, options)
61
+ end
62
+
63
+ def find_one(id, options = {})
64
+ from_json Hari.redis.get(id)
65
+ end
66
+
67
+ def find_many(ids, options = {})
68
+ Hari.redis.mget(ids).map &method(:from_json)
69
+ end
70
+
71
+ end
72
+
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,43 @@
1
+ module Hari
2
+ class Entity
3
+ module Serialization
4
+ module Boolean
5
+
6
+ MAPPINGS = {
7
+ true => true,
8
+ 'true' => true,
9
+ 'TRUE' => true,
10
+ '1' => true,
11
+ 1 => true,
12
+ 1.0 => true,
13
+ 'x' => true,
14
+ 'X' => true,
15
+ 't' => true,
16
+ 'T' => true,
17
+ false => false,
18
+ 'false' => false,
19
+ 'FALSE' => false,
20
+ '0' => false,
21
+ 0 => false,
22
+ 0.0 => false,
23
+ '' => false,
24
+ ' ' => false,
25
+ 'f' => false,
26
+ 'F' => false,
27
+ nil => false
28
+ }.freeze
29
+
30
+ def self.serialize(value, options = {})
31
+ desserialize value, options
32
+ end
33
+
34
+ def self.desserialize(value, options = {})
35
+ MAPPINGS[value].tap do |bool|
36
+ fail SerializationError, "#{options[:name]}:#{value} is not boolean" if bool.nil?
37
+ end
38
+ end
39
+
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,21 @@
1
+ module Hari
2
+ class Entity
3
+ module Serialization
4
+ module Date
5
+
6
+ def self.serialize(value, options = {})
7
+ desserialize(value, options).try :iso8601
8
+ end
9
+
10
+ def self.desserialize(value, options = {})
11
+ return unless value.present?
12
+
13
+ value.kind_of?(::Date) ? value : ::Date.parse(value)
14
+ rescue
15
+ raise SerializationError, "#{options[:name]}:#{value} is an invalid date"
16
+ end
17
+
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ module Hari
2
+ class Entity
3
+ module Serialization
4
+ module DateTime
5
+
6
+ def self.serialize(value, options = {})
7
+ desserialize(value, options).try :iso8601
8
+ end
9
+
10
+ def self.desserialize(value, options = {})
11
+ return unless value.present?
12
+
13
+ value.kind_of?(::DateTime) ? value : ::DateTime.parse(value)
14
+ rescue
15
+ raise SerializationError, "#{options[:name]}:#{value} is an invalid date time"
16
+ end
17
+
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,19 @@
1
+ module Hari
2
+ class Entity
3
+ module Serialization
4
+ module Float
5
+
6
+ def self.serialize(value, options = {})
7
+ desserialize value, options
8
+ end
9
+
10
+ def self.desserialize(value, options = {})
11
+ Float value
12
+ rescue
13
+ raise SerializationError, "#{options[:name]}:#{value} is not a float"
14
+ end
15
+
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,28 @@
1
+ module Hari
2
+ class Entity
3
+ module Serialization
4
+ module Integer
5
+
6
+ def self.serialize(value, options = {})
7
+ desserialize value, options
8
+ end
9
+
10
+ def self.desserialize(value, options = {})
11
+ case value
12
+ when ::String
13
+ if value =~ /^\d+$/
14
+ value.to_i
15
+ else
16
+ raise
17
+ end
18
+ else
19
+ Integer(value)
20
+ end
21
+ rescue
22
+ raise SerializationError, "#{options[:name]}:#{value} is not an integer"
23
+ end
24
+
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,17 @@
1
+ module Hari
2
+ class Entity
3
+ module Serialization
4
+ module String
5
+
6
+ def self.serialize(value, options = {})
7
+ value.to_s if value
8
+ end
9
+
10
+ def self.desserialize(value, options = {})
11
+ value
12
+ end
13
+
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,21 @@
1
+ module Hari
2
+ class Entity
3
+ module Serialization
4
+ module Time
5
+
6
+ def self.serialize(value, options = {})
7
+ desserialize(value, options).try :strftime, '%Y%m%d%H%M%S'
8
+ end
9
+
10
+ def self.desserialize(value, options = {})
11
+ return unless value.present?
12
+
13
+ value.kind_of?(::Time) ? value : ::Time.parse(value)
14
+ rescue
15
+ raise SerializationError, "#{options[:name]}:#{value} is an invalid time"
16
+ end
17
+
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,42 @@
1
+ require 'hari/entity/serialization/boolean'
2
+ require 'hari/entity/serialization/date'
3
+ require 'hari/entity/serialization/datetime'
4
+ require 'hari/entity/serialization/float'
5
+ require 'hari/entity/serialization/integer'
6
+ require 'hari/entity/serialization/string'
7
+ require 'hari/entity/serialization/time'
8
+
9
+ module Hari
10
+ class Entity
11
+ module Serialization
12
+ extend ActiveSupport::Concern
13
+
14
+ def to_json
15
+ hash = self.class.properties.inject({}) do |buffer, prop|
16
+ buffer.merge prop.name => prop.serialize(send(prop.name))
17
+ end
18
+
19
+ Yajl::Encoder.encode hash
20
+ end
21
+
22
+ module ClassMethods
23
+
24
+ def from_json(source)
25
+ return if source.blank?
26
+
27
+ attrs = Yajl::Parser.parse(source).inject({}) do |buffer, (key, value)|
28
+ if prop = properties.find { |p| p.name == key }
29
+ buffer[key] = prop.desserialize(value)
30
+ end
31
+
32
+ buffer
33
+ end
34
+
35
+ new attrs
36
+ end
37
+
38
+ end
39
+
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,77 @@
1
+ require 'hari/entity/property'
2
+ require 'hari/entity/repository'
3
+ require 'hari/entity/serialization'
4
+
5
+ module Hari
6
+ class Entity
7
+ extend ActiveModel::Naming
8
+ extend ActiveModel::Callbacks
9
+ include ActiveModel::Validations
10
+ extend Property::Builder
11
+ include Repository
12
+ include Serialization
13
+
14
+ define_model_callbacks :create, :update, :destroy, :save
15
+
16
+ property :id
17
+ property :created_at, type: Time
18
+ property :updated_at, type: Time
19
+
20
+ def initialize(attrs = {})
21
+ return if attrs.blank?
22
+
23
+ attrs = attrs.with_indifferent_access
24
+
25
+ self.class.properties.each do |prop|
26
+ send("#{prop.name}=", attrs[prop.name]) if attrs[prop.name]
27
+ end
28
+ end
29
+
30
+ def attributes
31
+ self.class.properties.inject({}) do |buffer, prop|
32
+ buffer.merge prop.name => send(prop.name)
33
+ end
34
+ end
35
+
36
+ alias attribute send
37
+ alias read_attribute send
38
+
39
+ def write_attribute(name, value)
40
+ send "#{name}=", value
41
+ end
42
+
43
+ def has_attribute?(name)
44
+ respond_to? name
45
+ end
46
+
47
+ def ==(other)
48
+ other.is_a?(Hari::Entity) && self.id == other.id
49
+ end
50
+
51
+ def new?
52
+ self.id.nil?
53
+ end
54
+
55
+ alias new_record? new?
56
+
57
+ def persisted?
58
+ not new?
59
+ end
60
+
61
+ def destroyed?
62
+ @destroyed
63
+ end
64
+
65
+ def generate_id
66
+ 'ent' + ::Time.now.strftime('%Y%m%d%H%M%S') + SecureRandom.hex(3)
67
+ end
68
+
69
+ def to_s
70
+ attrs = attributes
71
+ attrs.delete 'id'
72
+
73
+ "<#{self.class} id=#{id} attributes=#{attrs}>"
74
+ end
75
+
76
+ end
77
+ end
@@ -0,0 +1,17 @@
1
+ module Hari
2
+ class HariException < RuntimeError; end
3
+ class NotFound < HariException; end
4
+ class InvalidQuery < HariException; end
5
+ class SerializationError < HariException; end
6
+
7
+ class ValidationsFailed < HariException
8
+ attr_reader :object
9
+
10
+ def initialize(object)
11
+ @object = object
12
+ errors = @object.errors.full_messages.to_sentence
13
+ super errors
14
+ end
15
+ end
16
+
17
+ end
@@ -0,0 +1,7 @@
1
+ module Hari
2
+ class Node < Entity
3
+ module Queries
4
+
5
+ end
6
+ end
7
+ end
data/lib/hari/node.rb ADDED
@@ -0,0 +1,16 @@
1
+ require 'hari/node/queries'
2
+
3
+ module Hari
4
+ class Node < Entity
5
+ include Hari::Node::Queries
6
+
7
+ property :model_id, required: true
8
+
9
+ def generate_id
10
+ return model_id if model_id.include?('#')
11
+
12
+ self.class.to_s.underscore + "#" + model_id.to_s
13
+ end
14
+
15
+ end
16
+ end
@@ -0,0 +1,22 @@
1
+ module Hari
2
+ class Relationship < Entity
3
+ module Backend
4
+ module LinkedList
5
+ extend self
6
+
7
+ def type
8
+ :ll
9
+ end
10
+
11
+ def create(rel)
12
+ %w(in out).each { |d| Hari.redis.lpush rel.key(d), rel.id }
13
+ end
14
+
15
+ def delete(rel)
16
+ %w(in out).each { |d| Hari.redis.lrem rel.key(d), 1, rel.id }
17
+ end
18
+
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,22 @@
1
+ module Hari
2
+ class Relationship < Entity
3
+ module Backend
4
+ module SortedSet
5
+ extend self
6
+
7
+ def type
8
+ :ss
9
+ end
10
+
11
+ def create(rel)
12
+ %w(in out).each { |d| Hari.redis.zadd rel.key(d), rel.weight(d), rel.id }
13
+ end
14
+
15
+ def delete(rel)
16
+ %w(in out).each { |d| Hari.redis.zrem rel.key(d), rel.id }
17
+ end
18
+
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,72 @@
1
+ module Hari
2
+ class Relationship < Entity
3
+
4
+ properties :label, :start_node_id, :end_node_id, presence: true
5
+
6
+ def generate_id
7
+ 'rel:' + start_node.id + ':' + end_node.id + ':' + backend.id + ':' + SecureRandom.hex(3)
8
+ end
9
+
10
+ def start_node
11
+ @start_node ||= Hari::Node.find(start_node_id)
12
+ end
13
+
14
+ def end_node
15
+ @end_node ||= Hari::Node.find(end_node_id)
16
+ end
17
+
18
+ def self.create(label, start_node, end_node, attributes = {})
19
+ attrs = attributes.merge(label: label,
20
+ start_node_id: node_id(start_node),
21
+ end_node_id: node_id(end_node))
22
+ new(attrs).save
23
+ end
24
+
25
+ def self.use!(backend)
26
+ @backend = backend.kind_of?(Module) ? backend
27
+ : "Hari::Relationship::#{backend.to_s.camelize}".constantize
28
+ end
29
+
30
+ def self.backend
31
+ @backend ||= Hari::Relationship::Backend::SortedSet
32
+ end
33
+
34
+ def backend
35
+ self.class.backend
36
+ end
37
+
38
+ def weight(dir)
39
+ Time.now
40
+ end
41
+
42
+ private
43
+
44
+ def node_id(node)
45
+ node.kind_of?(::String) ? node : node.try(:id)
46
+ end
47
+
48
+ def key(dir = nil)
49
+ case dir
50
+ when nil
51
+ "#{start_node_id}:#{label}:#{end_node_id}"
52
+ else
53
+ "#{start_node_id}:#{label}:#{dir}"
54
+ end
55
+ end
56
+
57
+ def create
58
+ super
59
+ backend.create self
60
+ Hari.redis.set key, id
61
+ self
62
+ end
63
+
64
+ def delete
65
+ backend.delete self
66
+ Hari.redis.del key
67
+ super
68
+ self
69
+ end
70
+
71
+ end
72
+ end
@@ -0,0 +1,26 @@
1
+ module Hari
2
+ module Scripts
3
+
4
+ SCRIPT_PATH = File.expand_path('../scripts', __FILE__)
5
+
6
+ def map
7
+ @scripts ||= {}
8
+ end
9
+
10
+ def load
11
+ files = Dir[SCRIPT_PATH.join('**/*.lua')]
12
+
13
+ files.each do |file|
14
+ name = file.gsub("#{SCRIPT_PATH}/", '').gsub('.lua', '')
15
+ script = File.read(file)
16
+ sha = Hari.redis.script(:load, script)
17
+ map[name] = sha
18
+ end
19
+ end
20
+
21
+ def sha(script_name)
22
+ map[script_name.to_s]
23
+ end
24
+
25
+ end
26
+ end
@@ -0,0 +1,3 @@
1
+ module Hari
2
+ VERSION = '0.0.1'
3
+ end
data/lib/hari.rb ADDED
@@ -0,0 +1,20 @@
1
+ require 'redis'
2
+ require 'redis/namespace'
3
+ require 'active_model'
4
+ require 'active_support/core_ext/hash/indifferent_access'
5
+ require 'active_support/core_ext/module/delegation'
6
+ require 'active_support/core_ext/object/try'
7
+ require 'yajl'
8
+
9
+ require 'hari/version'
10
+ require 'hari/configuration'
11
+ require 'hari/errors'
12
+ require 'hari/entity'
13
+ require 'hari/node'
14
+ require 'hari/relationship'
15
+
16
+ module Hari
17
+ extend self
18
+ extend Configuration
19
+
20
+ end
@@ -0,0 +1,22 @@
1
+ require 'spec_helper'
2
+
3
+ describe Hari::Entity::Repository do
4
+
5
+ specify '.create, .find' do
6
+ model = TestModel.create(name: 'Ze', birth: '2012-04-20', points: '300')
7
+ model.id.should be
8
+
9
+ found = TestModel.find(model.id)
10
+ found.birth.year.should == 2012
11
+ found.birth.month.should == 4
12
+ found.birth.day.should == 20
13
+ found.points.should == 300
14
+ found.name.should == 'Ze'
15
+
16
+ model2 = TestModel.create(name: 'Jo', birth: '2009-03-21', points: '404')
17
+
18
+ founds = TestModel.find(model.id, model2.id)
19
+ founds.size.should == 2
20
+ end
21
+
22
+ end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ describe Hari::Entity::Serialization::Boolean do
4
+
5
+ describe '.serialize, .desserialize' do
6
+ it 'truthful values become true' do
7
+ subject.serialize(true).should be_true
8
+ subject.serialize('true').should be_true
9
+ subject.serialize('TRUE').should be_true
10
+ subject.serialize('1').should be_true
11
+ subject.serialize(1).should be_true
12
+ subject.serialize(1.0).should be_true
13
+ subject.serialize('x').should be_true
14
+ subject.serialize('X').should be_true
15
+ subject.serialize('t').should be_true
16
+ subject.serialize('T').should be_true
17
+ end
18
+
19
+ it 'untruthful values become false' do
20
+ subject.serialize(false).should be_false
21
+ subject.serialize('false').should be_false
22
+ subject.serialize('FALSE').should be_false
23
+ subject.serialize('0').should be_false
24
+ subject.serialize(0).should be_false
25
+ subject.serialize(0.0).should be_false
26
+ subject.serialize('').should be_false
27
+ subject.serialize(' ').should be_false
28
+ subject.serialize(nil).should be_false
29
+ end
30
+ end
31
+
32
+ end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ describe Hari::Entity::Serialization::Date do
4
+
5
+ describe '.serialize' do
6
+ it 'converts to date string' do
7
+ subject.serialize(Date.new(2011, 07, 01)).should == '2011-07-01'
8
+ end
9
+ end
10
+
11
+ describe '.desserialize' do
12
+ it 'converts to date' do
13
+ subject.desserialize('2011-07-01').should == Date.new(2011, 07, 01)
14
+ end
15
+
16
+ context 'when an invalid value is desserialized' do
17
+ it 'raises an error' do
18
+ expect { subject.desserialize('not a date') }.to raise_error
19
+ end
20
+ end
21
+ end
22
+
23
+ end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ describe Hari::Entity::Serialization::DateTime do
4
+
5
+ describe '.serialize' do
6
+ it 'converts to date time string' do
7
+ subject.serialize(DateTime.new(2011, 07, 01, 10, 20, 30)).should == '2011-07-01T10:20:30+00:00'
8
+ end
9
+ end
10
+
11
+ describe '.desserialize' do
12
+ it 'converts to date time' do
13
+ subject.desserialize('2011-07-01T10:20:30').should == DateTime.new(2011, 07, 01, 10, 20, 30)
14
+ end
15
+
16
+ context 'when an invalid value is desserialized' do
17
+ it 'raises an error' do
18
+ expect { subject.desserialize('not a date time') }.to raise_error
19
+ end
20
+ end
21
+ end
22
+
23
+ end
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+
3
+ describe Hari::Entity::Serialization::Float do
4
+
5
+ describe '.serialize, .desserialize' do
6
+ it 'converts to float' do
7
+ subject.serialize(4237.55).should == 4237.55
8
+ subject.serialize('4237.55').should == 4237.55
9
+ subject.serialize('4237').should == 4237.0
10
+ end
11
+
12
+ context 'when an invalid value is desserialized' do
13
+ it 'raises an error' do
14
+ expect { subject.desserialize('not a float') }.to raise_error
15
+ end
16
+ end
17
+ end
18
+
19
+ end
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+
3
+ describe Hari::Entity::Serialization::Integer do
4
+
5
+ describe '.serialize, .desserialize' do
6
+ it 'converts to integer' do
7
+ subject.serialize('1200').should == 1200
8
+ subject.serialize(1200).should == 1200
9
+ end
10
+
11
+ context 'when an invalid value is serialized' do
12
+ it 'raises an error' do
13
+ expect { subject.desserialize('not an integer') }.to raise_error
14
+ end
15
+ end
16
+ end
17
+
18
+ end
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+
3
+ describe Hari::Entity::Serialization::String do
4
+
5
+ describe '.serialize, .desserialize' do
6
+ it 'converts value to string' do
7
+ subject.serialize(:something).should == 'something'
8
+ subject.serialize(1).should == '1'
9
+ subject.serialize(nil).should == nil
10
+ end
11
+ end
12
+
13
+ end
@@ -0,0 +1,14 @@
1
+ require 'spec_helper'
2
+
3
+ describe Hari::Entity::Serialization::Time do
4
+
5
+ describe '.serialize, .desserialize' do
6
+ it 'converts value to string' do
7
+ time = Time.new(2012, 04, 30, 12, 05, 50)
8
+ subject.serialize(time).should == '20120430120550'
9
+ subject.serialize('2012-04-30T12:05:50').should == '20120430120550'
10
+ subject.desserialize('20120430120550').should == time
11
+ end
12
+ end
13
+
14
+ end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+
3
+ describe Hari::Entity::Serialization do
4
+
5
+ describe '#to_json' do
6
+ it 'serializes instance to json' do
7
+ model = TestModel.new(name: 'Ze',
8
+ birth: Date.new(1986, 01, 23),
9
+ points: '200')
10
+
11
+ model.to_json.should == '{"id":null,"created_at":null,"updated_at":null,"name":"Ze","birth":"1986-01-23","points":200}'
12
+ end
13
+ end
14
+
15
+ describe '.from_json' do
16
+ it 'desserializes instance from json' do
17
+ model = TestModel.from_json('{"name":"Ze","birth":"1986-01-23","points":200}')
18
+ model.name.should == 'Ze'
19
+ model.birth.should == Date.new(1986, 01, 23)
20
+ model.points.should == 200
21
+ end
22
+ end
23
+
24
+ end
@@ -0,0 +1,10 @@
1
+ $:.push '../lib'
2
+
3
+ require 'hari'
4
+ require 'pry'
5
+
6
+ class TestModel < Hari::Entity
7
+ property :name
8
+ property :birth, type: Date
9
+ property :points, type: Integer
10
+ end
metadata ADDED
@@ -0,0 +1,256 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: hari
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Victor Rodrigues
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-05-02 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: redis
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '3.0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '3.0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: redis-namespace
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: '1.2'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: '1.2'
46
+ - !ruby/object:Gem::Dependency
47
+ name: hiredis
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: '0.4'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '0.4'
62
+ - !ruby/object:Gem::Dependency
63
+ name: activemodel
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: '3.2'
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: '3.2'
78
+ - !ruby/object:Gem::Dependency
79
+ name: activesupport
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ~>
84
+ - !ruby/object:Gem::Version
85
+ version: '3.2'
86
+ type: :runtime
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ~>
92
+ - !ruby/object:Gem::Version
93
+ version: '3.2'
94
+ - !ruby/object:Gem::Dependency
95
+ name: yajl-ruby
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ~>
100
+ - !ruby/object:Gem::Version
101
+ version: '1.1'
102
+ type: :runtime
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ~>
108
+ - !ruby/object:Gem::Version
109
+ version: '1.1'
110
+ - !ruby/object:Gem::Dependency
111
+ name: bundler
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ~>
116
+ - !ruby/object:Gem::Version
117
+ version: '1.3'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ~>
124
+ - !ruby/object:Gem::Version
125
+ version: '1.3'
126
+ - !ruby/object:Gem::Dependency
127
+ name: rspec
128
+ requirement: !ruby/object:Gem::Requirement
129
+ none: false
130
+ requirements:
131
+ - - ~>
132
+ - !ruby/object:Gem::Version
133
+ version: '2.13'
134
+ type: :development
135
+ prerelease: false
136
+ version_requirements: !ruby/object:Gem::Requirement
137
+ none: false
138
+ requirements:
139
+ - - ~>
140
+ - !ruby/object:Gem::Version
141
+ version: '2.13'
142
+ - !ruby/object:Gem::Dependency
143
+ name: rake
144
+ requirement: !ruby/object:Gem::Requirement
145
+ none: false
146
+ requirements:
147
+ - - ~>
148
+ - !ruby/object:Gem::Version
149
+ version: '10.0'
150
+ type: :development
151
+ prerelease: false
152
+ version_requirements: !ruby/object:Gem::Requirement
153
+ none: false
154
+ requirements:
155
+ - - ~>
156
+ - !ruby/object:Gem::Version
157
+ version: '10.0'
158
+ - !ruby/object:Gem::Dependency
159
+ name: pry
160
+ requirement: !ruby/object:Gem::Requirement
161
+ none: false
162
+ requirements:
163
+ - - ! '>='
164
+ - !ruby/object:Gem::Version
165
+ version: '0'
166
+ type: :development
167
+ prerelease: false
168
+ version_requirements: !ruby/object:Gem::Requirement
169
+ none: false
170
+ requirements:
171
+ - - ! '>='
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ description: ! ' Hari is a graph library on top of Redis database + Lua scripts
175
+
176
+ '
177
+ email: victorc.rodrigues@gmail.com
178
+ executables: []
179
+ extensions: []
180
+ extra_rdoc_files: []
181
+ files:
182
+ - .gitignore
183
+ - Gemfile
184
+ - LICENSE
185
+ - README.md
186
+ - Rakefile
187
+ - hari.gemspec
188
+ - lib/hari.rb
189
+ - lib/hari/configuration.rb
190
+ - lib/hari/configuration/redis.rb
191
+ - lib/hari/entity.rb
192
+ - lib/hari/entity/property.rb
193
+ - lib/hari/entity/property/builder.rb
194
+ - lib/hari/entity/repository.rb
195
+ - lib/hari/entity/serialization.rb
196
+ - lib/hari/entity/serialization/boolean.rb
197
+ - lib/hari/entity/serialization/date.rb
198
+ - lib/hari/entity/serialization/datetime.rb
199
+ - lib/hari/entity/serialization/float.rb
200
+ - lib/hari/entity/serialization/integer.rb
201
+ - lib/hari/entity/serialization/string.rb
202
+ - lib/hari/entity/serialization/time.rb
203
+ - lib/hari/errors.rb
204
+ - lib/hari/node.rb
205
+ - lib/hari/node/queries.rb
206
+ - lib/hari/relationship.rb
207
+ - lib/hari/relationship/linked_list.rb
208
+ - lib/hari/relationship/sorted_set.rb
209
+ - lib/hari/scripts.rb
210
+ - lib/hari/version.rb
211
+ - spec/hari/entity/repository_spec.rb
212
+ - spec/hari/entity/serialization/boolean_spec.rb
213
+ - spec/hari/entity/serialization/date_spec.rb
214
+ - spec/hari/entity/serialization/datetime_spec.rb
215
+ - spec/hari/entity/serialization/float_spec.rb
216
+ - spec/hari/entity/serialization/integer_spec.rb
217
+ - spec/hari/entity/serialization/string_spec.rb
218
+ - spec/hari/entity/serialization/time_spec.rb
219
+ - spec/hari/entity/serialization_spec.rb
220
+ - spec/spec_helper.rb
221
+ homepage: http://github.com/rodrigues/hari
222
+ licenses:
223
+ - MIT
224
+ post_install_message:
225
+ rdoc_options: []
226
+ require_paths:
227
+ - lib
228
+ required_ruby_version: !ruby/object:Gem::Requirement
229
+ none: false
230
+ requirements:
231
+ - - ! '>='
232
+ - !ruby/object:Gem::Version
233
+ version: '0'
234
+ required_rubygems_version: !ruby/object:Gem::Requirement
235
+ none: false
236
+ requirements:
237
+ - - ! '>='
238
+ - !ruby/object:Gem::Version
239
+ version: '0'
240
+ requirements: []
241
+ rubyforge_project:
242
+ rubygems_version: 1.8.25
243
+ signing_key:
244
+ specification_version: 3
245
+ summary: Hari is a graph library on top of Redis + Lua scripts
246
+ test_files:
247
+ - spec/hari/entity/repository_spec.rb
248
+ - spec/hari/entity/serialization/boolean_spec.rb
249
+ - spec/hari/entity/serialization/date_spec.rb
250
+ - spec/hari/entity/serialization/datetime_spec.rb
251
+ - spec/hari/entity/serialization/float_spec.rb
252
+ - spec/hari/entity/serialization/integer_spec.rb
253
+ - spec/hari/entity/serialization/string_spec.rb
254
+ - spec/hari/entity/serialization/time_spec.rb
255
+ - spec/hari/entity/serialization_spec.rb
256
+ - spec/spec_helper.rb