toolbelt 0.0.1.pre → 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +3 -1
- data/README.md +54 -0
- data/lib/toolbelt.rb +8 -0
- data/lib/toolbelt/policy.rb +25 -0
- data/lib/toolbelt/service.rb +17 -0
- data/lib/toolbelt/version.rb +1 -1
- data/spec/lib/toolbelt/policy_spec.rb +33 -0
- data/spec/lib/toolbelt/service_spec.rb +23 -0
- data/spec/lib/toolbelt/version_spec.rb +1 -1
- data/spec/spec_helper.rb +3 -3
- data/toolbelt.gemspec +2 -2
- metadata +12 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a7afd7745cf8454490939df0c70494c9607e56d7
|
4
|
+
data.tar.gz: 4cf8e403fd73e10e5f38d7574d607d8285919140
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 460ce56fd6d50ccd4638ea447847bcf728112a76678b8e17ac7de8143e2f5de7f3d243b7b58a422ff338a2ddc84af42dacb57346d89d6ca12e9a050a46062901
|
7
|
+
data.tar.gz: 6f403237c9310f9d5a356dcecac2ae692ce9326cbd734ac67608b8125e17ae4434d2f0a3fc5f574e4fb8e0e4dfca81e53c783518222c213668b78d961179a33a
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -6,6 +6,17 @@
|
|
6
6
|
|
7
7
|
A collection of POROs to use in your applications.
|
8
8
|
|
9
|
+
## Why?
|
10
|
+
|
11
|
+
The objects contained within this library represent the most common types of objects used in our Ruby and Rails applications. They exist to keep models and controllers thin and make our domain logic easy to test. Additionally, including these base objects in a library makes re-use clean and simple, eliminating a lot of the boilerplate/duplicate that has historically existed in our applications.
|
12
|
+
|
13
|
+
## What's Included?
|
14
|
+
|
15
|
+
There are several kinds of objects included in this library. They include:
|
16
|
+
|
17
|
+
* Service
|
18
|
+
* Policy
|
19
|
+
|
9
20
|
## Installation
|
10
21
|
|
11
22
|
`gem install toolbelt`
|
@@ -24,6 +35,49 @@ Make sure you require the library.
|
|
24
35
|
require 'toolbelt'
|
25
36
|
```
|
26
37
|
|
38
|
+
### Service Objects
|
39
|
+
|
40
|
+
Service objects should be used any time you want to abstract an operating that _does_ something. That something can be a write to the database, sending of email, retrieval of data from an API, etc. These objects accept a hash of options and only require that you implement a single method, `#call`. The class method `.call` exists as a convenience so you can write `MyService.call` instead of `MyService.new.call`.
|
41
|
+
|
42
|
+
``` ruby
|
43
|
+
class CreateWidgetService < Toolbelt::Service
|
44
|
+
def call
|
45
|
+
widget = Widget.new(:name => options.name)
|
46
|
+
if widget.save
|
47
|
+
AdminMailer.new_widget_notification.deliver
|
48
|
+
else
|
49
|
+
AdminMailer.widget_creation_error_notification.deliver
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
CreateWidgetService.call(:name => 'FooBar')
|
55
|
+
```
|
56
|
+
|
57
|
+
### Policy Objects
|
58
|
+
|
59
|
+
Policy objects exist to encapsulate business logic that needs to be verified within your application. These objects accept a hash of options and only require that you implement a single method `#pass?`. For scenarios when you want to ask the policy if it's failing, a `#fail?` method exists which simply returns the inverse of `#pass?`. There are corresponding class methods `.pass?` and `.fail?` for your convenience as well.
|
60
|
+
|
61
|
+
``` ruby
|
62
|
+
class ValidWidgetPolicy < Toolbelt::Service
|
63
|
+
def call
|
64
|
+
Widget.new(options).valid?
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
ValidWidgetPolicy.pass?(:name => 'FooBar')
|
69
|
+
# => true
|
70
|
+
ValidWidgetPolicy.fail?(:name => 'FooBar')
|
71
|
+
# => false
|
72
|
+
```
|
73
|
+
|
74
|
+
## Credit
|
75
|
+
|
76
|
+
Many of the concepts this library uses are beautifully explained in the following articles:
|
77
|
+
|
78
|
+
* [@brynary's](https://twitter.com/brynary) post ["7 Patterns to Refactor Fat ActiveRecord Models"](http://blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models/).
|
79
|
+
* [@createbang's](https://twitter.com/createbang) series of articles ["7 Patterns to Refactor JavaScript Applications"](http://journal.crushlovely.com/post/88286828068/7-patterns-to-refactor-javascript-applications-value)
|
80
|
+
|
27
81
|
## Contributing to toolbelt
|
28
82
|
|
29
83
|
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
|
data/lib/toolbelt.rb
CHANGED
@@ -0,0 +1,25 @@
|
|
1
|
+
module Toolbelt
|
2
|
+
class Policy
|
3
|
+
attr_reader :options
|
4
|
+
|
5
|
+
def self.pass?(options = {})
|
6
|
+
new(options).pass?
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.fail?(options = {})
|
10
|
+
new(options).fail?
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize(options = {})
|
14
|
+
@options = Hashie::Mash.new(options)
|
15
|
+
end
|
16
|
+
|
17
|
+
def pass?
|
18
|
+
fail Toolbelt::OverrideInSubclassError
|
19
|
+
end
|
20
|
+
|
21
|
+
def fail?
|
22
|
+
!pass?
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Toolbelt
|
2
|
+
class Service
|
3
|
+
attr_reader :options
|
4
|
+
|
5
|
+
def self.call(options = {})
|
6
|
+
new(options).call
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize(options = {})
|
10
|
+
@options = Hashie::Mash.new(options)
|
11
|
+
end
|
12
|
+
|
13
|
+
def call
|
14
|
+
fail Toolbelt::OverrideInSubclassError
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/toolbelt/version.rb
CHANGED
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Toolbelt::Policy' do
|
4
|
+
class ValidWidget < Toolbelt::Policy
|
5
|
+
def pass?
|
6
|
+
true
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
describe '.pass?' do
|
11
|
+
context 'when interacted with on the base class' do
|
12
|
+
it 'raises an exception' do
|
13
|
+
expect { Toolbelt::Policy.pass? }
|
14
|
+
.to raise_error { Toolbelt::OverrideInSubclassError }
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe 'when properly overriden from a subclass' do
|
19
|
+
subject { ValidWidget.pass? }
|
20
|
+
it { should eq(true) }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe '.fail?' do
|
25
|
+
describe 'when properly overriden from a subclass' do
|
26
|
+
let(:policy) { ValidWidget.new }
|
27
|
+
|
28
|
+
it 'returns the opposite of #pass?' do
|
29
|
+
expect(policy.fail?).to eq(!policy.pass?)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Toolbelt::Service' do
|
4
|
+
class CreateWidget < Toolbelt::Service
|
5
|
+
def call
|
6
|
+
true
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
describe '.call' do
|
11
|
+
context 'when interacted with on the base class' do
|
12
|
+
it 'raises an exception' do
|
13
|
+
expect { Toolbelt::Service.call }
|
14
|
+
.to raise_error { Toolbelt::OverrideInSubclassError }
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe 'when properly overriden from a subclass' do
|
19
|
+
subject { CreateWidget.call }
|
20
|
+
it { should eq(true) }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require 'codeclimate-test-reporter'
|
2
2
|
CodeClimate::TestReporter.start
|
3
3
|
|
4
4
|
require 'rspec'
|
@@ -6,5 +6,5 @@ require 'toolbelt'
|
|
6
6
|
|
7
7
|
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
|
8
8
|
|
9
|
-
RSpec.configure do |config|
|
10
|
-
end
|
9
|
+
# RSpec.configure do |config|
|
10
|
+
# end
|
data/toolbelt.gemspec
CHANGED
@@ -10,8 +10,8 @@ Gem::Specification.new do |spec|
|
|
10
10
|
spec.authors = ['PJ Kelly']
|
11
11
|
spec.email = ['pj@crushlovely.com']
|
12
12
|
spec.homepage = 'https://github.com/crushlovely/toolbelt'
|
13
|
-
spec.summary = '
|
14
|
-
spec.description = '
|
13
|
+
spec.summary = 'A collection of POROs to use in your applications.'
|
14
|
+
spec.description = 'A collection of POROs to use in your applications.'
|
15
15
|
|
16
16
|
spec.rubyforge_project = 'toolbelt'
|
17
17
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: toolbelt
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.1
|
4
|
+
version: 0.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- PJ Kelly
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-08-
|
11
|
+
date: 2014-08-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: hashie
|
@@ -150,8 +150,7 @@ dependencies:
|
|
150
150
|
- - '>='
|
151
151
|
- !ruby/object:Gem::Version
|
152
152
|
version: '0'
|
153
|
-
description:
|
154
|
-
S3.
|
153
|
+
description: A collection of POROs to use in your applications.
|
155
154
|
email:
|
156
155
|
- pj@crushlovely.com
|
157
156
|
executables: []
|
@@ -169,7 +168,11 @@ files:
|
|
169
168
|
- README.md
|
170
169
|
- Rakefile
|
171
170
|
- lib/toolbelt.rb
|
171
|
+
- lib/toolbelt/policy.rb
|
172
|
+
- lib/toolbelt/service.rb
|
172
173
|
- lib/toolbelt/version.rb
|
174
|
+
- spec/lib/toolbelt/policy_spec.rb
|
175
|
+
- spec/lib/toolbelt/service_spec.rb
|
173
176
|
- spec/lib/toolbelt/version_spec.rb
|
174
177
|
- spec/lib/toolbelt_spec.rb
|
175
178
|
- spec/spec_helper.rb
|
@@ -188,16 +191,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
188
191
|
version: '0'
|
189
192
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
190
193
|
requirements:
|
191
|
-
- - '
|
194
|
+
- - '>='
|
192
195
|
- !ruby/object:Gem::Version
|
193
|
-
version:
|
196
|
+
version: '0'
|
194
197
|
requirements: []
|
195
198
|
rubyforge_project: toolbelt
|
196
199
|
rubygems_version: 2.0.3
|
197
200
|
signing_key:
|
198
201
|
specification_version: 4
|
199
|
-
summary:
|
202
|
+
summary: A collection of POROs to use in your applications.
|
200
203
|
test_files:
|
204
|
+
- spec/lib/toolbelt/policy_spec.rb
|
205
|
+
- spec/lib/toolbelt/service_spec.rb
|
201
206
|
- spec/lib/toolbelt/version_spec.rb
|
202
207
|
- spec/lib/toolbelt_spec.rb
|
203
208
|
- spec/spec_helper.rb
|