scoped-concerns 0.1.0
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/.gitignore +4 -0
- data/LICENSE.md +21 -0
- data/README.md +71 -0
- data/Rakefile +6 -0
- data/lib/.gitkeep +0 -0
- data/lib/scoped-concerns.rb +2 -0
- data/lib/scoped-concerns/concern.rb +25 -0
- data/lib/scoped-concerns/response.rb +19 -0
- data/ruby-version.sample +1 -0
- data/scoped-concerns.gemspec +15 -0
- data/test/concern/concern_test.rb +30 -0
- data/test/concern/response_test.rb +34 -0
- data/test/test_helper.rb +4 -0
- metadata +59 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 244c3ca326094f41d147f31cfd45f6335fa601e7d99bd6fe477f8c429bbd0657
|
4
|
+
data.tar.gz: cc65ed38693ddfe83c6fffc4993f54836a55cb51521697cf7c3d69bbeb942100
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 63a38e08a0bf82682854a5491319e55dac9185125663b47a379d9748fb71a60bd04767dc376f0d4e4a99cb394455f801bb4529869e7b056454fa48bbc880e467
|
7
|
+
data.tar.gz: 76ceec63edf7e391b8ea15aee64b35028e4b8e49a15e186e4944575a84e421a9c355037a88798f0b9cf46f629b3be2f889a8ff866f8ae8c945fde6b695a7b3c0
|
data/.gitignore
ADDED
data/LICENSE.md
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2017 Three Funky Monkeys
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
# Scoped Concerns
|
2
|
+
|
3
|
+
Scoped-Concerns is a tiny utility library to help you encapsulate responsibilities in your Ruby applications by providing a common interface and a common response object for the so called _service classes_ or how we like to call them: _concerns_.
|
4
|
+
|
5
|
+
We've been playing around with this concept in a few applications and it was evolving until this point that we feel it reusable enough to become a separated library.
|
6
|
+
|
7
|
+
## Install
|
8
|
+
|
9
|
+
It's a Ruby gem in rubygems.org, so is as simple as:
|
10
|
+
|
11
|
+
```
|
12
|
+
gem install scoped-concerns
|
13
|
+
```
|
14
|
+
|
15
|
+
## Usage
|
16
|
+
|
17
|
+
Include `Scoped::Concern` in your service (concern) class, and implement your constructor and the `run` methods with the logic for your domain. For example
|
18
|
+
|
19
|
+
```Ruby
|
20
|
+
module MyApp
|
21
|
+
module Concerns
|
22
|
+
class ActivateUser
|
23
|
+
include Scoped::Concern
|
24
|
+
|
25
|
+
def initialize(params = {})
|
26
|
+
@user_id = params[:user_id]
|
27
|
+
end
|
28
|
+
|
29
|
+
def run
|
30
|
+
user = User.find(@user_id)
|
31
|
+
return error(user: [:not_valid]) unless user
|
32
|
+
|
33
|
+
begin
|
34
|
+
user.activate!
|
35
|
+
success(user: "Activated")
|
36
|
+
rescue => e
|
37
|
+
logger.log(e.message)
|
38
|
+
error(update: [:not_valid])
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
```
|
45
|
+
|
46
|
+
Then you can use this concern in your endpoints logic, like:
|
47
|
+
|
48
|
+
```Ruby
|
49
|
+
on "activate/:id" do |id|
|
50
|
+
response = MyApp::Concerns::ActivateUser.run(user_id: id)
|
51
|
+
|
52
|
+
if response.success?
|
53
|
+
json(message: "User has been activated")
|
54
|
+
else
|
55
|
+
json_error(message: [response.errors[:update], response.errors[:user]].join("\n"))
|
56
|
+
end
|
57
|
+
end
|
58
|
+
```
|
59
|
+
|
60
|
+
`Scoped-Concerns` provides the `run`, `error` and `success` helper methods through `Concern` module and the `Scoped::Response` class as a standard response format.
|
61
|
+
|
62
|
+
`Scoped-Concerns` proposes the following conventions:
|
63
|
+
|
64
|
+
* Parameters to a concern should always be a `Hash`, even if you need only one parameter (see example above)
|
65
|
+
* A `Concern` should always return a `Scoped::Response` object. (`success` and `error` helper methods return this)
|
66
|
+
|
67
|
+
### Response
|
68
|
+
|
69
|
+
The `Scoped::Response` class has the `result` and `errors` attributes, both of them must be hashes. The keys of these `Hash`es will depend on your application domain, but, at least, you know that you'll deal with `Hash`es.
|
70
|
+
|
71
|
+
The `Scoped::Response` class also has a `success?` instance utility method that is a wrapper to `@errors.empty?` for readability's sake.
|
data/Rakefile
ADDED
data/lib/.gitkeep
ADDED
File without changes
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Scoped
|
2
|
+
module Concern
|
3
|
+
def self.included(base)
|
4
|
+
base.send :include, InstanceMethods
|
5
|
+
base.extend ClassMethods
|
6
|
+
end
|
7
|
+
|
8
|
+
module ClassMethods
|
9
|
+
def run(params = {})
|
10
|
+
instance = new(params)
|
11
|
+
instance.run
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
module InstanceMethods
|
16
|
+
def success(results = {})
|
17
|
+
Response.new(result: results)
|
18
|
+
end
|
19
|
+
|
20
|
+
def error(errors = {})
|
21
|
+
Response.new(errors: errors)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Scoped
|
2
|
+
class InvalidType < RuntimeError;end
|
3
|
+
|
4
|
+
class Response
|
5
|
+
attr_accessor :result, :errors
|
6
|
+
|
7
|
+
def initialize(result: {}, errors: {})
|
8
|
+
raise InvalidType, "result must be a hash" unless result.is_a?(Hash)
|
9
|
+
raise InvalidType, "errors must be a hash" unless errors.is_a?(Hash)
|
10
|
+
|
11
|
+
@result = result
|
12
|
+
@errors = errors
|
13
|
+
end
|
14
|
+
|
15
|
+
def success?
|
16
|
+
@errors.empty?
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/ruby-version.sample
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.4.1
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = "scoped-concerns"
|
5
|
+
s.version = "0.1.0"
|
6
|
+
s.summary = "Gem for Pure Ruby Objects to encapsulate specific behavior"
|
7
|
+
s.license = "MIT"
|
8
|
+
s.description = "Gem for Pure Ruby Objects to encapsulate specific behavior"
|
9
|
+
s.authors = ["Leonardo Mateo", "Lautaro Orazi"]
|
10
|
+
s.email = ["kandalf@threefunkymonkeys.com", "taro@threefunkymonkeys.com"]
|
11
|
+
s.homepage = "https://github.com/threefunkymonkeys/scoped-concerns"
|
12
|
+
s.require_paths = ["lib"]
|
13
|
+
|
14
|
+
s.files = `git ls-files`.split("\n")
|
15
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require_relative '../test_helper'
|
2
|
+
|
3
|
+
class MyConcern
|
4
|
+
include Scoped::Concern
|
5
|
+
end
|
6
|
+
|
7
|
+
describe Scoped::Concern do
|
8
|
+
it "should add class run method" do
|
9
|
+
assert MyConcern.respond_to?(:run)
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should add instance success and error methods" do
|
13
|
+
concern = MyConcern.new
|
14
|
+
|
15
|
+
assert concern.respond_to?(:success)
|
16
|
+
assert concern.respond_to?(:error)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should return a Response instance with no errors" do
|
20
|
+
concern = MyConcern.new
|
21
|
+
result = { message: "Done" }
|
22
|
+
|
23
|
+
response = concern.success(result)
|
24
|
+
|
25
|
+
assert response.is_a?(Scoped::Response)
|
26
|
+
assert response.errors.empty?
|
27
|
+
|
28
|
+
assert_equal result, response.result
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require_relative '../test_helper'
|
2
|
+
|
3
|
+
describe Scoped::Response do
|
4
|
+
it "should expose result and errors" do
|
5
|
+
response = Scoped::Response.new
|
6
|
+
|
7
|
+
assert response.respond_to?(:result)
|
8
|
+
assert response.respond_to?(:errors)
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should not accept other than a Hash for result" do
|
12
|
+
assert_raises(Scoped::InvalidType, "result must be a Hash") do
|
13
|
+
Scoped::Response.new(result: "Hallo")
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should not accept other than a Hash for errors" do
|
18
|
+
assert_raises(Scoped::InvalidType, "result must be a Hash") do
|
19
|
+
Scoped::Response.new(errors: "Hallo")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should be successful if no errors" do
|
24
|
+
response = Scoped::Response.new(result: { message: "I'm successful" })
|
25
|
+
assert response.success?
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should not be successful if errors" do
|
29
|
+
response = Scoped::Response.new(result: { message: "I'm successful" },
|
30
|
+
errors: { success: "No, you're not" })
|
31
|
+
|
32
|
+
assert !response.success?
|
33
|
+
end
|
34
|
+
end
|
data/test/test_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: scoped-concerns
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Leonardo Mateo
|
8
|
+
- Lautaro Orazi
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2019-02-19 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: Gem for Pure Ruby Objects to encapsulate specific behavior
|
15
|
+
email:
|
16
|
+
- kandalf@threefunkymonkeys.com
|
17
|
+
- taro@threefunkymonkeys.com
|
18
|
+
executables: []
|
19
|
+
extensions: []
|
20
|
+
extra_rdoc_files: []
|
21
|
+
files:
|
22
|
+
- ".gitignore"
|
23
|
+
- LICENSE.md
|
24
|
+
- README.md
|
25
|
+
- Rakefile
|
26
|
+
- lib/.gitkeep
|
27
|
+
- lib/scoped-concerns.rb
|
28
|
+
- lib/scoped-concerns/concern.rb
|
29
|
+
- lib/scoped-concerns/response.rb
|
30
|
+
- ruby-version.sample
|
31
|
+
- scoped-concerns.gemspec
|
32
|
+
- test/concern/concern_test.rb
|
33
|
+
- test/concern/response_test.rb
|
34
|
+
- test/test_helper.rb
|
35
|
+
homepage: https://github.com/threefunkymonkeys/scoped-concerns
|
36
|
+
licenses:
|
37
|
+
- MIT
|
38
|
+
metadata: {}
|
39
|
+
post_install_message:
|
40
|
+
rdoc_options: []
|
41
|
+
require_paths:
|
42
|
+
- lib
|
43
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
49
|
+
requirements:
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '0'
|
53
|
+
requirements: []
|
54
|
+
rubyforge_project:
|
55
|
+
rubygems_version: 2.7.6
|
56
|
+
signing_key:
|
57
|
+
specification_version: 4
|
58
|
+
summary: Gem for Pure Ruby Objects to encapsulate specific behavior
|
59
|
+
test_files: []
|