service_objects_rails 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +8 -0
- data/LICENSE.txt +21 -0
- data/README.md +181 -0
- data/lib/generators/services/install_generator.rb +24 -0
- data/lib/generators/services/new_generator.rb +38 -0
- data/lib/generators/templates/new_service.erb +16 -0
- data/lib/generators/templates/new_service_spec.erb +13 -0
- data/lib/generators/templates/service_objects_rails_config.rb +12 -0
- data/lib/service_objects_rails.rb +16 -0
- data/lib/services/base.rb +24 -0
- data/lib/services/response.rb +19 -0
- data/lib/services/version.rb +3 -0
- data/service_objects_rails.gemspec +38 -0
- metadata +253 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: dfd8b349fec82efeaba05ceebd23dceb3f5b6b72840442cc7e4e5d22e219c89b
|
4
|
+
data.tar.gz: fcda7ca5e0417fcc890dc1e8867d6019af4c0dabf75d8b507065ab6b38fcf3ae
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c03cda7db0b3b27378a6eadb576e13b5fb022b8a4fa333a8bddf103b81c101319e8cdf0c8683451e859478f4c9f71ed8204447c047fe3a88a8d456f28fecb86c
|
7
|
+
data.tar.gz: 0554bf7e6ec1b43463c2928b5378fc0e0e608677c70f29ce54befc120e744c313908d90ef6fd9b24d929e4c4f42533cd78dc1b20146fb5fbb5f97be216a7a82a
|
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2022 Matthew
|
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,181 @@
|
|
1
|
+
# Service Objects for Rails
|
2
|
+
|
3
|
+
[![mattwd7](https://circleci.com/gh/mattwd7/service_objects_rails.svg?style=svg)](https://app.circleci.com/pipelines/github/mattwd7/service_objects_rails?filter=all)
|
4
|
+
[![Test Coverage](https://codecov.io/gh/mattwd7/service_objects_rails/graph/badge.svg)](https://codecov.io/gh/mattwd7/service_objects_rails)
|
5
|
+
|
6
|
+
A lightweight, high-speed service layer for Rails applications.
|
7
|
+
|
8
|
+
## Motivation
|
9
|
+
Gone are the days of fat controllers and fat models! Service objects (sometimes known as Commands) enable an important service layer in your Rails applications to keep your code readable, reusable, and testable. Service objects help to facilitate a separation of concerns and the single responsibility principle. Here is an example of a service object that adds a new user to a table in a poker application:
|
10
|
+
|
11
|
+
```
|
12
|
+
module Services
|
13
|
+
class AddPlayerToTable
|
14
|
+
include Services::Base
|
15
|
+
|
16
|
+
def initialize(user_id:, table_id:)
|
17
|
+
@user = User.find(user_id)
|
18
|
+
@table = Table.find(table_id)
|
19
|
+
end
|
20
|
+
|
21
|
+
def call
|
22
|
+
confirm_player_has_available_funds
|
23
|
+
assign_player_to_table
|
24
|
+
queue_player_for_next_deal
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
attr_reader :user, :table
|
30
|
+
|
31
|
+
def confirm_player_has_available_funds
|
32
|
+
# business logic
|
33
|
+
end
|
34
|
+
|
35
|
+
def assign_player_to_table
|
36
|
+
# business logic
|
37
|
+
end
|
38
|
+
|
39
|
+
def queue_player_for_next_deal
|
40
|
+
# business logic
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
```
|
45
|
+
Without this Service Object, our Rails models like User, Table, and Queue would require a knowledge of associated models and their logic, consequently bloating model classes and their tests. Instead, this Service Object orchestrates the necessary objects to perform the singular task of adding a player to a poker table.
|
46
|
+
|
47
|
+
## Installation
|
48
|
+
Include the gem in your Gemfile:
|
49
|
+
```
|
50
|
+
gem "service_objects_rails"
|
51
|
+
```
|
52
|
+
|
53
|
+
and install:
|
54
|
+
```
|
55
|
+
bundle install
|
56
|
+
```
|
57
|
+
|
58
|
+
Then generate boilerplate directories and gem configuration files with
|
59
|
+
```
|
60
|
+
rails generate services:install
|
61
|
+
```
|
62
|
+
|
63
|
+
This will create the `app/namespaces/services` directory which will hold the namespaced service objects you create and use in your application.
|
64
|
+
|
65
|
+
## Quick start
|
66
|
+
```
|
67
|
+
## generate a service
|
68
|
+
|
69
|
+
rails g services:new AddPlayerToTable user_id table_id
|
70
|
+
|
71
|
+
## write out and test the service
|
72
|
+
|
73
|
+
module Services
|
74
|
+
class AddPlayerToTable
|
75
|
+
include Services::Base
|
76
|
+
|
77
|
+
def initialize(user_id:, table_id:)
|
78
|
+
@user = User.find(user_id)
|
79
|
+
@table = Table.find(table_id)
|
80
|
+
end
|
81
|
+
|
82
|
+
def call
|
83
|
+
confirm_player_has_available_funds
|
84
|
+
assign_player_to_table
|
85
|
+
queue_player_for_next_deal
|
86
|
+
end
|
87
|
+
|
88
|
+
private
|
89
|
+
|
90
|
+
attr_reader :user, :table
|
91
|
+
|
92
|
+
def confirm_player_has_available_funds
|
93
|
+
# business logic
|
94
|
+
end
|
95
|
+
|
96
|
+
def assign_player_to_table
|
97
|
+
# business logic
|
98
|
+
end
|
99
|
+
|
100
|
+
def queue_player_for_next_deal
|
101
|
+
# business logic
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
## use the service
|
107
|
+
|
108
|
+
# app/controllers/tables_controller.rb
|
109
|
+
class TablesController < ApplicationController
|
110
|
+
def join_table
|
111
|
+
service_response = Services::AddPlayerToTable.call(
|
112
|
+
user_id: params[:user_id],
|
113
|
+
table_id: params[:table_id]
|
114
|
+
)
|
115
|
+
|
116
|
+
if service_response.success?
|
117
|
+
render :show, status: 204
|
118
|
+
else
|
119
|
+
render json: { errors: service_response.errors.full_messages }
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
```
|
124
|
+
|
125
|
+
## Usage
|
126
|
+
All service objects have the same skeleton: an `initialize` method, a `call` method, and an included `Services::Base` mixin. The `Services::Base` mixin enforces strict, predictable usage of service objects such that they
|
127
|
+
|
128
|
+
1. Are always called with named arguemnts
|
129
|
+
1. Can never be publicly instantiated; only `call`ed
|
130
|
+
1. Always return an instance of a Services::Response object
|
131
|
+
|
132
|
+
It is a best-practice to name service objects in the format <ACTION><NOUN> to abstract the responsibilty and function of the service at the highest level, e.g. `Services::AddPlayerToTable` as opposed to `Services::NewPlayerTable`.
|
133
|
+
|
134
|
+
### Using the Generator
|
135
|
+
To quickly whip up a new service object and corresponding spec, use the provided generator:
|
136
|
+
```
|
137
|
+
rails generate services:new <MyNewServiceName> <named_arg_1> <named_arg_2> ...
|
138
|
+
```
|
139
|
+
|
140
|
+
An example of using the generator:
|
141
|
+
```
|
142
|
+
rails g services:new AddPlayerToTable user_id table_id
|
143
|
+
|
144
|
+
# app/namespaces/services/add_player_to_table.rb
|
145
|
+
module Services
|
146
|
+
class AddPlayerToTable
|
147
|
+
include ServiceObject::Base
|
148
|
+
|
149
|
+
def initialize(user_id:, table_id:,)
|
150
|
+
@user_id = user_id
|
151
|
+
@table_id = table_id
|
152
|
+
end
|
153
|
+
|
154
|
+
def call
|
155
|
+
end
|
156
|
+
|
157
|
+
private
|
158
|
+
|
159
|
+
attr_reader :user_id, :table_id
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
|
164
|
+
# spec/namespaces/services/add_player_to_table_spec.rb
|
165
|
+
include "rails_helper"
|
166
|
+
|
167
|
+
RSpec.describe Services::AddPlayerToTable do
|
168
|
+
subject(:service_response) do
|
169
|
+
described_class.call(user_id: user_id, table_id: table_id)
|
170
|
+
end
|
171
|
+
|
172
|
+
let(:user_id) { nil }
|
173
|
+
let(:table_id) { nil }
|
174
|
+
|
175
|
+
it "does what it says" do
|
176
|
+
end
|
177
|
+
|
178
|
+
it "returns what is expected" do
|
179
|
+
end
|
180
|
+
end
|
181
|
+
```
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require "rails/generators"
|
2
|
+
|
3
|
+
module Services
|
4
|
+
module Generators
|
5
|
+
class InstallGenerator < Rails::Generators::Base
|
6
|
+
source_root File.expand_path("../templates", __dir__)
|
7
|
+
|
8
|
+
desc "Creates the file structure for Service objects, " \
|
9
|
+
"generates a config files, and generates the ServiceBase module."
|
10
|
+
|
11
|
+
def copy_config
|
12
|
+
template(
|
13
|
+
"service_objects_rails_config.rb",
|
14
|
+
"#{Rails.root}/config/service_objects_rails.rb"
|
15
|
+
)
|
16
|
+
end
|
17
|
+
|
18
|
+
def setup_file_structure
|
19
|
+
empty_directory("#{Rails.root}/app/namespaces/services")
|
20
|
+
empty_directory("#{Rails.root}/spec/namespaces/services")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require "rails/generators"
|
2
|
+
|
3
|
+
module Services
|
4
|
+
module Generators
|
5
|
+
class NewGenerator < Rails::Generators::Base
|
6
|
+
source_root File.expand_path("../templates", __dir__)
|
7
|
+
|
8
|
+
argument :service_name, type: :string
|
9
|
+
argument :service_args, type: :array, default: []
|
10
|
+
|
11
|
+
desc "Creates a new Service Object and corresponding spec file"
|
12
|
+
|
13
|
+
def create_new_service
|
14
|
+
template(
|
15
|
+
"new_service.erb",
|
16
|
+
"#{Rails.root}/app/namespaces/services/#{service_filepath}.rb"
|
17
|
+
)
|
18
|
+
end
|
19
|
+
|
20
|
+
def create_new_service_spec
|
21
|
+
template(
|
22
|
+
"new_service_spec.erb",
|
23
|
+
"#{Rails.root}/spec/namespaces/services/#{service_filepath}_spec.rb"
|
24
|
+
)
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def service_filepath
|
30
|
+
service_name.gsub(/::/, "/")
|
31
|
+
.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
|
32
|
+
.gsub(/([a-z\d])([A-Z])/, '\1_\2')
|
33
|
+
.tr("-", "_")
|
34
|
+
.downcase
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Services
|
2
|
+
class <%= @service_name %>
|
3
|
+
include Services::Base
|
4
|
+
|
5
|
+
def initialize(<%= @service_args.map { |arg| "#{arg}:" }.join(", ") %>)
|
6
|
+
<%= @service_args.map { |arg| "@#{arg} = #{arg}" }.join("\n ") %>
|
7
|
+
end
|
8
|
+
|
9
|
+
def call
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
attr_reader <%= @service_args.map { |arg| ":#{arg}" }.join(", ") %>
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require "rails_helper"
|
2
|
+
|
3
|
+
RSpec.describe Services::<%= @service_name %> do
|
4
|
+
subject(:service_response) do
|
5
|
+
described_class.call<%= "(\n #{@service_args.map { |arg| "#{arg}: #{arg}" }.join(",\n ")}\n )" if @service_args.any? %>
|
6
|
+
end
|
7
|
+
|
8
|
+
<%= @service_args.map { |arg| "let(:#{arg}) { nil }" }.join("\n ") %>
|
9
|
+
|
10
|
+
it "does what it should"
|
11
|
+
|
12
|
+
it "returns what it ought to"
|
13
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require "service_objects_rails"
|
2
|
+
|
3
|
+
ServiceObjectsRails.config do |c|
|
4
|
+
# The Services::Response class is always returned after
|
5
|
+
# executing the #call on a Service. This object includes
|
6
|
+
# goodies like graceful error handling and returning with the
|
7
|
+
# object(s) upon which the Service operated in response.body.
|
8
|
+
# However, some consider it good practice to simply return the
|
9
|
+
# object(s) a service operated on. Set this to false to avoid
|
10
|
+
# Services::Response altogether.
|
11
|
+
# c.return_service_response_object = false
|
12
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require "services/base"
|
2
|
+
require "services/version"
|
3
|
+
|
4
|
+
module ServiceObjectsRails
|
5
|
+
class << self
|
6
|
+
attr_writer :return_service_response_object
|
7
|
+
|
8
|
+
def config
|
9
|
+
yield self
|
10
|
+
end
|
11
|
+
|
12
|
+
def return_service_response_object
|
13
|
+
@return_service_response_object.nil? ? true : @return_service_response_object
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require "services/response"
|
2
|
+
|
3
|
+
module Services::Base
|
4
|
+
def self.included(base)
|
5
|
+
base.extend ClassMethods
|
6
|
+
|
7
|
+
base.private_class_method :new
|
8
|
+
base.send(:attr_reader, :response)
|
9
|
+
end
|
10
|
+
|
11
|
+
module ClassMethods
|
12
|
+
def call(**args)
|
13
|
+
service = new(**args)
|
14
|
+
service.instance_variable_set(:@response, Services::Response.new)
|
15
|
+
|
16
|
+
if ServiceObjectsRails.return_service_response_object
|
17
|
+
service.response.body = service.call
|
18
|
+
service.response
|
19
|
+
else
|
20
|
+
service.call
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Services
|
2
|
+
class Response
|
3
|
+
attr_accessor :body
|
4
|
+
attr_reader :errors
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@body = nil
|
8
|
+
@errors = []
|
9
|
+
end
|
10
|
+
|
11
|
+
def add_errors(*errors)
|
12
|
+
@errors.concat(Array(errors))
|
13
|
+
end
|
14
|
+
|
15
|
+
def success?
|
16
|
+
errors.empty?
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
$LOAD_PATH << File.expand_path("lib", __dir__)
|
2
|
+
require "services/version"
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.name = "service_objects_rails"
|
6
|
+
gem.version = Services::VERSION
|
7
|
+
gem.authors = ["Matthew Dick"]
|
8
|
+
gem.email = ["mattwd7@gmail.com"]
|
9
|
+
gem.summary = "A lightweight, high-speed service layer for Rails applications"
|
10
|
+
gem.description = "A lightweight, high-speed service layer for Rails applications"
|
11
|
+
gem.homepage = "https://github.com/mattwd7/service_objects_rails"
|
12
|
+
gem.license = "MIT"
|
13
|
+
gem.platform = Gem::Platform::RUBY
|
14
|
+
gem.required_ruby_version = ">= 2.5.0"
|
15
|
+
gem.require_path = "lib"
|
16
|
+
gem.files = Dir.glob("lib/**/*") + [
|
17
|
+
"service_objects_rails.gemspec",
|
18
|
+
"Gemfile",
|
19
|
+
"CHANGELOG.md",
|
20
|
+
"LICENSE.txt",
|
21
|
+
"README.md"
|
22
|
+
]
|
23
|
+
|
24
|
+
gem.add_development_dependency "codecov", "~> 0.6"
|
25
|
+
gem.add_development_dependency "dotenv", "~> 2.7"
|
26
|
+
gem.add_development_dependency "factory_bot_rails", "~> 6.2"
|
27
|
+
gem.add_development_dependency "pry", "~> 0.14"
|
28
|
+
gem.add_development_dependency "rake", "~> 13.0"
|
29
|
+
gem.add_development_dependency "rails", "~> 7.0"
|
30
|
+
gem.add_development_dependency "rspec-rails", "~> 5.1"
|
31
|
+
gem.add_development_dependency "rspec", "~> 3.11"
|
32
|
+
gem.add_development_dependency "rubocop-performance", "~> 1.13"
|
33
|
+
gem.add_development_dependency "rubocop-rails", "~> 2.13"
|
34
|
+
gem.add_development_dependency "rubocop-rspec", "~> 2.8"
|
35
|
+
gem.add_development_dependency "rubocop", "~> 1.25"
|
36
|
+
gem.add_development_dependency "simplecov", "~> 0.21"
|
37
|
+
gem.add_development_dependency "standard", "~> 1.7"
|
38
|
+
end
|
metadata
ADDED
@@ -0,0 +1,253 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: service_objects_rails
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Matthew Dick
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2022-03-03 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: codecov
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.6'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.6'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: dotenv
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '2.7'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '2.7'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: factory_bot_rails
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '6.2'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '6.2'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: pry
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0.14'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0.14'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rake
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '13.0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '13.0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rails
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '7.0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '7.0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rspec-rails
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '5.1'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '5.1'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rspec
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '3.11'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '3.11'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: rubocop-performance
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '1.13'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '1.13'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: rubocop-rails
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - "~>"
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '2.13'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - "~>"
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '2.13'
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: rubocop-rspec
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - "~>"
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '2.8'
|
160
|
+
type: :development
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - "~>"
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '2.8'
|
167
|
+
- !ruby/object:Gem::Dependency
|
168
|
+
name: rubocop
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - "~>"
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '1.25'
|
174
|
+
type: :development
|
175
|
+
prerelease: false
|
176
|
+
version_requirements: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - "~>"
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: '1.25'
|
181
|
+
- !ruby/object:Gem::Dependency
|
182
|
+
name: simplecov
|
183
|
+
requirement: !ruby/object:Gem::Requirement
|
184
|
+
requirements:
|
185
|
+
- - "~>"
|
186
|
+
- !ruby/object:Gem::Version
|
187
|
+
version: '0.21'
|
188
|
+
type: :development
|
189
|
+
prerelease: false
|
190
|
+
version_requirements: !ruby/object:Gem::Requirement
|
191
|
+
requirements:
|
192
|
+
- - "~>"
|
193
|
+
- !ruby/object:Gem::Version
|
194
|
+
version: '0.21'
|
195
|
+
- !ruby/object:Gem::Dependency
|
196
|
+
name: standard
|
197
|
+
requirement: !ruby/object:Gem::Requirement
|
198
|
+
requirements:
|
199
|
+
- - "~>"
|
200
|
+
- !ruby/object:Gem::Version
|
201
|
+
version: '1.7'
|
202
|
+
type: :development
|
203
|
+
prerelease: false
|
204
|
+
version_requirements: !ruby/object:Gem::Requirement
|
205
|
+
requirements:
|
206
|
+
- - "~>"
|
207
|
+
- !ruby/object:Gem::Version
|
208
|
+
version: '1.7'
|
209
|
+
description: A lightweight, high-speed service layer for Rails applications
|
210
|
+
email:
|
211
|
+
- mattwd7@gmail.com
|
212
|
+
executables: []
|
213
|
+
extensions: []
|
214
|
+
extra_rdoc_files: []
|
215
|
+
files:
|
216
|
+
- CHANGELOG.md
|
217
|
+
- Gemfile
|
218
|
+
- LICENSE.txt
|
219
|
+
- README.md
|
220
|
+
- lib/generators/services/install_generator.rb
|
221
|
+
- lib/generators/services/new_generator.rb
|
222
|
+
- lib/generators/templates/new_service.erb
|
223
|
+
- lib/generators/templates/new_service_spec.erb
|
224
|
+
- lib/generators/templates/service_objects_rails_config.rb
|
225
|
+
- lib/service_objects_rails.rb
|
226
|
+
- lib/services/base.rb
|
227
|
+
- lib/services/response.rb
|
228
|
+
- lib/services/version.rb
|
229
|
+
- service_objects_rails.gemspec
|
230
|
+
homepage: https://github.com/mattwd7/service_objects_rails
|
231
|
+
licenses:
|
232
|
+
- MIT
|
233
|
+
metadata: {}
|
234
|
+
post_install_message:
|
235
|
+
rdoc_options: []
|
236
|
+
require_paths:
|
237
|
+
- lib
|
238
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
239
|
+
requirements:
|
240
|
+
- - ">="
|
241
|
+
- !ruby/object:Gem::Version
|
242
|
+
version: 2.5.0
|
243
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
244
|
+
requirements:
|
245
|
+
- - ">="
|
246
|
+
- !ruby/object:Gem::Version
|
247
|
+
version: '0'
|
248
|
+
requirements: []
|
249
|
+
rubygems_version: 3.3.8
|
250
|
+
signing_key:
|
251
|
+
specification_version: 4
|
252
|
+
summary: A lightweight, high-speed service layer for Rails applications
|
253
|
+
test_files: []
|