lab_coat 0.1.2 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 22451390278d5dff8546f421b305107ea5e6d6636ea288eb674ab980353dcd20
4
- data.tar.gz: 0a97027504a75312e42501283898021c9417b6e283e22cb5d86a614ebf939ae8
3
+ metadata.gz: 35fcc39652cc2ab43879a6a513214962c139d6b5751f5a1d4b4e8dba7b72b5e3
4
+ data.tar.gz: 5b54b1fb3fcabe26a80b2cdd619308f51b7fc44c6b0b93572550eb3e9a50aedd
5
5
  SHA512:
6
- metadata.gz: d59adedb051274080954bd28c23b0fbbdc4b6914d90a19f45e5a4c8d3d8f46a06b334e7a2c1e5698eee9adbc9bdfb0f8d4270d37c37430978d952635f4186711
7
- data.tar.gz: eb3f5aadd5a01813521b81941052a699ce5ced2b7e9f8d0964942d4a419524e001a0664cd55170069a9fff149eddc6f36885d704e035cc139309115f35c8d856
6
+ metadata.gz: 48e1e6af3c47d799f6eecd76dcac57a168da9c1729fc29091742b79ae114d36741a9d72bac6348db0db43a868ee5f75087ced725d270ae55074221a2dc152cd5
7
+ data.tar.gz: 6b98f3702d8a8cc8494bc2c9eb5e09e1ecc6aff21d204be93d54485eba4754fa60aa89aa832b2644910e42d6ac42c4cdc683db0ac4d0b49b7c3fe2025b417488
data/CHANGELOG.md CHANGED
@@ -1,3 +1,6 @@
1
+ ## [0.1.3] - 2024-04-17
2
+ - `Experiment` now enforces arity at runtime for the `#enabled?`, `control`, and `candidate` methods.
3
+
1
4
  ## [0.1.2] - 2024-04-15
2
5
  - use `Benchmark` to capture the duration with more details
3
6
  - add `to_h` methods to `Result` and `Observation` for convenience
data/README.md CHANGED
@@ -8,6 +8,7 @@ This library is heavily inspired by [Scientist](https://github.com/github/scient
8
8
  - `Experiments` are `classes`, not `modules` which means they are stateful by default.
9
9
  - There is no app wide default experiment that gets magically set.
10
10
  - The `Result` only supports one comparison at a time, i.e. only 1 `candidate` is allowed per run.
11
+ - The `duration` is measured using Ruby's `Benchmark`.
11
12
 
12
13
  ## Installation
13
14
 
@@ -55,8 +56,8 @@ See the [`Experiment`](lib/lab_coat/experiment.rb) class for more details.
55
56
  |`enabled?`|Returns a `Boolean` that controls whether or not the experiment runs.|
56
57
  |`publish!`|This is not _technically_ required, but `Experiments` are not useful unless you can analyze the results. Override this method to record the `Result` however you wish.|
57
58
 
58
- > [!TIP]
59
- > The `#run!` method accepts arbitrary arguments and forwards them to `enabled?`, `control`, and `candidate` in case you need to provide data at runtime.
59
+ > [!IMPORTANT]
60
+ > The `#run!` method accepts arbitrary arguments and forwards them to `enabled?`, `control`, and `candidate` in case you need to provide data at runtime. This means the [arity](https://en.wikipedia.org/wiki/Arity) of the three methods needs to be the same. This is enforced by `LabCoat` at runtime.
60
61
 
61
62
  #### Additional methods
62
63
 
@@ -190,7 +191,7 @@ def publish!(result)
190
191
  end
191
192
  ```
192
193
 
193
- > ![NOTE]
194
+ > [!NOTE]
194
195
  > All `Results` are passed to `publish!`, **including ignored ones**. It is your responsibility to call the `ignored?` method and handle those as you wish.
195
196
 
196
197
  You can always access all of the attributes of the `Result` and its `Observations` directly to fully customize what your experiment publishing looks like.
@@ -60,24 +60,38 @@ module LabCoat
60
60
  # Runs the control and candidate and publishes the result. Always returns the result of `control`.
61
61
  # @param context [Hash] Any data needed at runtime.
62
62
  def run!(...) # rubocop:disable Metrics/MethodLength
63
+ enforce_arity!
64
+
63
65
  # Run the control and exit early if the experiment is not enabled.
64
- control = Observation.new("control", self) do
66
+ control_obs = Observation.new("control", self) do
65
67
  control(...)
66
68
  end
67
- raised(control) if control.raised?
68
- return control.value unless enabled?(...)
69
+ raised(control_obs) if control_obs.raised?
70
+ return control_obs.value unless enabled?(...)
69
71
 
70
- candidate = Observation.new("candidate", self) do
72
+ candidate_obs = Observation.new("candidate", self) do
71
73
  candidate(...)
72
74
  end
73
- raised(candidate) if candidate.raised?
75
+ raised(candidate_obs) if candidate_obs.raised?
74
76
 
75
77
  # Compare and publish the results.
76
- result = Result.new(self, control, candidate)
78
+ result = Result.new(self, control_obs, candidate_obs)
77
79
  publish!(result)
78
80
 
79
81
  # Always return the control.
80
- control.value
82
+ control_obs.value
83
+ end
84
+
85
+ private
86
+
87
+ # Because `run!` forwards arbitrary args to `#enabled?`, `control`, and `candidate`, the methods must have the same
88
+ # arity. Otherwise
89
+ def enforce_arity!
90
+ return if %i[enabled? control candidate].map { |m| method(m).arity }.uniq.size == 1
91
+
92
+ raise InvalidExperimentError,
93
+ "The `#enabled?`, `#control` and `#candidate` methods must have the same arity. All runtime args passed " \
94
+ "to `#run!` are forwarded to these methods."
81
95
  end
82
96
  end
83
97
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module LabCoat
4
- VERSION = "0.1.2"
4
+ VERSION = "0.1.3"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lab_coat
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Omkar Moghe
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-04-15 00:00:00.000000000 Z
11
+ date: 2024-04-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest