telephone 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/README.md +139 -0
- data/lib/telephone.rb +3 -0
- data/lib/telephone/service.rb +75 -0
- data/lib/telephone/version.rb +5 -0
- metadata +63 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 2961c1545d60c8daef9cdc90a8ecea01c12ecd14357d446dbfe86cae84cc43c2
|
4
|
+
data.tar.gz: 27dad4361e48e380776fb3c32ea59855f95804e024b1aad879d84ad292f96a23
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 70159c4118b77a694873f4cf9f14d28bfbaae52692c28eaa95eafec80b06a91e8fd65dd76db1a849efdd5e7b5a294c5d1836a5b924c6df81eb9b9a636145c14e
|
7
|
+
data.tar.gz: 2bd95f410bc0bc92960c1e6065ecf5b0971dbc6792dff760cebef1494d1cdbc8efd5e87499d53a7eaae1786f8904a4280b570c9d59327995877a17fad20a8773
|
data/README.md
ADDED
@@ -0,0 +1,139 @@
|
|
1
|
+
# Telephone ☎️
|
2
|
+
|
3
|
+

|
4
|
+
|
5
|
+
Telephone is a light weight utility that helps you create and call service objects from anywhere within your application.
|
6
|
+
|
7
|
+
Telepone comes with a simple interface that helps with:
|
8
|
+
|
9
|
+
* Keeping your code DRY
|
10
|
+
* Encapsulating complex logic in a more readable way
|
11
|
+
* Making your code easier to test
|
12
|
+
* Gracefully handling errors and validations
|
13
|
+
|
14
|
+
## Installation
|
15
|
+
|
16
|
+
Add this line to your application's Gemfile:
|
17
|
+
|
18
|
+
```ruby
|
19
|
+
gem 'telephone'
|
20
|
+
```
|
21
|
+
|
22
|
+
And then execute:
|
23
|
+
|
24
|
+
$ bundle install
|
25
|
+
|
26
|
+
Or install it yourself as:
|
27
|
+
|
28
|
+
$ gem install telephone
|
29
|
+
|
30
|
+
## Usage
|
31
|
+
|
32
|
+
`Telephone::Service` is a simple utility class for creating and calling service objects. It allows you to define arguments and validations, and provides
|
33
|
+
a simple interface for calling the service and determining its success.
|
34
|
+
|
35
|
+
To start, define an `ApplicationService` and inherit from `Telephone::Service`.
|
36
|
+
|
37
|
+
```ruby
|
38
|
+
# /app/services/application_service.rb
|
39
|
+
|
40
|
+
class ApplicationService < Telephone::Service
|
41
|
+
end
|
42
|
+
```
|
43
|
+
|
44
|
+
A very simple example of a service object:
|
45
|
+
|
46
|
+
```ruby
|
47
|
+
class SimpleExample < ApplicationService
|
48
|
+
def call
|
49
|
+
"Hello World"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
s = SimpleExample.call #=> <#SimpleExample @result="Hello World">
|
54
|
+
s.success? #=> true
|
55
|
+
s.result #=> "Hello World"
|
56
|
+
```
|
57
|
+
|
58
|
+
### Arguments
|
59
|
+
|
60
|
+
You can define arguments for the service object. These arguments will be passed to the service object's `call` method, and will be available as an attribute.
|
61
|
+
|
62
|
+
```ruby
|
63
|
+
class SimpleExample < ApplicationService
|
64
|
+
argument :name
|
65
|
+
|
66
|
+
def call
|
67
|
+
"Hello, #{name}."
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
SimpleExample.call(name: "Benjamin").result #=> "Hello, Benjamin."
|
72
|
+
```
|
73
|
+
|
74
|
+
Arguments can also be required, which will prevent the service object from executing unless they are present.
|
75
|
+
|
76
|
+
```ruby
|
77
|
+
class SimpleExample < ApplicationService
|
78
|
+
argument :name, required: true
|
79
|
+
|
80
|
+
def call
|
81
|
+
"Hello, #{name}."
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
s = SimpleExample.call
|
86
|
+
s.success? #=> false
|
87
|
+
s.errors.full_messages #=> ["Name can't be blank"]
|
88
|
+
s.result #=> nil
|
89
|
+
```
|
90
|
+
|
91
|
+
You can also give a default value for an argument.
|
92
|
+
|
93
|
+
```ruby
|
94
|
+
argument :name, default: "Benjamin"
|
95
|
+
```
|
96
|
+
|
97
|
+
### Validations
|
98
|
+
|
99
|
+
Since `Telephone::Service` includes `ActiveModel::Model`, you can define validations in the same way you would for an ActiveRecord model.
|
100
|
+
|
101
|
+
```ruby
|
102
|
+
validates :name, format: { with: /\A[a-zA-Z]+\z/ }
|
103
|
+
validate :admin_user?
|
104
|
+
|
105
|
+
def admin_user?
|
106
|
+
errors.add(:user, "not admin") unless user.admin?
|
107
|
+
end
|
108
|
+
```
|
109
|
+
|
110
|
+
If a validation fails, the service object will not execute and return `nil` as the result of th call. You can check the status of the service object by calling `success?`.
|
111
|
+
|
112
|
+
```ruby
|
113
|
+
s = SomeService.call
|
114
|
+
s.success? #=> false
|
115
|
+
```
|
116
|
+
|
117
|
+
## Best Practices
|
118
|
+
|
119
|
+
Service objects are a great way to keep your code DRY and encapsulate business logic. As a rule of thumb, try to keep your service objects to a single responsibility. If you find yourself dealing with very complex logic, consider breaking it up into smaller services.
|
120
|
+
|
121
|
+
## Development
|
122
|
+
|
123
|
+
After checking out the repo, run `bin/setup` to install dependencies. This will install the dependencies for each subgem and run the entire test suite.
|
124
|
+
|
125
|
+
To experiment, you can run `bin/console` for an interactive prompt.
|
126
|
+
|
127
|
+
### Documentation
|
128
|
+
|
129
|
+
This project is documented using YARD. All code should be well documented via the YARD syntax prior to merging.
|
130
|
+
|
131
|
+
You can access the docmentation by starting up the YARD server.
|
132
|
+
|
133
|
+
```sh
|
134
|
+
yard server --reload
|
135
|
+
```
|
136
|
+
|
137
|
+
The `--reload`, or `-r`, flag tells the server to auto reload the documentation on each request.
|
138
|
+
|
139
|
+
Once the server is running, the documentation will by available at http://localhost:8808
|
data/lib/telephone.rb
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_model"
|
4
|
+
|
5
|
+
module Telephone
|
6
|
+
class Service
|
7
|
+
include ActiveModel::Model
|
8
|
+
|
9
|
+
##
|
10
|
+
# The primary outcome of the service object. For consistency,
|
11
|
+
# all service objects always return +self+. If you need a value
|
12
|
+
# returned, the return value of +#call+ will be available on the
|
13
|
+
# attribute +@result+.
|
14
|
+
#
|
15
|
+
# @example
|
16
|
+
# Telephone::Service.call(foo: bar).result # "baz"
|
17
|
+
attr_accessor :result
|
18
|
+
|
19
|
+
##
|
20
|
+
# Determines whether or not the action of the service
|
21
|
+
# object was successful.
|
22
|
+
#
|
23
|
+
# @example
|
24
|
+
# Telephone::Service.call(foo: bar).success? # true
|
25
|
+
#
|
26
|
+
# @return [Boolean] whether or not the action succeeded.
|
27
|
+
def success?
|
28
|
+
errors.empty?
|
29
|
+
end
|
30
|
+
|
31
|
+
class << self
|
32
|
+
##
|
33
|
+
# Defines a getter/setter for a service object argument. This also allows you
|
34
|
+
# to pass in a default, or set the argument to "required" to add a validation
|
35
|
+
# that runs before executing the block.
|
36
|
+
#
|
37
|
+
# @example
|
38
|
+
# class SomeService < Telephone::Service
|
39
|
+
# argument :foo, default: "bar"
|
40
|
+
# argument :baz, required: true
|
41
|
+
#
|
42
|
+
# def call
|
43
|
+
# puts foo
|
44
|
+
# puts baz
|
45
|
+
# end
|
46
|
+
# end
|
47
|
+
def argument(arg, default: nil, required: false)
|
48
|
+
send(:attr_accessor, arg.to_sym)
|
49
|
+
send(:validates, arg.to_sym, presence: true) if required
|
50
|
+
|
51
|
+
defaults[arg.to_sym] = default
|
52
|
+
end
|
53
|
+
|
54
|
+
##
|
55
|
+
# Used to maintain a list of default values to set prior to initialization
|
56
|
+
# based on the options in #argument.
|
57
|
+
def defaults
|
58
|
+
@defaults ||= {}
|
59
|
+
end
|
60
|
+
|
61
|
+
##
|
62
|
+
# Executes the service object action directly from the class — similar to the
|
63
|
+
# way a Proc can be executed with `Proc#call`. This allows us to add some common
|
64
|
+
# logic around running validations and setting argument defaults.
|
65
|
+
#
|
66
|
+
# @example
|
67
|
+
# Telephone::Service.call(foo: bar)
|
68
|
+
def call(**args)
|
69
|
+
instance = new(defaults.merge(args))
|
70
|
+
instance.result = instance.call if instance.valid?
|
71
|
+
instance
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
metadata
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: telephone
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Benjamin Hargett
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2021-07-31 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activemodel
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
description: Utility class for creating and calling service objects.
|
28
|
+
email: hargettbenjamin@gmail.com
|
29
|
+
executables: []
|
30
|
+
extensions: []
|
31
|
+
extra_rdoc_files: []
|
32
|
+
files:
|
33
|
+
- README.md
|
34
|
+
- lib/telephone.rb
|
35
|
+
- lib/telephone/service.rb
|
36
|
+
- lib/telephone/version.rb
|
37
|
+
homepage: https://github.com/bharget/telephone
|
38
|
+
licenses: []
|
39
|
+
metadata:
|
40
|
+
bug_tracker_uri: https://github.com/bharget/telephone/issues
|
41
|
+
changelog_uri: https://github.com/bharget/telephone/blob/master/CHANGELOG.md
|
42
|
+
source_code_uri: https://github.com/bharget/telephone
|
43
|
+
post_install_message:
|
44
|
+
rdoc_options: []
|
45
|
+
require_paths:
|
46
|
+
- lib
|
47
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
48
|
+
requirements:
|
49
|
+
- - ">="
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
version: 2.6.0
|
52
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: '0'
|
57
|
+
requirements:
|
58
|
+
- none
|
59
|
+
rubygems_version: 3.0.3
|
60
|
+
signing_key:
|
61
|
+
specification_version: 4
|
62
|
+
summary: Utility class for creating and calling service objects.
|
63
|
+
test_files: []
|