simple-orm 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.
- checksums.yaml +7 -0
- data/README.md +0 -0
- data/lib/simple-orm.rb +0 -0
- data/lib/simple-orm/db.rb +61 -0
- data/lib/simple-orm/presenters.rb +208 -0
- data/spec/db_spec.rb +112 -0
- data/spec/presenters_spec.rb +166 -0
- data/spec/spec_helper.rb +0 -0
- metadata +78 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 59a7344e57f7b6ead0f7d01a44560bae74264ab4
|
4
|
+
data.tar.gz: b4fda3c6faf544e63922d4e055898d895ead01e8
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 59ddba5e0a9507c1ab2f81edc4c55e1c09cf4ef16dd8222346213aaa8d09c40e589df8c5ebf78b620415e489e20576016334c122cbe0b6ebfe30550786dbf236
|
7
|
+
data.tar.gz: 657f8ef0fabaa3dbd72cc1db1bc5b00776cf419d61c96b3ca76abb7a27e43f74f26a135a251201b20030437cbfd53878a55acd2fcf46038cb10bc084df56b55a
|
data/README.md
ADDED
File without changes
|
data/lib/simple-orm.rb
ADDED
File without changes
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'redis'
|
2
|
+
require 'ppt/presenters'
|
3
|
+
|
4
|
+
class PPT
|
5
|
+
module DB
|
6
|
+
def self.redis
|
7
|
+
@redis ||= Redis.new(driver: :hiredis)
|
8
|
+
end
|
9
|
+
|
10
|
+
class Entity
|
11
|
+
def self.presenter(klass = nil)
|
12
|
+
@presenter ||= klass
|
13
|
+
end
|
14
|
+
|
15
|
+
attr_reader :presenter
|
16
|
+
def initialize(values)
|
17
|
+
@presenter = self.class.presenter.new(values)
|
18
|
+
@is_new_record = true
|
19
|
+
end
|
20
|
+
|
21
|
+
def new_record?
|
22
|
+
@is_new_record
|
23
|
+
end
|
24
|
+
|
25
|
+
def values(stage = nil)
|
26
|
+
@presenter.values(stage)
|
27
|
+
end
|
28
|
+
|
29
|
+
def save
|
30
|
+
stage = self.new_record? ? :create : :update
|
31
|
+
self.values(stage).each do |key, value|
|
32
|
+
PPT::DB.redis.hset(self.key, key, value)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class User < Entity
|
38
|
+
presenter PPT::Presenters::User
|
39
|
+
|
40
|
+
def key
|
41
|
+
"users.#{@presenter.username}"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
class Developer < Entity
|
46
|
+
presenter PPT::Presenters::Developer
|
47
|
+
|
48
|
+
def key
|
49
|
+
"devs.#{@presenter.company}.#{@presenter.username}"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
class Story < Entity
|
54
|
+
presenter PPT::Presenters::Story
|
55
|
+
|
56
|
+
def key
|
57
|
+
"stories.#{@presenter.company}.#{@presenter.id}"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,208 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'ppt/extensions'
|
3
|
+
|
4
|
+
class PPT
|
5
|
+
module Presenters
|
6
|
+
class ValidationError < ::StandardError
|
7
|
+
end
|
8
|
+
|
9
|
+
class Validator
|
10
|
+
def initialize(message, &block)
|
11
|
+
@message, @block = message, block
|
12
|
+
end
|
13
|
+
|
14
|
+
def validate!(name, value)
|
15
|
+
unless @block.call(value)
|
16
|
+
raise ValidationError.new("Value of #{name} is invalid (value is #{value.inspect}).")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class Attribute
|
22
|
+
attr_accessor :instance
|
23
|
+
attr_reader :name
|
24
|
+
def initialize(name)
|
25
|
+
@name = name
|
26
|
+
@validators, @hooks = Array.new, Hash.new
|
27
|
+
end
|
28
|
+
|
29
|
+
# DSL
|
30
|
+
def private
|
31
|
+
@private = true
|
32
|
+
self
|
33
|
+
end
|
34
|
+
|
35
|
+
def required
|
36
|
+
@validators << Validator.new('is required') do |value|
|
37
|
+
value != nil && ! value.empty?
|
38
|
+
end
|
39
|
+
|
40
|
+
self
|
41
|
+
end
|
42
|
+
|
43
|
+
def validate(message, &block)
|
44
|
+
self.validators << Validator.new(message, &block)
|
45
|
+
self
|
46
|
+
end
|
47
|
+
|
48
|
+
def type(type)
|
49
|
+
@type = type
|
50
|
+
self
|
51
|
+
end
|
52
|
+
|
53
|
+
def default(value = nil, &block)
|
54
|
+
@hooks[:default] = value ? Proc.new { value } : block
|
55
|
+
self
|
56
|
+
end
|
57
|
+
|
58
|
+
def on_create(value = nil, &block)
|
59
|
+
@hooks[:on_create] = value ? Proc.new { value } : block
|
60
|
+
self
|
61
|
+
end
|
62
|
+
|
63
|
+
def on_update(value = nil, &block)
|
64
|
+
@hooks[:on_update] = value ? Proc.new { value } : block
|
65
|
+
self
|
66
|
+
end
|
67
|
+
|
68
|
+
# API
|
69
|
+
def private?
|
70
|
+
@private
|
71
|
+
end
|
72
|
+
|
73
|
+
def run_hook(name)
|
74
|
+
@hooks[name] && @instance.instance_eval(&@hooks[name])
|
75
|
+
end
|
76
|
+
|
77
|
+
def set(value)
|
78
|
+
if self.private?
|
79
|
+
raise "Attribute #{@name} is private!"
|
80
|
+
end
|
81
|
+
|
82
|
+
@value = value
|
83
|
+
end
|
84
|
+
|
85
|
+
def get(stage = nil)
|
86
|
+
if stage.nil?
|
87
|
+
@value ||= self.run_hook(:default)
|
88
|
+
elsif stage == :create
|
89
|
+
@value ||= self.run_hook(:on_create)
|
90
|
+
elsif stage == :update
|
91
|
+
@value ||= self.run_hook(:on_update)
|
92
|
+
else
|
93
|
+
raise ArgumentError.new("Attribute#get takes an optional argument which can be either :create or :update.")
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def validate!(stage = nil)
|
98
|
+
@validators.each do |validator|
|
99
|
+
validator.validate!(self.name, self.get(stage))
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
class Entity
|
105
|
+
def self.attributes
|
106
|
+
@attributes ||= Hash.new
|
107
|
+
end
|
108
|
+
|
109
|
+
def self.attribute(name, options = Hash.new)
|
110
|
+
self.attributes[name] = Attribute.new(name)
|
111
|
+
end
|
112
|
+
|
113
|
+
def initialize(values = Hash.new)
|
114
|
+
# Let's consider it safe since this is not user input.
|
115
|
+
# It might not be the best idea, but for now, who cares.
|
116
|
+
values = PPT.symbolise_keys(values)
|
117
|
+
|
118
|
+
values.each do |key, value|
|
119
|
+
unless attribute = self.attributes[key]
|
120
|
+
raise ArgumentError.new("No such attribute: #{key}")
|
121
|
+
end
|
122
|
+
|
123
|
+
attribute.set(value)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
def attributes
|
128
|
+
@attributes ||= self.class.attributes.reduce(Hash.new) do |buffer, (name, attribute)|
|
129
|
+
buffer.merge(name => attribute.dup.tap { |attribute| attribute.instance = self })
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def method_missing(name, *args, &block)
|
134
|
+
if self.attributes.has_key?(name)
|
135
|
+
self.attributes[name].get
|
136
|
+
elsif name[-1] == '=' && self.attributes.has_key?(name.to_s[0..-2].to_sym)
|
137
|
+
self.attributes[name.to_s[0..-2].to_sym].set(args.first)
|
138
|
+
else
|
139
|
+
super(name, *args, &block)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def respond_to_missing?(name, include_private = false)
|
144
|
+
self.attributes.has_key?(name) ||
|
145
|
+
name[-1] == '=' && self.attributes.has_key?(name.to_s[0..-2].to_sym) ||
|
146
|
+
super(name, include_private)
|
147
|
+
end
|
148
|
+
|
149
|
+
def values(stage = nil)
|
150
|
+
self.attributes.reduce(Hash.new) do |buffer, (name, attribute)|
|
151
|
+
value = attribute.get(stage)
|
152
|
+
buffer[name] = value if value && value != ''
|
153
|
+
buffer
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
def to_json
|
158
|
+
self.values.to_json
|
159
|
+
end
|
160
|
+
|
161
|
+
def validate
|
162
|
+
self.attributes.each do |_, attribute|
|
163
|
+
attribute.validate!
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
# User is either a person or most likely a company.
|
169
|
+
#
|
170
|
+
# Each user can have only one service, just to make it simple.
|
171
|
+
# Besides, not many people use both Jira and Pivotal Tracker.
|
172
|
+
require 'securerandom'
|
173
|
+
|
174
|
+
class User < Entity
|
175
|
+
attribute(:service).required
|
176
|
+
attribute(:username).required
|
177
|
+
attribute(:name).required
|
178
|
+
attribute(:email).required
|
179
|
+
attribute(:accounting_email).default { self.email }
|
180
|
+
attribute(:auth_key).private.default { SecureRandom.hex }
|
181
|
+
|
182
|
+
attribute(:created_at).type(Time).on_create { Time.now.utc.to_i }
|
183
|
+
attribute(:updated_at).type(Time).on_update { Time.now.utc.to_i }
|
184
|
+
end
|
185
|
+
|
186
|
+
class Developer < Entity
|
187
|
+
attribute(:company).required
|
188
|
+
attribute(:username).required
|
189
|
+
attribute(:name).required
|
190
|
+
attribute(:email).required
|
191
|
+
|
192
|
+
attribute(:created_at).type(Time).on_create { Time.now.utc.to_i }
|
193
|
+
attribute(:updated_at).type(Time).on_update { Time.now.utc.to_i }
|
194
|
+
end
|
195
|
+
|
196
|
+
class Story < Entity
|
197
|
+
attribute(:company).required
|
198
|
+
attribute(:id).required
|
199
|
+
attribute(:title).required
|
200
|
+
attribute(:price).required
|
201
|
+
attribute(:currency).required
|
202
|
+
attribute(:link).required
|
203
|
+
|
204
|
+
attribute(:created_at).type(Time).on_create { Time.now.utc.to_i }
|
205
|
+
attribute(:updated_at).type(Time).on_update { Time.now.utc.to_i }
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
data/spec/db_spec.rb
ADDED
@@ -0,0 +1,112 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'ppt/db'
|
3
|
+
|
4
|
+
describe PPT::DB do
|
5
|
+
let(:redis) { Redis.new(driver: :hiredis) }
|
6
|
+
|
7
|
+
before(:each) do
|
8
|
+
redis.flushdb
|
9
|
+
Time.stub(:now) { Time.at(1403347217) }
|
10
|
+
end
|
11
|
+
|
12
|
+
describe PPT::DB::Entity do
|
13
|
+
let(:subclass) do
|
14
|
+
Class.new(described_class) do |klass|
|
15
|
+
attribute(:id).required
|
16
|
+
attribute(:username).required
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe PPT::DB::User do
|
22
|
+
subject { described_class.new(attrs) }
|
23
|
+
|
24
|
+
let(:attrs) {{
|
25
|
+
service: 'pt',
|
26
|
+
username: 'ppt',
|
27
|
+
name: 'PayPerTask Ltd',
|
28
|
+
email: 'james@pay-per-task.com',
|
29
|
+
accounting_email: 'accounting@pay-per-task.com'
|
30
|
+
}}
|
31
|
+
|
32
|
+
describe '#key' do
|
33
|
+
it 'is users.username' do
|
34
|
+
expect(subject.key).to eq('users.ppt')
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe '#save' do
|
39
|
+
it 'saves data of its presenter as a Redis hash' do
|
40
|
+
subject.save
|
41
|
+
data = redis.hgetall(subject.key)
|
42
|
+
expect(data).to eq({'service' => 'pt',
|
43
|
+
'username' => 'ppt',
|
44
|
+
'name' => 'PayPerTask Ltd',
|
45
|
+
'email' => 'james@pay-per-task.com',
|
46
|
+
'accounting_email' => 'accounting@pay-per-task.com',
|
47
|
+
'created_at' => '1403347217'})
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe PPT::DB::Developer do
|
53
|
+
subject { described_class.new(attrs) }
|
54
|
+
|
55
|
+
let(:attrs) {{
|
56
|
+
company: 'ppt',
|
57
|
+
username: 'botanicus',
|
58
|
+
name: 'James C Russell',
|
59
|
+
email: 'contracts@101ideas.cz'
|
60
|
+
}}
|
61
|
+
|
62
|
+
describe '#key' do
|
63
|
+
it 'is devs.company.username' do
|
64
|
+
expect(subject.key).to eq('devs.ppt.botanicus')
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe '#save' do
|
69
|
+
it 'saves data of its presenter as a Redis hash' do
|
70
|
+
subject.save
|
71
|
+
data = redis.hgetall(subject.key)
|
72
|
+
expect(data).to eq({'company' => 'ppt',
|
73
|
+
'username' => 'botanicus',
|
74
|
+
'name' => 'James C Russell',
|
75
|
+
'email' => 'contracts@101ideas.cz',
|
76
|
+
'created_at' => '1403347217'})
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe PPT::DB::Story do
|
82
|
+
subject { described_class.new(attrs) }
|
83
|
+
|
84
|
+
let(:attrs) {{
|
85
|
+
company: 'ppt',
|
86
|
+
id: 957456,
|
87
|
+
price: 120,
|
88
|
+
currency: 'GBP',
|
89
|
+
link: 'http://www.pivotaltracker.com/story/show/60839620'
|
90
|
+
}}
|
91
|
+
|
92
|
+
describe '#key' do
|
93
|
+
it 'is stories.company.id' do
|
94
|
+
expect(subject.key).to eq('stories.ppt.957456')
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
describe '#save' do
|
99
|
+
it 'saves data of its presenter as a Redis hash' do
|
100
|
+
subject.save
|
101
|
+
data = redis.hgetall(subject.key)
|
102
|
+
expect(data).to eq({'company' => 'ppt',
|
103
|
+
'id' => '957456',
|
104
|
+
'price' => '120',
|
105
|
+
'currency' => 'GBP',
|
106
|
+
'link' => 'http://www.pivotaltracker.com/story/show/60839620',
|
107
|
+
'created_at' => '1403347217'})
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
@@ -0,0 +1,166 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'ppt/presenters'
|
3
|
+
|
4
|
+
describe PPT::Presenters do
|
5
|
+
describe PPT::Presenters::Entity do
|
6
|
+
let(:subclass) do
|
7
|
+
Class.new(described_class) do |klass|
|
8
|
+
attribute(:id).required
|
9
|
+
attribute(:username).required
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '#validate' do
|
14
|
+
it 'throws an error if whatever has been specified as required is missing' do
|
15
|
+
expect { subclass.new.validate }.to raise_error(PPT::Presenters::ValidationError)
|
16
|
+
expect { subclass.new(Hash.new).validate }.to raise_error(PPT::Presenters::ValidationError)
|
17
|
+
expect { subclass.new(username: 'botanicus').validate }.to raise_error(PPT::Presenters::ValidationError)
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'throws an error if there are any extra arguments' do
|
21
|
+
expect { subclass.new(id: 1, username: 'botanicus', extra: 'x') }.to raise_error(ArgumentError)
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'succeeds if just the right arguments have been provided' do
|
25
|
+
expect { subclass.new(id: 1, username: 'botanicus') }.not_to raise_error
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe '#values' do
|
30
|
+
it 'returns values as a hash' do
|
31
|
+
instance = subclass.new(id: 1, username: 'botanicus')
|
32
|
+
expect(instance.values[:id]).to eq(1)
|
33
|
+
expect(instance.values[:username]).to eq('botanicus')
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe 'accessors' do
|
38
|
+
it 'provides accessors for all the the attributes' do
|
39
|
+
instance = subclass.new(id: 1, username: 'botanicus')
|
40
|
+
expect(instance.id).to eq(1)
|
41
|
+
expect(instance.username).to eq('botanicus')
|
42
|
+
|
43
|
+
expect(instance.respond_to?(:username)).to be(true)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe '#to_json' do
|
48
|
+
it 'converts #values to JSON' do
|
49
|
+
instance = subclass.new(id: 1, username: 'botanicus')
|
50
|
+
expect(instance.to_json).to eq('{"id":1,"username":"botanicus"}')
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe PPT::Presenters::User do
|
56
|
+
let(:attrs) {{
|
57
|
+
service: 'pt',
|
58
|
+
username: 'ppt',
|
59
|
+
name: 'PayPerTask Ltd',
|
60
|
+
email: 'james@pay-per-task.com',
|
61
|
+
accounting_email: 'accounting@pay-per-task.com'
|
62
|
+
}}
|
63
|
+
|
64
|
+
it 'raises an exception if service is missing' do
|
65
|
+
instance = described_class.new(attrs.reject { |key, value| key == :service })
|
66
|
+
expect { instance.validate }.to raise_error(PPT::Presenters::ValidationError)
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'raises an exception if username is missing' do
|
70
|
+
instance = described_class.new(attrs.reject { |key, value| key == :username })
|
71
|
+
expect { instance.validate }.to raise_error(PPT::Presenters::ValidationError)
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'raises an exception if name is missing' do
|
75
|
+
instance = described_class.new(attrs.reject { |key, value| key == :name })
|
76
|
+
expect { instance.validate }.to raise_error(PPT::Presenters::ValidationError)
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'raises an exception if email is missing' do
|
80
|
+
instance = described_class.new(attrs.reject { |key, value| key == :email })
|
81
|
+
expect { instance.validate }.to raise_error(PPT::Presenters::ValidationError)
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'returns a valid presenter if all the required arguments have been provided' do
|
85
|
+
expect { described_class.new(attrs).validate }.to_not raise_error
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
describe PPT::Presenters::Developer do
|
90
|
+
let(:attrs) {{
|
91
|
+
company: 'ppt',
|
92
|
+
username: 'botanicus',
|
93
|
+
name: 'James C Russell',
|
94
|
+
email: 'contracts@101ideas.cz'
|
95
|
+
}}
|
96
|
+
|
97
|
+
it 'raises an exception if company is missing' do
|
98
|
+
instance = described_class.new(attrs.reject { |key, value| key == :company })
|
99
|
+
expect { instance.validate }.to raise_error(PPT::Presenters::ValidationError)
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'raises an exception if username is missing' do
|
103
|
+
instance = described_class.new(attrs.reject { |key, value| key == :username })
|
104
|
+
expect { instance.validate }.to raise_error(PPT::Presenters::ValidationError)
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'raises an exception if name is missing' do
|
108
|
+
instance = described_class.new(attrs.reject { |key, value| key == :name })
|
109
|
+
expect { instance.validate }.to raise_error(PPT::Presenters::ValidationError)
|
110
|
+
end
|
111
|
+
|
112
|
+
it 'raises an exception if email is missing' do
|
113
|
+
instance = described_class.new(attrs.reject { |key, value| key == :email })
|
114
|
+
expect { instance.validate }.to raise_error(PPT::Presenters::ValidationError)
|
115
|
+
end
|
116
|
+
|
117
|
+
it 'returns a valid presenter if all the required arguments have been provided' do
|
118
|
+
expect { described_class.new(attrs).validate }.to_not raise_error
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
describe PPT::Presenters::Story do
|
123
|
+
let(:attrs) {{
|
124
|
+
company: 'ppt',
|
125
|
+
id: 957456,
|
126
|
+
title: 'Implement login',
|
127
|
+
price: 120,
|
128
|
+
currency: 'GBP',
|
129
|
+
link: 'http://www.pivotaltracker.com/story/show/60839620'
|
130
|
+
}}
|
131
|
+
|
132
|
+
it 'raises an exception if company is missing' do
|
133
|
+
instance = described_class.new(attrs.reject { |key, value| key == :company })
|
134
|
+
expect { instance.validate }.to raise_error(PPT::Presenters::ValidationError)
|
135
|
+
end
|
136
|
+
|
137
|
+
it 'raises an exception if id is missing' do
|
138
|
+
instance = described_class.new(attrs.reject { |key, value| key == :id })
|
139
|
+
expect { instance.validate }.to raise_error(PPT::Presenters::ValidationError)
|
140
|
+
end
|
141
|
+
|
142
|
+
it 'raises an exception if title is missing' do
|
143
|
+
instance = described_class.new(attrs.reject { |key, value| key == :title })
|
144
|
+
expect { instance.validate }.to raise_error(PPT::Presenters::ValidationError)
|
145
|
+
end
|
146
|
+
|
147
|
+
it 'raises an exception if price is missing' do
|
148
|
+
instance = described_class.new(attrs.reject { |key, value| key == :price })
|
149
|
+
expect { instance.validate }.to raise_error(PPT::Presenters::ValidationError)
|
150
|
+
end
|
151
|
+
|
152
|
+
it 'raises an exception if currency is missing' do
|
153
|
+
instance = described_class.new(attrs.reject { |key, value| key == :currency })
|
154
|
+
expect { instance.validate }.to raise_error(PPT::Presenters::ValidationError)
|
155
|
+
end
|
156
|
+
|
157
|
+
it 'raises an exception if link is missing' do
|
158
|
+
instance = described_class.new(attrs.reject { |key, value| key == :link })
|
159
|
+
expect { instance.validate }.to raise_error(PPT::Presenters::ValidationError)
|
160
|
+
end
|
161
|
+
|
162
|
+
it 'returns a valid presenter if all the required arguments have been provided' do
|
163
|
+
expect { described_class.new(attrs).validate }.to_not raise_error
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
data/spec/spec_helper.rb
ADDED
File without changes
|
metadata
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: simple-orm
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- https://github.com/botanicus
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-06-21 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: redis
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '3.1'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '3.1'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: hiredis
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0.5'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0.5'
|
41
|
+
description: A simple ORM. By default it stores to Redis hashes.
|
42
|
+
email: james@101ideas.cz
|
43
|
+
executables: []
|
44
|
+
extensions: []
|
45
|
+
extra_rdoc_files: []
|
46
|
+
files:
|
47
|
+
- README.md
|
48
|
+
- lib/simple-orm.rb
|
49
|
+
- lib/simple-orm/db.rb
|
50
|
+
- lib/simple-orm/presenters.rb
|
51
|
+
- spec/db_spec.rb
|
52
|
+
- spec/presenters_spec.rb
|
53
|
+
- spec/spec_helper.rb
|
54
|
+
homepage: https://github.com/botanicus/simple-orm
|
55
|
+
licenses:
|
56
|
+
- MIT
|
57
|
+
metadata: {}
|
58
|
+
post_install_message:
|
59
|
+
rdoc_options: []
|
60
|
+
require_paths:
|
61
|
+
- lib
|
62
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
63
|
+
requirements:
|
64
|
+
- - '>='
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '0'
|
67
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
68
|
+
requirements:
|
69
|
+
- - '>='
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: '0'
|
72
|
+
requirements: []
|
73
|
+
rubyforge_project: simple-orm
|
74
|
+
rubygems_version: 2.2.2
|
75
|
+
signing_key:
|
76
|
+
specification_version: 4
|
77
|
+
summary: Does what is says on the can. Nothing more, nothing less.
|
78
|
+
test_files: []
|