Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/waterlink/confident.ruby
Be confident and narrative when writing code in ruby
https://github.com/waterlink/confident.ruby
Last synced: 30 days ago
JSON representation
Be confident and narrative when writing code in ruby
- Host: GitHub
- URL: https://github.com/waterlink/confident.ruby
- Owner: waterlink
- License: mit
- Created: 2015-01-16T02:12:44.000Z (almost 10 years ago)
- Default Branch: master
- Last Pushed: 2015-01-21T17:18:44.000Z (almost 10 years ago)
- Last Synced: 2024-04-25T14:01:03.785Z (8 months ago)
- Language: Ruby
- Size: 145 KB
- Stars: 1
- Watchers: 3
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE.txt
Awesome Lists containing this project
README
# Confident.ruby
[![Build Status](https://travis-ci.org/waterlink/confident.ruby.svg?branch=master)](https://travis-ci.org/waterlink/confident.ruby)
Be confident and narrative when writing code in ruby.
Gem contains useful abstractions for eliminating most condition and switch smells, treating anything just like a duck, implementing barricade and null object pattern efficiently.
## Installation
Add this line to your application's Gemfile:
```ruby
gem 'confident_ruby'
```or if you use `Bundler.setup`:
```ruby
gem 'confident_ruby', require: 'confident'
```And then execute:
$ bundle
Or install it yourself as:
$ gem install confident_ruby
## Usage
```ruby
require "confident"
```### Eliminating condition
*Not implemented*
Given this code:
```ruby
class Order
# ...
def charge
if date < SEASON_START || date > SEASON_END
quantity * normal_rate - discount
else
quantity * season_rate
end
end
# ...
end
```Becomes:
```ruby
class Order
# ...
def charge
Charge.lift(date).for(quantity)
end
# ...
end
Charge = Confident::Liftable.build do
lifts(to: :NormalCharge) { date < SEASON_START || date > SEASON_END }
lifts(to: :SeasonCharge) { true }
class NormalCharge < self
def for(quantity)
Money.lift(normal_rate) * quantity - Money.lift(discount)
end
end
class SeasonCharge < self
def for(quantity)
Money.lift(season_rate) * quantity
end
end
end
```### Eliminating switch
*Not implemented*
Given this code:
```ruby
class Product# ...
def cost
case kind
when "hosting"
hosting_cost
when "dedicated"
dedicated_cost
when "virtual"
virtual_cost
else
raise "Unreachable code"
end
end# ...
end
```becomes:
```ruby
class Product# ...
def cost
kind.cost
enddef kind
ProductKind.lift(@kind)
end# ...
end
# could be abstracted even better, if the whole thing was in database source
ProductKind = Confident::Liftable.build do
lift_map "hosting" => :HostingProductKind,
"dedicated" => :DedicatedProductKind,
"virtual" => :VirtualProductKinddef cost
Confident::Result.error("Unknown product kind")
endclass HostingProductKind < self
def cost
Confident::Result.ok(Money.lift(hosting_kind))
end
endclass DedicatedProductKind < self
def cost
Confident::Result.ok(Money.lift(dedicated_kind))
end
endclass VirtualProductKind < self
def cost
Confident::Result.ok(Money.lift(virtual_kind))
end
end
end
```Looks like we expanding our code and making it bigger at no time, but it is actually beneficial to us, because we don't need to duplicate knowledge on how to determine `kind` of product throughout a codebase, we just call `Product.lift(kind_string_value)`, and we are done with it. You can implement this stuff in raw ruby easily, but this library wants to cut of a boilerplate code involved in this usually.
### Handling success/failure result
Just use `Confident::Result`:
```ruby
def some_computation_that_may_fail
Confident::Result.ok(compute)
rescue => e
Confident::Result.error(e.to_s)
endputs some_computation_that_may_fail.on_error { |e| report_error(e) }.unwrap
```If you have something that returns `true` in case of success and `false` in case of failure, you can use `Confident::Result.from_condition(boolean_value, failure_message=nil)`:
```ruby
Confident::Result.from_condition(some_weird_external_api, "Weird external API returned unexpected error")
```### Pure null object
Pure null object (`Confident::NullObject`) quacks to any method with itself.
If you have an input value that could be `nil`, you can just wrap it in `Confident::AutoNullObject` to get either original value or pure null object if it is `nil`.
Example usage with `AutoNullObject`:```ruby
def do_something_with(possibly_nil_value)
AutoNullObject(some_possibly_nil_value).say("hello")
enddo_something_with(fetch_me_a_value) # => "said: hello"
do_something_with(fetch_me_a_nil_value) # => #
```### TODO (to specify in this README)
- lift & bind
- null object with ability to define your own custom null object
- barricade## Contributing
1. Fork it ( https://github.com/waterlink/confident.ruby/fork )
2. Create your feature branch (`git checkout -b my-new-feature`)
3. Commit your changes (`git commit -am 'Add some feature'`)
4. Push to the branch (`git push origin my-new-feature`)
5. Create a new Pull Request