sysarcana-data 0.0.14
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 +17 -0
- data/Gemfile +11 -0
- data/Rakefile +11 -0
- data/lib/sysarcana/data.rb +26 -0
- data/lib/sysarcana/data/posts.rb +71 -0
- data/lib/sysarcana/data/redis_wrapper.rb +16 -0
- data/lib/sysarcana/data/version.rb +5 -0
- data/spec/post_spec.rb +138 -0
- data/sysarcana-data.gemspec +20 -0
- metadata +88 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'datalogger'
|
2
|
+
require 'hashie'
|
3
|
+
require 'time'
|
4
|
+
|
5
|
+
require 'sysarcana/data/posts'
|
6
|
+
require 'sysarcana/data/redis_wrapper'
|
7
|
+
|
8
|
+
DataLogger::Logger.component = 'sysarcana'
|
9
|
+
|
10
|
+
module SysArcana
|
11
|
+
module Data
|
12
|
+
extend self
|
13
|
+
|
14
|
+
def connect_to_redis
|
15
|
+
DataLogger::Logger.log(action: 'Data.connect_to_redis') do
|
16
|
+
redis_url = ENV["REDISTOGO_URL"] || "redis://localhost:6379"
|
17
|
+
uri = URI.parse(redis_url)
|
18
|
+
RedisWrapper.new(:host => uri.host, :port => uri.port, :password => uri.password)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def redis
|
23
|
+
@redis ||= connect_to_redis
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module SysArcana
|
2
|
+
module Data
|
3
|
+
class Post < Hashie::Dash
|
4
|
+
extend DataLogger
|
5
|
+
include DataLogger
|
6
|
+
|
7
|
+
property :slug
|
8
|
+
property :title
|
9
|
+
property :body
|
10
|
+
property :published_at
|
11
|
+
|
12
|
+
def publish!
|
13
|
+
Post.publish!(self)
|
14
|
+
end
|
15
|
+
|
16
|
+
def save!
|
17
|
+
Post.save!(self)
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.all
|
21
|
+
log(action: 'Post.all') do
|
22
|
+
all_slugs.map { |slug| find(slug) }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.all_slugs
|
27
|
+
SysArcana::Data.redis.smembers("posts")
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.find(slug)
|
31
|
+
log(action: 'Post.find', slug: slug) do
|
32
|
+
result = SysArcana::Data.redis.hgetall("post:#{slug}")
|
33
|
+
if result == {}
|
34
|
+
log(action: 'Post.find', slug: slug, result: 'not-found')
|
35
|
+
nil
|
36
|
+
else
|
37
|
+
log(action: 'Post.find', slug: slug, result: 'found')
|
38
|
+
new(result)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.publish!(post)
|
44
|
+
log(action: 'Post.publish!', slug: post.slug) do
|
45
|
+
post.published_at = Time.now.utc.iso8601
|
46
|
+
post.save!
|
47
|
+
SysArcana::Data.redis.zadd "posts_published", post.published_at.to_i, post.slug
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.published
|
52
|
+
log(action: 'Post.published') do
|
53
|
+
published_slugs.map { |slug| find(slug) }
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.published_slugs
|
58
|
+
SysArcana::Data.redis.zrevrange("posts_published", 0, -1)
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.save!(post)
|
62
|
+
log(action: 'save!', slug: post.slug) do
|
63
|
+
SysArcana::Data.redis.multi do |r|
|
64
|
+
r.mapped_hmset "post:#{post.slug}", post
|
65
|
+
r.sadd "posts", post.slug
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'redis'
|
2
|
+
require 'uri'
|
3
|
+
|
4
|
+
class RedisWrapper < Redis
|
5
|
+
def nillify_string(s)
|
6
|
+
s.empty? ? nil : s
|
7
|
+
end
|
8
|
+
|
9
|
+
def normalize_hash(h)
|
10
|
+
h.inject({}) { |h, (k,v)| h[k] = nillify_string(v); h }
|
11
|
+
end
|
12
|
+
|
13
|
+
def hgetall(key)
|
14
|
+
normalize_hash(super)
|
15
|
+
end
|
16
|
+
end
|
data/spec/post_spec.rb
ADDED
@@ -0,0 +1,138 @@
|
|
1
|
+
require 'minitest/spec'
|
2
|
+
require 'minitest/autorun'
|
3
|
+
|
4
|
+
require 'sysarcana/data'
|
5
|
+
|
6
|
+
include SysArcana::Data
|
7
|
+
|
8
|
+
describe Post do
|
9
|
+
before do
|
10
|
+
redis.flushdb
|
11
|
+
@post = Post.new
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "Post.new" do
|
15
|
+
it "must create a new Post object" do
|
16
|
+
@post.kind_of?(Post).must_equal(true)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "must respond to slug" do
|
20
|
+
@post.respond_to?(:slug).must_equal(true)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "must respond to title" do
|
24
|
+
@post.respond_to?(:title).must_equal(true)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "must respond to body" do
|
28
|
+
@post.respond_to?(:body).must_equal(true)
|
29
|
+
end
|
30
|
+
|
31
|
+
it "must respond to published_at" do
|
32
|
+
@post.respond_to?(:published_at).must_equal(true)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "Post.all_slugs" do
|
37
|
+
it "must return an Array if there are not any" do
|
38
|
+
Post.all_slugs.kind_of?(Array).must_equal(true)
|
39
|
+
end
|
40
|
+
|
41
|
+
it "must return an empty Array if there are not any slugs" do
|
42
|
+
Post.all_slugs.empty?.must_equal(true)
|
43
|
+
end
|
44
|
+
|
45
|
+
it "must contain the slug if it has been saved" do
|
46
|
+
@post.slug = 'test'
|
47
|
+
@post.save!
|
48
|
+
Post.all_slugs.include?(@post.slug).must_equal(true)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "Post.all" do
|
53
|
+
it "must return an Array" do
|
54
|
+
Post.all.kind_of?(Array).must_equal(true)
|
55
|
+
end
|
56
|
+
|
57
|
+
it "must reutrn an empty Array of there are not any posts" do
|
58
|
+
Post.all.empty?.must_equal(true)
|
59
|
+
end
|
60
|
+
|
61
|
+
it "must contain the post if it has been saved" do
|
62
|
+
@post.slug = 'test'
|
63
|
+
@post.save!
|
64
|
+
Post.all.include?(@post).must_equal(true)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe "save!" do
|
69
|
+
it "must create a post entry in redis" do
|
70
|
+
@post.slug = 'test'
|
71
|
+
@post.save!
|
72
|
+
redis.hgetall("post:#{@post.slug}").must_equal(@post.to_hash)
|
73
|
+
end
|
74
|
+
|
75
|
+
it "must add the post to the posts_all set" do
|
76
|
+
@post.slug = 'test'
|
77
|
+
@post.save!
|
78
|
+
redis.sismember("posts", @post.slug).must_equal(true)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
describe "publish!" do
|
83
|
+
before do
|
84
|
+
@post = Post.new slug: 'test'
|
85
|
+
@post.save!
|
86
|
+
end
|
87
|
+
|
88
|
+
it "must set the published_at attribute" do
|
89
|
+
@post.publish!
|
90
|
+
@post.published_at.wont_equal(nil)
|
91
|
+
end
|
92
|
+
|
93
|
+
it "must add to the 'posts_published' sorted set" do
|
94
|
+
@post.publish!
|
95
|
+
redis.zrevrange('posts_published', 0, -1).include?(@post.slug).must_equal(true)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
describe "published" do
|
100
|
+
before do
|
101
|
+
@post = Post.new slug: 'test'
|
102
|
+
@post.save!
|
103
|
+
end
|
104
|
+
|
105
|
+
it "must return an Array" do
|
106
|
+
Post.published.kind_of?(Array).must_equal(true)
|
107
|
+
end
|
108
|
+
|
109
|
+
it "must be empty if there are not any published posts" do
|
110
|
+
Post.published.empty?.must_equal(true)
|
111
|
+
end
|
112
|
+
|
113
|
+
it "must contain them if they exist" do
|
114
|
+
@post.publish!
|
115
|
+
Post.published.include?(@post).must_equal(true)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
describe "published_slugs" do
|
120
|
+
before do
|
121
|
+
@post = Post.new slug: 'test'
|
122
|
+
@post.save!
|
123
|
+
end
|
124
|
+
|
125
|
+
it "must return an Array" do
|
126
|
+
Post.published_slugs.kind_of?(Array).must_equal(true)
|
127
|
+
end
|
128
|
+
|
129
|
+
it "must be empty if there are not any slugs" do
|
130
|
+
Post.published_slugs.empty?.must_equal(true)
|
131
|
+
end
|
132
|
+
|
133
|
+
it "must contain them if they are there" do
|
134
|
+
@post.publish!
|
135
|
+
Post.published_slugs.include?(@post.slug).must_equal(true)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/sysarcana/data/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Michael Gorsuch"]
|
6
|
+
gem.email = ["michael.gorsuch@gmail.com"]
|
7
|
+
gem.description = %q{data package for the SysArcana blog system}
|
8
|
+
gem.summary = %q{data package for the SysArcana blog system}
|
9
|
+
gem.homepage = ""
|
10
|
+
|
11
|
+
gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
12
|
+
gem.files = `git ls-files`.split("\n")
|
13
|
+
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
14
|
+
gem.name = "sysarcana-data"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = SysArcana::Data::VERSION
|
17
|
+
gem.add_dependency('hashie')
|
18
|
+
gem.add_dependency('redis', '>= 2.2.2')
|
19
|
+
gem.add_dependency('datalogger', '0.0.5')
|
20
|
+
end
|
metadata
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sysarcana-data
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.14
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Michael Gorsuch
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-01-28 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: hashie
|
16
|
+
requirement: &70189588943560 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70189588943560
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: redis
|
27
|
+
requirement: &70189588943060 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 2.2.2
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70189588943060
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: datalogger
|
38
|
+
requirement: &70189588942560 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - =
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 0.0.5
|
44
|
+
type: :runtime
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *70189588942560
|
47
|
+
description: data package for the SysArcana blog system
|
48
|
+
email:
|
49
|
+
- michael.gorsuch@gmail.com
|
50
|
+
executables: []
|
51
|
+
extensions: []
|
52
|
+
extra_rdoc_files: []
|
53
|
+
files:
|
54
|
+
- .gitignore
|
55
|
+
- Gemfile
|
56
|
+
- Rakefile
|
57
|
+
- lib/sysarcana/data.rb
|
58
|
+
- lib/sysarcana/data/posts.rb
|
59
|
+
- lib/sysarcana/data/redis_wrapper.rb
|
60
|
+
- lib/sysarcana/data/version.rb
|
61
|
+
- spec/post_spec.rb
|
62
|
+
- sysarcana-data.gemspec
|
63
|
+
homepage: ''
|
64
|
+
licenses: []
|
65
|
+
post_install_message:
|
66
|
+
rdoc_options: []
|
67
|
+
require_paths:
|
68
|
+
- lib
|
69
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
70
|
+
none: false
|
71
|
+
requirements:
|
72
|
+
- - ! '>='
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '0'
|
75
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
76
|
+
none: false
|
77
|
+
requirements:
|
78
|
+
- - ! '>='
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '0'
|
81
|
+
requirements: []
|
82
|
+
rubyforge_project:
|
83
|
+
rubygems_version: 1.8.10
|
84
|
+
signing_key:
|
85
|
+
specification_version: 3
|
86
|
+
summary: data package for the SysArcana blog system
|
87
|
+
test_files:
|
88
|
+
- spec/post_spec.rb
|