telephone 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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
+ ![](https://github.com/bharget/telephone/actions/workflows/ci.yml/badge.svg)
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,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "telephone/service"
@@ -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
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Telephone
4
+ VERSION = "0.1.0"
5
+ 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: []