|
169 | 169 | ``` |
170 | 170 |
|
171 | 171 | ⚠️ Warning: The `:requires_new` option for nested transactions is not yet fully supported. |
| 172 | + |
| 173 | +### Params |
| 174 | + |
| 175 | +The `Params` extension adds input validation support to your operations using [dry-schema](https://dry-rb.org/gems/dry-schema/). When a operation is called, the input will be automatically validated against the defined schema before the operation logic executes. If validation fails, the operation returns a `Failure` with detailed error information without executing the operation body. |
| 176 | + |
| 177 | +Make sure you have dry-schema installed: |
| 178 | + |
| 179 | +```ruby |
| 180 | +gem "dry-schema" |
| 181 | +``` |
| 182 | + |
| 183 | +Require and include the extension in your operation class, then define a schema using the `params` class method: |
| 184 | + |
| 185 | +```ruby |
| 186 | +require "dry/operation/extensions/params" |
| 187 | + |
| 188 | +class CreateUser < Dry::Operation |
| 189 | + include Dry::Operation::Extensions::Params |
| 190 | + |
| 191 | + params do |
| 192 | + required(:name).filled(:string) |
| 193 | + required(:email).filled(:string) |
| 194 | + optional(:age).maybe(:integer) |
| 195 | + end |
| 196 | + |
| 197 | + def call(input) |
| 198 | + user = step create_user(input) |
| 199 | + step notify(user) |
| 200 | + user |
| 201 | + end |
| 202 | + |
| 203 | + # ... |
| 204 | +end |
| 205 | +``` |
| 206 | + |
| 207 | +When validation succeeds, the operation receives the validated and coerced input: |
| 208 | + |
| 209 | +```ruby |
| 210 | +result = CreateUser. new.call( name: "Alice", email: "[email protected]", age: "25") |
| 211 | +# => Success(user) with age coerced to integer 25 |
| 212 | +``` |
| 213 | + |
| 214 | +When validation fails, the operation returns a `Failure` tagged with `:invalid_params` and the validation errors, without executing any of the operation's steps: |
| 215 | + |
| 216 | +```ruby |
| 217 | +result = CreateUser.new.call(name: "", email: "invalid") |
| 218 | +# => Failure[:invalid_params, {name: ["must be filled"]}] |
| 219 | +``` |
| 220 | + |
| 221 | +The `params` extension works seamlessly with custom wrapped methods when using `.operate_on`: |
| 222 | + |
| 223 | +```ruby |
| 224 | +class ProcessData < Dry::Operation |
| 225 | + include Dry::Operation::Extensions::Params |
| 226 | + |
| 227 | + operate_on :process, :transform |
| 228 | + |
| 229 | + params do |
| 230 | + required(:value).filled(:string) |
| 231 | + end |
| 232 | + |
| 233 | + def process(input) |
| 234 | + # input is validated before this executes |
| 235 | + end |
| 236 | + |
| 237 | + def transform(input) |
| 238 | + # input is validated before this executes |
| 239 | + end |
| 240 | +end |
| 241 | +``` |
| 242 | + |
| 243 | +Schemas are inherited by subclasses, allowing you to build operation hierarchies with shared validation rules. |
0 commit comments