performify 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.rubocop.yml +81 -0
- data/.travis.yml +6 -1
- data/README.md +226 -10
- data/Rakefile +3 -3
- data/bin/rubocop +17 -0
- data/lib/performify/base.rb +9 -1
- data/lib/performify/callbacks.rb +1 -1
- data/lib/performify/validation.rb +42 -0
- data/lib/performify/version.rb +1 -1
- data/performify.gemspec +17 -17
- metadata +53 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c4e16b9f54a462104c0d2851bbbb75d30a36ae4d
|
4
|
+
data.tar.gz: 4788ceeb7f37d2210c400afdbc628497386d2d9a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a08337228b009943e7995b4384c30724f7685264bcea0ba1afda47643e5790924a8b84f6971cb4be0a5d071e882096b4516595a80b8bee10c78f6e5db4a7d7ec
|
7
|
+
data.tar.gz: 2516c4e62c09d77ed0681a46c06ca2650f906d480a57f61bd4f5091e02bf0753a8005622c6dcad49a8cfba20b6d76de3ce30cd1063f2d2694bfed3767d3b30cc
|
data/.gitignore
CHANGED
data/.rubocop.yml
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
AllCops:
|
2
|
+
Exclude:
|
3
|
+
- 'bin/*'
|
4
|
+
- 'spec/**/*_spec.rb'
|
5
|
+
|
6
|
+
Rails:
|
7
|
+
Enabled: false
|
8
|
+
|
9
|
+
Documentation:
|
10
|
+
Enabled: false
|
11
|
+
|
12
|
+
Metrics/ClassLength:
|
13
|
+
CountComments: false
|
14
|
+
Max: 300
|
15
|
+
|
16
|
+
Metrics/LineLength:
|
17
|
+
Max: 120
|
18
|
+
AllowHeredoc: true
|
19
|
+
AllowURI: true
|
20
|
+
URISchemes:
|
21
|
+
- http
|
22
|
+
- https
|
23
|
+
|
24
|
+
Style/ClassAndModuleChildren:
|
25
|
+
Enabled: false
|
26
|
+
|
27
|
+
Rails/Validation:
|
28
|
+
Enabled: false
|
29
|
+
|
30
|
+
Rails/HasAndBelongsToMany:
|
31
|
+
Enabled: false
|
32
|
+
|
33
|
+
Metrics/MethodLength:
|
34
|
+
Max: 30
|
35
|
+
Exclude:
|
36
|
+
- db/migrate/*
|
37
|
+
|
38
|
+
Lint/HandleExceptions:
|
39
|
+
Enabled: false
|
40
|
+
|
41
|
+
Metrics/AbcSize:
|
42
|
+
Enabled: false
|
43
|
+
|
44
|
+
Style/EmptyLinesAroundClassBody:
|
45
|
+
Enabled: false
|
46
|
+
|
47
|
+
Style/EmptyLinesAroundBlockBody:
|
48
|
+
Enabled: false
|
49
|
+
|
50
|
+
Style/CommentAnnotation:
|
51
|
+
Enabled: false
|
52
|
+
|
53
|
+
Style/FrozenStringLiteralComment:
|
54
|
+
Enabled: false
|
55
|
+
|
56
|
+
Style/StringLiterals:
|
57
|
+
Enabled: false
|
58
|
+
|
59
|
+
Style/SpaceInsideBrackets:
|
60
|
+
Enabled: false
|
61
|
+
|
62
|
+
Style/NumericLiterals:
|
63
|
+
Enabled: false
|
64
|
+
|
65
|
+
Style/DoubleNegation:
|
66
|
+
Enabled: false
|
67
|
+
|
68
|
+
Style/MultilineMethodCallIndentation:
|
69
|
+
Enabled: false
|
70
|
+
|
71
|
+
Style/ClosingParenthesisIndentation:
|
72
|
+
Enabled: false
|
73
|
+
|
74
|
+
Style/MultilineMethodCallBraceLayout:
|
75
|
+
Enabled: false
|
76
|
+
|
77
|
+
Style/IfUnlessModifier:
|
78
|
+
Enabled: false
|
79
|
+
|
80
|
+
Bundler/OrderedGems:
|
81
|
+
Enabled: false
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -1,8 +1,6 @@
|
|
1
1
|
# Performify
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
TODO: Delete this and the text above, and describe your gem
|
3
|
+
It's well-known practice that has been proved in many large projects to move server logic into separated service classes. This approach gives a lot of advantages, because when you are able to create object that incapsulates your logic it's much easier to develop, search, control and test. And `performify` helps you to do it in nice and easy way with minimum of pain and maximum of result.
|
6
4
|
|
7
5
|
## Installation
|
8
6
|
|
@@ -14,28 +12,246 @@ gem 'performify'
|
|
14
12
|
|
15
13
|
And then execute:
|
16
14
|
|
17
|
-
|
15
|
+
```
|
16
|
+
$ bundle
|
17
|
+
```
|
18
18
|
|
19
19
|
Or install it yourself as:
|
20
20
|
|
21
|
-
|
21
|
+
```
|
22
|
+
$ gem install performify
|
23
|
+
```
|
22
24
|
|
23
25
|
## Usage
|
24
26
|
|
25
|
-
|
27
|
+
How to have a deal with services:
|
28
|
+
|
29
|
+
1. Define `ApplicationService`
|
30
|
+
2. Create new service inherited from `ApplicationService`
|
31
|
+
3. Implement `execute!` method
|
32
|
+
4. Use `super` to work with db transaction and automatic success / fail workflow control
|
33
|
+
5. Use `success!` and `fail!` to control everything by hands
|
34
|
+
6. Use `on_success` / `on_fail` to define callbacks
|
35
|
+
|
36
|
+
### ApplicationService
|
37
|
+
|
38
|
+
So, first of all it's better to create `ApplicationService` class that will be used as base for all services in your project. You can put any shared logic (like, authorization, for example) here:
|
39
|
+
|
40
|
+
```ruby
|
41
|
+
class ApplicationService < Performify::Base
|
42
|
+
def authorize!(record)
|
43
|
+
# you can put authorization logic here and use it from inherited services
|
44
|
+
end
|
45
|
+
end
|
46
|
+
```
|
47
|
+
|
48
|
+
This is, for example, how authorization can be implemented for `Pundit`:
|
49
|
+
|
50
|
+
```ruby
|
51
|
+
class ApplicationService < Performify::Base
|
52
|
+
def authorize!(record, query = default_query, record_policy = nil)
|
53
|
+
record_policy ||= policy(record)
|
54
|
+
return if record_policy.public_send(query)
|
55
|
+
|
56
|
+
raise Pundit::NotAuthorizedError, query: query, record: record, policy: record_policy
|
57
|
+
end
|
58
|
+
|
59
|
+
def default_query
|
60
|
+
@default_query ||= "#{self.class.name.demodulize.underscore.to_sym}?"
|
61
|
+
end
|
62
|
+
|
63
|
+
def policy(record)
|
64
|
+
@policy ||= Pundit.policy!(@current_user, record)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
```
|
68
|
+
|
69
|
+
### Service: database
|
70
|
+
|
71
|
+
Now, to define new service just create new class and inherit it from `ApplicationService`:
|
72
|
+
|
73
|
+
```ruby
|
74
|
+
module Users
|
75
|
+
class Destroy < ApplicationService
|
76
|
+
def execute!
|
77
|
+
# current user is already available, so feel free to use it
|
78
|
+
# to get user's context
|
79
|
+
|
80
|
+
authorize! current_user unless force?
|
81
|
+
|
82
|
+
# block passed into super's implementation will be executed
|
83
|
+
# in transaction, so you can do multiple data operations, and final
|
84
|
+
# result of this block will be used to determine result of execution
|
85
|
+
|
86
|
+
super do
|
87
|
+
if current_user.update(destroyed_at: Time.zone.now)
|
88
|
+
current_user.comments.find_each do |c|
|
89
|
+
s = Comments::Destroy.new(current_user, c)
|
90
|
+
s.execute!
|
91
|
+
|
92
|
+
# it's also ok to raise ActiveRecord::Rollback, it will be handled
|
93
|
+
# gracefully as regular execution fail
|
94
|
+
|
95
|
+
raise ActiveRecord::Rollback unless s.success?
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def force?
|
102
|
+
# additional instance variables can be passed as named args into
|
103
|
+
# initializer and accessed in service flow
|
104
|
+
|
105
|
+
force.present?
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
```
|
110
|
+
|
111
|
+
Now you can create instance of your service and check result of execution:
|
112
|
+
|
113
|
+
```ruby
|
114
|
+
service = Users::Destroy.new(current_user, force: true)
|
115
|
+
service.execute!
|
116
|
+
service.success? # or service.fail?
|
117
|
+
```
|
118
|
+
|
119
|
+
### Service: HTTP API
|
120
|
+
|
121
|
+
Sometimes your service doesn't work with database, but calls some http endpoint or do some other stuff that doesn't require db transaction. In this case you can control your service flow manually:
|
122
|
+
|
123
|
+
```ruby
|
124
|
+
class Stripe::Create < ApplicationService
|
125
|
+
attr_reader :subscription
|
126
|
+
|
127
|
+
def execute!
|
128
|
+
# here you can go to Stripe and create subscription for the user
|
129
|
+
begin
|
130
|
+
@subscription = Stripe::Subscription.create(
|
131
|
+
customer: current_user.customer_id,
|
132
|
+
plan: selected_plan.stripe_name,
|
133
|
+
)
|
134
|
+
|
135
|
+
# everything looks ok, success
|
136
|
+
|
137
|
+
success!
|
138
|
+
rescue Stripe::StripeError => e
|
139
|
+
# something went wrong, let's notify developers and say that
|
140
|
+
# service execution has been failed
|
141
|
+
|
142
|
+
Airbrake.notify(e)
|
143
|
+
fail!
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
```
|
148
|
+
|
149
|
+
### Callbacks
|
150
|
+
|
151
|
+
If you need to do something on service success / fail it is possible to define appropriate callbacks. Notice, that in case of using `super` callbacks will be executed outside of db transaction, so it's safe to send emails from there, for example.
|
152
|
+
|
153
|
+
```ruby
|
154
|
+
module Passwords
|
155
|
+
class Update < ApplicationService
|
156
|
+
def execute!
|
157
|
+
authorize! current_user
|
158
|
+
|
159
|
+
super do
|
160
|
+
current_user.update(password: password, password_confirmation: password_confirmation)
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
# you can pass method name as a callback
|
165
|
+
|
166
|
+
on_success :invalidate_sessions
|
167
|
+
|
168
|
+
# or you can pass block instead of method name
|
169
|
+
|
170
|
+
on_success { UserMailer.password_changed(current_user).deliver_later }
|
171
|
+
|
172
|
+
private def invalidate_sessions
|
173
|
+
# you can invalidate existing user's sessions here
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
```
|
178
|
+
|
179
|
+
### Validation
|
180
|
+
|
181
|
+
Performify allows you to validate input arguments using [dry-validation](http://dry-rb.org/gems/dry-validation/) schemas. Validation is performed on creation of service instance. And if validation is not passed it will be impossible to call execution. Result of execution will be automatically switched to failed state.
|
182
|
+
|
183
|
+
```ruby
|
184
|
+
module Users
|
185
|
+
module Create
|
186
|
+
schema do
|
187
|
+
required(:email).filled(:str?)
|
188
|
+
end
|
189
|
+
|
190
|
+
def execute!
|
191
|
+
# it will be impossible to call execution if provided arguments
|
192
|
+
# did not pass validation
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
service = Users::Create.new(current_user, email: nil)
|
198
|
+
service.execute! # nothing happens here
|
199
|
+
service.success? # will be false because of validation
|
200
|
+
service.errors # contains hash of errors
|
201
|
+
```
|
202
|
+
|
203
|
+
Sometimes you can have differences between validation errors and execution errors. But usually it's boring to check them separately since you just need to display final result to user. To avoid double check you can use following trick:
|
204
|
+
|
205
|
+
```ruby
|
206
|
+
module Users
|
207
|
+
module Create
|
208
|
+
attr_reader :user
|
209
|
+
|
210
|
+
schema do
|
211
|
+
required(:email).filled(:str?)
|
212
|
+
end
|
213
|
+
|
214
|
+
def execute!
|
215
|
+
user = User.new(email: email)
|
216
|
+
authorize! user
|
217
|
+
|
218
|
+
# Let's assume that user has additional validation of uniqueness on the
|
219
|
+
# level of model, so in controller you need to check separately service's
|
220
|
+
# errors and model's errors, right?
|
221
|
+
|
222
|
+
super { user.save }
|
223
|
+
end
|
224
|
+
|
225
|
+
# So, we define on fail callback where we copy errors from model
|
226
|
+
# to service so now in controller we can check and use only service's errors
|
227
|
+
|
228
|
+
on_fail { errors! user.errors.to_h }
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
# in controller
|
233
|
+
|
234
|
+
service = Users::Create.new(current_user, email: nil)
|
235
|
+
service.execute!
|
236
|
+
|
237
|
+
if service.success?
|
238
|
+
# respond with ok
|
239
|
+
else
|
240
|
+
# respond with unprocessable entity and service.errors
|
241
|
+
end
|
242
|
+
```
|
26
243
|
|
27
244
|
## Development
|
28
245
|
|
29
|
-
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
246
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `bin/rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
30
247
|
|
31
|
-
To install this gem onto your local machine, run `
|
248
|
+
To install this gem onto your local machine, run `bin/rake install`. To release a new version, update the version number in `version.rb`, and then run `bin/rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
32
249
|
|
33
250
|
## Contributing
|
34
251
|
|
35
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
252
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/kimrgrey/performify.
|
36
253
|
|
37
254
|
|
38
255
|
## License
|
39
256
|
|
40
257
|
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
41
|
-
|
data/Rakefile
CHANGED
data/bin/rubocop
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
#
|
4
|
+
# This file was generated by Bundler.
|
5
|
+
#
|
6
|
+
# The application 'rubocop' is installed as part of a gem, and
|
7
|
+
# this file is here to facilitate running it.
|
8
|
+
#
|
9
|
+
|
10
|
+
require "pathname"
|
11
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
12
|
+
Pathname.new(__FILE__).realpath)
|
13
|
+
|
14
|
+
require "rubygems"
|
15
|
+
require "bundler/setup"
|
16
|
+
|
17
|
+
load Gem.bin_path("rubocop", "rubocop")
|
data/lib/performify/base.rb
CHANGED
@@ -1,20 +1,28 @@
|
|
1
1
|
require 'performify/callbacks'
|
2
|
+
require 'performify/validation'
|
2
3
|
|
3
4
|
module Performify
|
4
5
|
class Base
|
5
6
|
extend Performify::Callbacks
|
7
|
+
extend Performify::Validation
|
6
8
|
|
7
9
|
attr_reader :current_user
|
8
10
|
|
9
11
|
def initialize(current_user = nil, **args)
|
10
12
|
@current_user = current_user
|
11
13
|
|
12
|
-
args.
|
14
|
+
return if args.empty?
|
15
|
+
|
16
|
+
validate(args).each do |arg_name, arg_value|
|
13
17
|
define_singleton_method(arg_name) { arg_value }
|
14
18
|
end
|
19
|
+
|
20
|
+
fail!(with_callbacks: true) if errors?
|
15
21
|
end
|
16
22
|
|
17
23
|
def execute!
|
24
|
+
return if defined?(@result)
|
25
|
+
|
18
26
|
block_result = nil
|
19
27
|
|
20
28
|
ActiveRecord::Base.transaction do
|
data/lib/performify/callbacks.rb
CHANGED
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'dry-validation'
|
2
|
+
|
3
|
+
module Performify
|
4
|
+
module Validation
|
5
|
+
def self.extended(base)
|
6
|
+
base.extend Performify::Validation::ClassMethods
|
7
|
+
base.include Performify::Validation::InstanceMethods
|
8
|
+
end
|
9
|
+
|
10
|
+
module ClassMethods
|
11
|
+
def schema(&block)
|
12
|
+
return @schema unless block_given?
|
13
|
+
@schema = Dry::Validation.Schema(Dry::Validation::Schema::Form, {}, &block)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
module InstanceMethods
|
18
|
+
def schema
|
19
|
+
self.class.schema
|
20
|
+
end
|
21
|
+
|
22
|
+
def validate(args)
|
23
|
+
return args if schema.nil?
|
24
|
+
result = schema.call(args)
|
25
|
+
errors!(result.errors) unless result.success?
|
26
|
+
result.output
|
27
|
+
end
|
28
|
+
|
29
|
+
def errors!(new_errors)
|
30
|
+
errors.merge!(new_errors)
|
31
|
+
end
|
32
|
+
|
33
|
+
def errors
|
34
|
+
@errors ||= {}
|
35
|
+
end
|
36
|
+
|
37
|
+
def errors?
|
38
|
+
errors.any?
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/lib/performify/version.rb
CHANGED
data/performify.gemspec
CHANGED
@@ -1,37 +1,37 @@
|
|
1
1
|
# coding: utf-8
|
2
|
+
|
2
3
|
lib = File.expand_path('../lib', __FILE__)
|
3
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
5
|
require 'performify/version'
|
5
6
|
|
6
7
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name
|
8
|
-
spec.version
|
9
|
-
spec.authors
|
10
|
-
spec.email
|
8
|
+
spec.name = "performify"
|
9
|
+
spec.version = Performify::VERSION
|
10
|
+
spec.authors = ["Sergey Tsvetkov"]
|
11
|
+
spec.email = ["sergey.a.tsvetkov@gmail.com"]
|
11
12
|
|
12
|
-
spec.summary
|
13
|
-
Service classes that makes your life easier
|
14
|
-
}
|
13
|
+
spec.summary = "Service classes that makes your life easier"
|
15
14
|
|
16
|
-
spec.description
|
17
|
-
|
18
|
-
that is easy to use, test and maitain.
|
19
|
-
}
|
15
|
+
spec.description = "Performify helps you to define your app logic in separated and isolated \
|
16
|
+
service classes that is easy to use, test and maitain."
|
20
17
|
|
21
|
-
spec.homepage
|
22
|
-
spec.license
|
18
|
+
spec.homepage = "https://github.com/kimrgrey/performify"
|
19
|
+
spec.license = "MIT"
|
23
20
|
|
24
|
-
spec.files
|
21
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
25
22
|
f.match(%r{^(test|spec|features)/})
|
26
23
|
end
|
27
|
-
spec.bindir
|
28
|
-
spec.executables
|
24
|
+
spec.bindir = "exe"
|
25
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
29
26
|
spec.require_paths = ["lib"]
|
30
27
|
|
31
28
|
spec.add_dependency "activerecord", ">= 4.0.0"
|
29
|
+
spec.add_dependency "dry-validation", ">= 0.10.7"
|
32
30
|
|
33
|
-
spec.add_development_dependency "sqlite3"
|
31
|
+
spec.add_development_dependency "sqlite3", "~> 1.3.13"
|
34
32
|
spec.add_development_dependency "bundler", "~> 1.14"
|
35
33
|
spec.add_development_dependency "rake", "~> 10.0"
|
36
34
|
spec.add_development_dependency "rspec", "~> 3.5"
|
35
|
+
spec.add_development_dependency "rubocop", "~> 0.48"
|
36
|
+
spec.add_development_dependency "byebug", "~> 9.0.6"
|
37
37
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: performify
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sergey Tsvetkov
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-05-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -25,19 +25,33 @@ dependencies:
|
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 4.0.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: dry-validation
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
34
|
-
type: :
|
33
|
+
version: 0.10.7
|
34
|
+
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
40
|
+
version: 0.10.7
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: sqlite3
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 1.3.13
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 1.3.13
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: bundler
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -80,8 +94,36 @@ dependencies:
|
|
80
94
|
- - "~>"
|
81
95
|
- !ruby/object:Gem::Version
|
82
96
|
version: '3.5'
|
83
|
-
|
84
|
-
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rubocop
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0.48'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0.48'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: byebug
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 9.0.6
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: 9.0.6
|
125
|
+
description: Performify helps you to define your app logic in separated and isolated service
|
126
|
+
classes that is easy to use, test and maitain.
|
85
127
|
email:
|
86
128
|
- sergey.a.tsvetkov@gmail.com
|
87
129
|
executables: []
|
@@ -90,6 +132,7 @@ extra_rdoc_files: []
|
|
90
132
|
files:
|
91
133
|
- ".gitignore"
|
92
134
|
- ".rspec"
|
135
|
+
- ".rubocop.yml"
|
93
136
|
- ".travis.yml"
|
94
137
|
- Gemfile
|
95
138
|
- LICENSE.txt
|
@@ -98,10 +141,12 @@ files:
|
|
98
141
|
- bin/console
|
99
142
|
- bin/rake
|
100
143
|
- bin/rspec
|
144
|
+
- bin/rubocop
|
101
145
|
- bin/setup
|
102
146
|
- lib/performify.rb
|
103
147
|
- lib/performify/base.rb
|
104
148
|
- lib/performify/callbacks.rb
|
149
|
+
- lib/performify/validation.rb
|
105
150
|
- lib/performify/version.rb
|
106
151
|
- performify.gemspec
|
107
152
|
homepage: https://github.com/kimrgrey/performify
|