Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add configuration option to service #14

Merged
merged 2 commits into from
Jan 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
## v0.1.4
January 30 2024

## v0.1.3
September 18 2023

Expand All @@ -11,4 +14,3 @@ March 03 2022
- Add the response helper.
Refactor the code a bit :)
Include Dockerfile and docker-compose

3 changes: 1 addition & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
# Base image
FROM ruby:3.2.1-slim
FROM ruby:3.2.3-bullseye

# Add our Gemfile and install gems
ADD Gemfile* ./
ADD hanikamu-base_service.gemspec ./


RUN bundle check || bundle install

WORKDIR "/app"
16 changes: 12 additions & 4 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
PATH
remote: .
specs:
hanikamu-service (0.1.3)
hanikamu-service (0.1.4)
dry-configurable (~> 1.1.0)
dry-monads (~> 1.6.0)
dry-struct (~> 1.6.0)

Expand All @@ -10,9 +11,13 @@ GEM
specs:
ast (2.4.2)
base64 (0.1.1)
bigdecimal (3.1.6)
coderay (1.1.3)
concurrent-ruby (1.2.2)
concurrent-ruby (1.2.3)
diff-lcs (1.5.0)
dry-configurable (1.1.0)
dry-core (~> 1.0, < 2)
zeitwerk (~> 2.6)
dry-core (1.0.1)
concurrent-ruby (~> 1.0)
zeitwerk (~> 2.6)
Expand All @@ -30,7 +35,8 @@ GEM
dry-types (>= 1.7, < 2)
ice_nine (~> 0.11)
zeitwerk (~> 2.6)
dry-types (1.7.1)
dry-types (1.7.2)
bigdecimal (~> 3.0)
concurrent-ruby (~> 1.0)
dry-core (~> 1.0)
dry-inflector (~> 1.0)
Expand Down Expand Up @@ -92,9 +98,11 @@ GEM
rubocop-factory_bot (~> 2.22)
ruby-progressbar (1.13.0)
unicode-display_width (2.4.2)
zeitwerk (2.6.11)
zeitwerk (2.6.12)

PLATFORMS
aarch64-linux
arm64-darwin-23
x86_64-darwin-20
x86_64-linux
x86_64-linux-musl
Expand Down
6 changes: 5 additions & 1 deletion Makefile.example
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,8 @@ console: ## build the image

.PHONY: rspec
rspec: ## build the image
sudo docker-compose run --rm app sh -c "bundle exec rspec"
sudo docker-compose run --rm app sh -c "bundle exec rspec"

.PHONY: rubocop
rubocop:
sudo docker-compose run --rm app sh -c "bundle exec rubocop"
52 changes: 29 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,13 @@
#### Definition
Services enforce a pattern design as service objects.

#### Why?
- We want SRP(single responsibility classes) for easier testing.

- We want to have a common pattern on our service design preventing a fragmentation of patterns.

- We want to avoid business logic in our models.

- We want to test our business logic in isolation.

- We want a complete overview over our domain model and business logic transactions

- We want to express intent over data structure.
#### Objectives
- Adherence to the Single Responsibility Principle for simplified testing.
- Establishment of a uniform pattern for service design to prevent divergent practices.
- Removal of business logic from models to maintain clean architecture.
- Isolation of business logic for focused testing.
- Comprehensive understanding of domain models and business transactions.
- Emphasis on clear intent rather than mere data structuring.


#### Principles
Expand All @@ -27,11 +22,11 @@ Services enforce a pattern design as service objects.

- A `Service.call!` will success on it's task or will raise an error

- `.call!` will raise a set of known errors(validation, ...)
- `.call!` will raise a predefined set of errors (e.g., validation errors).

- `Service.call` will success on it's task returning a monadic Success reponse or will fail returning a monadic Failure
- `Service.call` should either successfully return a Success response or a Failure response in a monadic format.

- `.call` will only catch a set of known Service Errors inheriting from Hanikamu::Service::WhiteListedError and it's implemented as a wrapper of `.call!`
- `.call` will catch only specific Service Errors inheriting from Hanikamu::Service::WhiteListedError and it's implemented as a wrapper of `.call!`


#### Responsibilities
Expand All @@ -58,13 +53,12 @@ Services enforce a pattern design as service objects.
- When asking for a banana return only the banana
https://www.johndcook.com/blog/2011/07/19/you-wanted-banana/

###### Schema
###### Schema Validation
Checks if the input types are valid.
E.g. job_id is required and of type integer
Errors can be corrected by the client passing different input types to the operation

#### Example
- Validates input types (e.g., ensuring job_id is an integer and required).
- Errors can be corrected by the client passing different input types to the service.

#### Example Usage

```ruby
module Types
Expand Down Expand Up @@ -98,13 +92,25 @@ Errors can be corrected by the client passing different input types to the opera
monadic_response.success if monadic_response.success?
```


#### Configuration

If you wish to include additional error classes to the existing whitelisted_errors array, which is used for determining which errors should result in a Failure response when calling services without a bang (e.g., SomeService.call), you can do so by appending these classes to the whitelisted_errors list in an initializer.

```ruby

# in initializer config/initializers/hanikamu_service

Hanikamu::Service.configure do |config|
config.whitelisted_errors = [SomeError]
end

```

#### Using docker

Rename Makefile.example to Makefile
- `make build` for building the image
- `make shell` to get a shell console with the ruby environment
- `make console` get a ruby console
- `make rspec` run the specs



2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.1.3
0.1.4
14 changes: 4 additions & 10 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,17 +1,11 @@
version: "3"
version: "3.6"
networks:
docker-compose-example-tier:
hanikamu-service-network:
driver: bridge
services:
app:
build:
context: .
dockerfile: Dockerfile
build: .
volumes:
- .:/app
networks:
- docker-compose-example-tier
volumes:
- .:/app
networks:
- docker-compose-example-tier
- hanikamu-service-network
3 changes: 2 additions & 1 deletion hanikamu-base_service.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ $LOAD_PATH.push File.expand_path("lib", __dir__)

Gem::Specification.new do |s|
s.name = "hanikamu-service"
s.version = "0.1.3"
s.version = "0.1.4"
s.authors = ["Nicolai Seerup", "Alejandro Jimenez"]
s.summary = "This is the base service for all pattern designs used in hanikamu design"
s.required_ruby_version = ">= 3.1"
Expand All @@ -15,6 +15,7 @@ Gem::Specification.new do |s|
s.files = Dir["{config,lib}/**/*", "Rakefile"]
s.require_paths = ["lib"]

s.add_dependency "dry-configurable", "~> 1.1.0"
s.add_dependency "dry-monads", "~> 1.6.0"
s.add_dependency "dry-struct", "~> 1.6.0"

Expand Down
6 changes: 5 additions & 1 deletion lib/hanikamu/service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@
module Hanikamu
# :nodoc
class Service < Dry::Struct
extend Dry::Configurable
extend Dry::Monads[:result]
Error = Class.new(StandardError)

setting :whitelisted_errors, default: []

class << self
def call(options = {})
Success(call!(options))
Expand All @@ -27,7 +30,8 @@ def call!(options = {})
def whitelisted_error?(error_klass)
error_klass == Hanikamu::Service::Error ||
error_klass.superclass == Hanikamu::Service::Error ||
error_klass == Dry::Struct::Error
error_klass == Dry::Struct::Error ||
config.whitelisted_errors.include?(error_klass)
end
end

Expand Down
Loading