rewinfrey / actionlogic Goto Github PK
View Code? Open in Web Editor NEWA business logic abstraction gem that provides structure to the organization and composition of business logic (Ruby)
Home Page: http://rickwinfrey.com/ActionLogic/
A business logic abstraction gem that provides structure to the organization and composition of business logic (Ruby)
Home Page: http://rickwinfrey.com/ActionLogic/
For the sake of providing clear, real world examples, create a Rails app that performs logic.
The logic can be shows in a traditional Rails way and in the ActionLogic way.
For those cases when before / after or around filters are sufficient and a call method is not required.
This would make it possible for an ActionCoordinator
or ActionUseCase
to optionally define a call
method, and if none were defined, then one would be dynamically defined.
At each level, ActionCoordinator, ActionUseCase and ActionTask, allow for a simple convenience method for indicating the logic should be wrapped in a transaction.
After exploring type annotations in Haskell and Elm, using the class constant feels more natural than using a symbol.
The proposal would be to instead use class constant (e.g. String
rather than :string
). This also makes it easier for those new to ActionLogic
because the use of a class constant is more intuitive rather than a symbol representation (particularly for user defined classes).
For now this only includes benchmarking configuration options:
By default benchmark
is false
(this must be explicitly set to true
to enable benchmarking functionality):
ActionLogic::ActionConfiguration.configure do |config|
config.benchmark = true
end
By default benchmark_log
uses stdout
unless a Ruby IO object is specified (like a File):
ActionLogic::ActionConfiguration.configure do |config|
config.benchmark = true
config.benchmark_log = File.open("benchmark.log", "w")
end
By default benchmark_formatter
uses the ActionLogic::ActionBenchmark::DefaultFormatter
. Any custom formatters should subclass ActionLogic::ActionBenchmark::DefaultFormatter
or verify that the custom formatter class implements the same interface.
class CustomFormatter < ActionLogic::ActionBenchmark::DefaultFormatter
# Custom formatters require you to define three methods:
# `task`, `use_case` and `coordinator`
# Each of the format methods receives two inputs:
#1. `benchmark_result` : type is a Ruby stdlib Benchmark instance
#2. `context_name` : type is a Ruby String representing the class name of the execution
# context (`ActionTask`, `ActionUseCase`, or `ActionCoordinator` class)
# A `benchmark_log` attr_reader is provided to write to within the `task`, `use_case` or
# `coordinator` methods.
def task(benchmark_result, context_name)
benchmark_log.puts("[task] #{context_name}: #{benchmark_result.real}")
end
def use_case(benchmark_result, context_name)
benchmark_log.puts("[use case] #{context_name}: #{benchmark_result.real}")
end
def coordinator(benchmark_result, context_name)
benchmark_log.puts("[coordinator] #{context_name}: #{benchmark_result.real}")
end
end
# To use the CustomFormatter formatter class, we can configure ActionLogic like so:
ActionLogic::ActionConfiguration.configure do |config|
config.benchmark = true
config.benchmark_log = File.open("benchmark.log", "w")
config.benchmark_formatter = CustomFormatter
end
# Using this configuration with the test suite yields a benchmark output formatted like so:
SimpleTestTask: 3.322999691590667e-05
SimpleTestUseCase: 0.00011545396409928799
UseCaseTestTask1: 2.9074028134346008e-05
UseCaseTestTask2: 2.7913018129765987e-05
SimpleTestUseCase2: 0.00011622201418504119
SimpleTestTask: 6.190297426655889e-05
SimpleTestUseCase: 0.00018308503786101937
...
# If no custom formatter is defined, ActionLogic provides a default formatter
# whose output is a machine readable format for easy parsing:
context: SimpleTestTask user_time: 0.000000 system_time: 0.000000 total_time: 0.000000 real_time: 0.000048
context: SimpleTestTask user_time: 0.000000 system_time: 0.000000 total_time: 0.000000 real_time: 0.000030
context: FailureTestTask user_time: 0.000000 system_time: 0.000000 total_time: 0.000000 real_time: 0.000038
context: ErrorHandlerTestTask user_time: 0.000000 system_time: 0.000000 total_time: 0.000000 real_time: 0.000042
context: ValidateAroundCustomTypeTestTask user_time: 0.000000 system_time: 0.000000 total_time: 0.000000 real_time: 0.000044
context: ValidateAroundTestTask user_time: 0.000000 system_time: 0.000000 total_time: 0.000000 real_time: 0.000164
...
In a recently conversation on LightService, I suggested making benchmarking available via a configuration object that also would allow you to specify a log file for the benchmark results. The benchmarking would measure the execution time of any ActionCoordinator
, ActionUseCase
or ActionTask
.
I think this would be a fun and potentially useful feature for those in the future that may use ActionLogic
and want to understand the how their various execution contexts are running to isolate long-running tasks.
Allow users to register custom validations as part of ActionConfiguration.
Validations would include the default validations plus any registered during configuration.
Custom validations would be required to implement a call method.
When an ActionLogic
error is thrown, the intent is to communicate the context
in which the error was thrown (i.e. the name of the specific class). Instead the context
today reports a generic catchall Class
:
ActionLogic::AttributeTypeError: context: Class message: Attribute: integer_test with value: was expected to be of type Fixnum but is NilClass
The issue is not threading the executionContext
from ActionCore
through to the ActionValidation
methods. If executionContext
is passed as an argument, when we find an error within any of the ActionValidation
methods we would have the originating class information for producing a better error message.
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.