fretadao / f_service Goto Github PK
View Code? Open in Web Editor NEWSimpler, safer and more composable operations
License: MIT License
Simpler, safer and more composable operations
License: MIT License
Hello there!
I've noticed that ther is no Check example on the README file. Do you plan on adding it on a near future?
In exceptions, we can catch or a single error, or a family of errors, using its superclass...
Ex:
ClientError = Class.new(RuntimeError)
UnprocessableEntity = Class.new(ClientError)
Conflict = Class.new(ClientError)
def foo
create_user
rescue UnprocessableEntity => error
"User can not be created fix errors and try again #{error.message}"
rescue Conflict
"User already exist."
rescue ClientError => error
Sentry.capture_exception("Some unexpected client error happened: #{error.message}")
"Unknow error happened, please contact system administration"
end
Nowadays it is impossible in FService, because we can create a result using just one symbol....
If we are able to put more than one symbol, we could, for example, pass a specific symbol and a more generic one.
Ex:
class User::Create < FService::Base
attribute :attr
def run
response = create_user(attrs)
return Success(:ok, :created, data: response.body) if response.status == 200
if response.status.between?(400, 499)
error_name = client_error_name(response.status)
if error_name.error_name.present?
Failure(:unprocessable_entity, :client_error, data: response.body)
else
Failure(:client_error, data: response.body)
end
end
end
private
def client_error_name(status)
return :unprocessable_entity if status = 422
return :conflict if status = 409
end
end
And the usage would be:
User::Create(attrs: { name: 'Joe' })
.on_success(:created) { return 'User created' }
.on_failure(:unprocessable_entity) { |error| return "User can not be created fix errors and try again #{error}" }
.on_failure(:conflict) { return "User already exist." }
.on_failure(:client_error) do
Sentry.capture_exception("Some unexpected client error happened: #{error.message}")
return "Unknow error happened, please contact system administration"
end
Hi,
So, myself and my colleagues are always complaining that we cannot pass a custom data to the Base#Check
and always need to write both the Success and Failure to be able to use a custom data. I think it is a good idea to keep the actual behavior to validation purposes, but also expand it's usage by having an optional data argument.
Or even better, having a different data prop depending on the actual return could be a good one too, what do you think?
PR: #18
expect(result).to have_value/have_error(1)
)Resources:
MyService.()
.on_success { do_this }
.on_failure(:error_1, :error_2) { do_this_instead }
.on_failure(:other) { do_other }
then
already exist in ruby objects. It may be a good idea not to use the same method name in FService::Result
s. and_then
is a pretty straight forward alternative.
If services implement to_proc
we could chain them like this (respecting their inputs/outputs):
IsLeap.(year: 2020)
.then(&BoolToString)
.then(&AddEmotion) # Adds '!'
.then(&AddDoubt) # Adds '?'
.value
# => Yes!?
call
should be the safe version of the current run
(and future call!
). call
should work pretty much like run
does, but it also catches any StandardError
that may be raised in its body and encapsulates as a failure:
class Bomb < FService::Base
def call # safe
raise StandardError, 'BOOOM!'
end
end
Bomb.call # remember that Bomb.call == Bomb.new.call
# => #<Failure:uu1D @type=:exception @error=#<StandardError: BOOOM!>>
With call!
(with bang), we have the unsafe version:
class Bomb < FService::Base
def call! # unsafe
raise StandardError, 'BOOOM!'
end
end
Bomb.call # remember that Bomb.call == Bomb.new.call
# => BOOOM! (StandardError)
I'm not sure of the syntax yet, but it would be nice to have something like this:
class User::Create < FService::Base
input :name, type: String
input :age, type: Integer, should: { be_positive: ->(age) { age.positive? } }
input :github_username, type: String, default: '[no-username]'
output :user, type: User
def run
# ...
end
end
User::Create.(name: 'David', age: 40, github_username: 'ddd')
Due to the changes introduced in Ruby 2.7, it's necessary to fix the syntax for argument forwarding used on Fservice::Base.
Info:
https://bugs.ruby-lang.org/issues/16157
https://eregon.me/blog/2019/11/10/the-delegation-challenge-of-ruby27.html
This gem was suggested in this PR suggestion.
And as it was out of PR scope we are opening this issue to not lose sight of it.
call!
is more common in Ruby an is already present as a class method for FService::Base
. We should mark run
as deprecated in the next version.
We'll use call
(without bang) in #27, so call!
(with bang) is the drop-in replacement for run
.
MyService.(params: { a: 1, b: 2 })
.on_success { do_this }
.on_failure(:error_1) { |value, type| handle_failure(type) }
Some cool ideas from dry-transactions
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.