├── .github ├── FUNDING.yml └── workflows │ └── ci.yml ├── .gitignore ├── .jrubyrc ├── .repobot.yml ├── .rspec ├── .rubocop.yml ├── .yardopts ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── Gemfile ├── LICENSE.md ├── README.md ├── Rakefile ├── hanami-validations.gemspec ├── lib ├── hanami-validations.rb └── hanami │ ├── validations.rb │ └── validations │ └── version.rb ├── script └── ci └── spec ├── spec_helper.rb ├── support └── errors.yml └── unit └── hanami └── validations └── version_spec.rb /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: hanami 2 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: ci 2 | 3 | on: 4 | push: 5 | pull_request: 6 | create: 7 | schedule: 8 | - cron: "30 4 * * *" 9 | 10 | jobs: 11 | tests: 12 | runs-on: ubuntu-latest 13 | strategy: 14 | fail-fast: false 15 | matrix: 16 | ruby: 17 | - "3.4" 18 | - "3.3" 19 | - "3.2" 20 | - "3.1" 21 | steps: 22 | - uses: actions/checkout@v1 23 | - name: Install package dependencies 24 | run: "[ -e $APT_DEPS ] || sudo apt-get install -y --no-install-recommends $APT_DEPS" 25 | - name: Set up Ruby 26 | uses: ruby/setup-ruby@v1 27 | with: 28 | ruby-version: ${{matrix.ruby}} 29 | - name: Install latest bundler 30 | run: | 31 | gem install bundler --no-document 32 | - name: Bundle install 33 | run: bundle install --jobs 4 --retry 3 34 | - name: Run all tests 35 | run: script/ci 36 | 37 | workflow-keepalive: 38 | if: github.event_name == 'schedule' 39 | runs-on: ubuntu-latest 40 | permissions: 41 | actions: write 42 | steps: 43 | - uses: liskin/gh-workflow-keepalive@v1 44 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.bundle/ 2 | /.yardoc 3 | /Gemfile.lock 4 | /_yardoc/ 5 | /coverage/ 6 | /doc/ 7 | /pkg/ 8 | /spec/reports/ 9 | /tmp/ 10 | *.bundle 11 | *.so 12 | *.o 13 | *.a 14 | mkmf.log 15 | .greenbar 16 | .rubocop-*yml 17 | -------------------------------------------------------------------------------- /.jrubyrc: -------------------------------------------------------------------------------- 1 | debug.fullTrace=true 2 | -------------------------------------------------------------------------------- /.repobot.yml: -------------------------------------------------------------------------------- 1 | # This is a config synced from hanami/template-gem repo 2 | 3 | sources: 4 | - repo: hanami/template-gem 5 | sync: 6 | - ".repobot.yml.erb" 7 | - ".github/FUNDING.yml" 8 | - "CODE_OF_CONDUCT.md" 9 | - "LICENSE.md.erb" 10 | -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --color 2 | --require spec_helper 3 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | # Please keep AllCops, Bundler, Style, Metrics groups and then order cops 2 | # alphabetically 3 | inherit_from: 4 | - https://raw.githubusercontent.com/hanami/devtools/main/.rubocop.yml 5 | -------------------------------------------------------------------------------- /.yardopts: -------------------------------------------------------------------------------- 1 | - 2 | README.md 3 | LICENSE.md 4 | lib/**/*.rb 5 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Hanami::Validations 2 | 3 | Validations mixin for Ruby objects 4 | 5 | ## v2.2.0 - 2024-11-05 6 | 7 | ## v2.2.0.rc1 - 2024-10-29 8 | 9 | ## v2.2.0.beta2 - 2024-09-25 10 | 11 | ### Changed 12 | 13 | - [Tim Riley] Remove all Ruby code from the gem. This gem now exists only to manage the dependency on dry-validation. (#230) 14 | 15 | ## v2.2.0.beta1 - 2024-07-16 16 | 17 | ### Changed 18 | 19 | - Drop support for Ruby 3.0 20 | 21 | ## v2.1.0 - 2024-02-27 22 | 23 | ## v2.1.0.rc3 - 2024-02-16 24 | 25 | ## v2.1.0.rc2 - 2023-11-08 26 | 27 | ## v2.1.0.rc1 - 2023-11-02 28 | 29 | ## v2.1.0.beta1 - 2023-06-29 30 | 31 | ## v2.0.1 - 2022-12-25 32 | 33 | ### Added 34 | 35 | - [Luca Guidi] Official support for Ruby 3.2 36 | 37 | ## v2.0.0 - 2022-11-22 38 | 39 | ### Added 40 | 41 | - [Tim Riley] Use Zeitwerk to autoload the gem 42 | 43 | ## v2.0.0.rc1 - 2022-11-08 44 | 45 | ## v2.0.0.beta4 - 2022-10-24 46 | 47 | ### Changed 48 | 49 | - [Tim Riley] Require latest dry-validation (to ensure best compatibility with Zeitwerk-enabled dry-rb gems) (#224) 50 | 51 | ## v2.0.0.beta1 - 2022-07-20 52 | 53 | ### Added 54 | 55 | - [Luca Guidi] Official support for Ruby: MRI 3.1 56 | 57 | ## v2.0.0.alpha2 - 2021-05-04 58 | 59 | ### Added 60 | 61 | - [Luca Guidi] Official support for Ruby: MRI 3.0 62 | 63 | ### Changed 64 | 65 | - [Luca Guidi] Drop support for Ruby: MRI 2.4, 2.5 66 | 67 | ## v2.0.0.alpha1 - 2019-07-26 68 | 69 | ### Added 70 | 71 | - [Luca Guidi] Introduced `Hanami::Validator` 72 | - [Luca Guidi] Added support to validate JSON data 73 | - [Luca Guidi] Added rules 74 | - [Luca Guidi] Allow to inherit validations from superclasses (e.g. `ApplicationValidator < Hanami::Validator` => `SignupValidator < ApplicationValidator`) 75 | - [Luca Guidi] Allow to error messages to receive arbitrary information as a `Hash` (e.g. `error_code: 123`), which will be interpolated in the final error message. 76 | - [Luca Guidi] Added support for validator external dependencies 77 | 78 | ### Changed 79 | 80 | - [Luca Guidi] Drop support for Ruby: MRI 2.3, JRuby 9.1. 81 | - [Luca Guidi] New validation syntax 82 | - [Luca Guidi] Removed custom predicates (`Hanami::Validations.predicate`) 83 | - [Luca Guidi] Removed global custom predicates (`Hanami::Validations::Predicates`) 84 | - [Luca Guidi] Removed messages path setting (`Hanami::Validations.messages_path=`) 85 | - [Luca Guidi] Removed messages namespace setting (`Hanami::Validations.namespace`) 86 | - [Luca Guidi] Removed messages engine setting (`Hanami::Validations.messages`) 87 | 88 | ## v1.3.7 - 2021-01-06 89 | 90 | ### Fixed 91 | 92 | - [Panagiotis Matsinopoulos] Ensure `predicate` and `predicates` to work together 93 | 94 | ## v1.3.6 - 2020-01-08 95 | 96 | ### Added 97 | 98 | - [Luca Guidi] Official support for Ruby: MRI 2.7 99 | 100 | ## v1.3.5 - 2019-07-26 101 | 102 | ### Fixed 103 | 104 | - [ippachi] Ensure I18n doesn't crash when used for inline predicates 105 | 106 | ## v1.3.4 - 2019-07-26 107 | 108 | ### Fixed 109 | 110 | - [Luca Guidi] Ensure to load i18n backend (including `i18n` gem), when messages engine is `:i18n` 111 | 112 | ## v1.3.3 - 2019-01-31 113 | 114 | ### Fixed 115 | 116 | - [Luca Guidi] Depend on `dry-validation` `~> 0.11`, `< 0.12` 117 | - [Luca Guidi] Depend on `dry-logic` `~> 0.4.2`, `< 0.5` 118 | 119 | ## v1.3.2 - 2019-01-30 120 | 121 | ### Fixed 122 | 123 | - [Luca Guidi] Depend on `dry-validation` `~> 0.11.2`, `< 0.12` in order to skip non compatible `dry-logic` `0.5.0` 124 | 125 | ## v1.3.1 - 2019-01-18 126 | 127 | ### Added 128 | 129 | - [Luca Guidi] Official support for Ruby: MRI 2.6 130 | - [Luca Guidi] Support `bundler` 2.0+ 131 | 132 | ## v1.3.0 - 2018-10-24 133 | 134 | ## v1.3.0.beta1 - 2018-08-08 135 | 136 | ### Added 137 | 138 | - [Luca Guidi] Official support for JRuby 9.2.0.0 139 | 140 | ## v1.2.2 - 2018-06-05 141 | 142 | ### Fixed 143 | 144 | - [Luca Guidi] Revert dependency to `dry-validation` to `~> 0.11`, `< 0.12` 145 | 146 | ## v1.2.1 - 2018-06-04 147 | 148 | ### Fixed 149 | 150 | - [Luca Guidi] Bump dependency to `dry-validation` to `~> 0.12` 151 | 152 | ## v1.2.0 - 2018-04-11 153 | 154 | ## v1.2.0.rc2 - 2018-04-06 155 | 156 | ## v1.2.0.rc1 - 2018-03-30 157 | 158 | ## v1.2.0.beta2 - 2018-03-23 159 | 160 | ## v1.2.0.beta1 - 2018-02-28 161 | 162 | ### Added 163 | 164 | - [Luca Guidi] Official support for Ruby: MRI 2.5 165 | 166 | ## v1.1.0 - 2017-10-25 167 | 168 | ## v1.1.0.rc1 - 2017-10-16 169 | 170 | ## v1.1.0.beta3 - 2017-10-04 171 | 172 | ## v1.1.0.beta2 - 2017-10-03 173 | 174 | ## v1.1.0.beta1 - 2017-08-11 175 | 176 | ## v1.0.0 - 2017-04-06 177 | 178 | ## v1.0.0.rc1 - 2017-03-31 179 | 180 | ## v1.0.0.beta2 - 2017-03-17 181 | 182 | ## v1.0.0.beta1 - 2017-02-14 183 | 184 | ### Added 185 | 186 | - [Luca Guidi] Official support for Ruby: MRI 2.4 187 | 188 | ### Fixed 189 | 190 | - [Luca Guidi] Don't let inline predicates to discard other YAML error messages 191 | 192 | ## v0.7.1 - 2016-11-18 193 | 194 | ### Fixed 195 | 196 | - [Luca Guidi] Ensure custom validators to work with concrete classes with name 197 | 198 | ## v0.7.0 - 2016-11-15 199 | 200 | ### Changed 201 | 202 | - [Luca Guidi] Official support for Ruby: MRI 2.3+ and JRuby 9.1.5.0+ 203 | 204 | ## v0.6.0 - 2016-07-22 205 | 206 | ### Added 207 | 208 | - [Luca Guidi] Predicates syntax 209 | - [Luca Guidi] Custom predicates 210 | - [Luca Guidi] Inline predicates 211 | - [Luca Guidi] Shared predicates 212 | - [Luca Guidi] High level rules 213 | - [Luca Guidi] Error messages with I18n support (`i18n` gem) 214 | - [Luca Guidi] Introduced `Hanami::Validations#validate`, which returns a result object. 215 | - [Luca Guidi] Introduced `Hanami::Validations::Form` mixin, which must be used when input comes from HTTP params or web forms. 216 | 217 | ### Fixed 218 | 219 | – [Luca Guidi] Ensure to threat blank values as `nil` 220 | 221 | ### Changed 222 | 223 | – [Luca Guidi] Drop support for Ruby 2.0, 2.1 and Rubinius. Official support for JRuby 9.0.5.0+. 224 | 225 | - [Luca Guidi] Validations must be wrapped in `.validations` block. 226 | - [Luca Guidi] Removed `.attribute` DSL. A validator doesn't create accessors (getters/setters) for validated keys. 227 | - [Luca Guidi] Removed `Hanami::Validations#valid?` in favor of `#validate`. 228 | - [Luca Guidi] Error messages are accessible via result object. Eg. `result.errors` or `result.errors(full: true)` 229 | - [Luca Guidi] Coerced and sanitized data is accessible via result object. Eg. `result.output` 230 | 231 | ## v0.5.0 - 2016-01-22 232 | 233 | ### Changed 234 | 235 | - [Luca Guidi] Renamed the project 236 | 237 | ## v0.4.0 - 2016-01-12 238 | 239 | ## Changed 240 | 241 | - [Hélio Costa e Silva & Luca Guidi] Ignore blank values for format and size validation 242 | 243 | ### Fixed 244 | 245 | - [Pascal Betz] Ensure acceptance validation to reject blank strings 246 | 247 | ## v0.3.3 - 2015-09-30 248 | 249 | ### Added 250 | 251 | - [Luca Guidi] Official support for JRuby 9k+ 252 | 253 | ## v0.3.2 - 2015-05-22 254 | 255 | ### Added 256 | 257 | - [deepj] Introduced `Lotus::Validations#invalid?` 258 | 259 | ## v0.3.1 - 2015-05-15 260 | 261 | ### Fixed 262 | 263 | - [Luca Guidi] Fixed Hash serialization for nested validations. It always return nested `::Hash` structure. 264 | - [Alfonso Uceda Pompa & Dmitry Tymchuk] Fixed Hash serialization when `Lotus::Entity` is included in the same class. 265 | 266 | ## v0.3.0 - 2015-03-23 267 | 268 | ## v0.2.4 - 2015-01-30 269 | 270 | ### Added 271 | 272 | - [Steve Hodgkiss] Introduced `Lotus::Validations::Error#attribute_name` 273 | - [Steve Hodgkiss] Nested validations 274 | 275 | ### Changed 276 | 277 | - [Steve Hodgkiss] `Lotus::Validations::Error#name` returns the complete attribute name (Eg. `first_name` or `address.street`) 278 | 279 | ## v0.2.3 - 2015-01-12 280 | 281 | ### Added 282 | 283 | - [Luca Guidi] Compatibility with Lotus::Entity 284 | 285 | ### Fixed 286 | 287 | - [Luca Guidi] Ensure `.validates` usage to not raise `ArgumentError` when `:type` option is passed 288 | - [Luca Guidi] Ensure to assign attributes when only `.validates` is used 289 | 290 | ## v0.2.2 - 2015-01-08 291 | 292 | ### Added 293 | 294 | - [Steve Hodgkiss] Introduced `Validations.validates`. It defines validations, for already existing attributes. 295 | 296 | ## v0.2.1 - 2014-12-23 297 | 298 | ### Added 299 | 300 | - [Luca Guidi] Introduced `Validations::Errors#to_h` and `to_a` 301 | - [Luca Guidi] Introduced `Validations::Errors#any?` 302 | - [Luca Guidi] Official support for Ruby 2.2 303 | 304 | ### Fixed 305 | 306 | - [Satoshi Amemiya] Made `Validations#valid?` idempotent 307 | 308 | ## v0.2.0 - 2014-11-23 309 | 310 | ### Added 311 | 312 | - [Luca Guidi] Skip attribute whitelisting when a validator does not define any attribute 313 | - [Luca Guidi] Official support for Rubinius 2.3+ 314 | - [Luca Guidi] Implemented `#each` in order to allow bulk operations on attributes 315 | - [Luca Guidi] Implemented `#to_h` to make validations usable by other libraries 316 | - [Luca Guidi] Made `#initialize` to accept Hashes with strings as keys, but only for declared attributes 317 | - [Luca Guidi] Lazy coercions, from now on `valid?` is not required to obtain a coerced value from a single attribute 318 | - [Rik Tonnard] Made validators reusable by allowing infinite inclusion 319 | 320 | ## v0.1.0 - 2014-10-23 321 | 322 | ### Added 323 | 324 | - [Luca Guidi] Made `#initialize` to accept any object that implements `#to_h` 325 | - [Luca Guidi] Custom coercions for user defined classes 326 | - [Luca Guidi] Raise an exception at the load time when a validation is not recognized 327 | - [Luca Guidi] Allow validators inheritance 328 | - [Luca Guidi] Confirmation validation 329 | - [Luca Guidi] Exclusion validation 330 | - [Luca Guidi] Size validation 331 | - [Luca Guidi] Acceptance validation 332 | - [Jeremy Stephens] Inclusion validation 333 | - [Luca Guidi] Format validation 334 | - [Luca Guidi] Presence validation 335 | - [Luca Guidi] Coercions 336 | - [Luca Guidi] Basic module inclusion 337 | - [Luca Guidi] Official support for JRuby 1.7+ (with 2.0 mode) 338 | - [Luca Guidi] Official support for MRI 2.0+ 339 | 340 | ### Fixed 341 | 342 | - [Jeremy Stephens] Ensure to not fail validations when coerce falsey values 343 | - [Luca Guidi] Ensure `Lotus::Validations#valid?` to be idempotent 344 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | 2 | # Contributor Covenant Code of Conduct 3 | 4 | ## Our Pledge 5 | 6 | We as members, contributors, and leaders pledge to make participation in our 7 | community a harassment-free experience for everyone, regardless of age, body 8 | size, visible or invisible disability, ethnicity, sex characteristics, gender 9 | identity and expression, level of experience, education, socio-economic status, 10 | nationality, personal appearance, race, caste, color, religion, or sexual 11 | identity and orientation. 12 | 13 | We pledge to act and interact in ways that contribute to an open, welcoming, 14 | diverse, inclusive, and healthy community. 15 | 16 | ## Our Standards 17 | 18 | Examples of behavior that contributes to a positive environment for our 19 | community include: 20 | 21 | * Demonstrating empathy and kindness toward other people 22 | * Being respectful of differing opinions, viewpoints, and experiences 23 | * Giving and gracefully accepting constructive feedback 24 | * Accepting responsibility and apologizing to those affected by our mistakes, 25 | and learning from the experience 26 | * Focusing on what is best not just for us as individuals, but for the overall 27 | community 28 | 29 | Examples of unacceptable behavior include: 30 | 31 | * The use of sexualized language or imagery, and sexual attention or advances of 32 | any kind 33 | * Trolling, insulting or derogatory comments, and personal or political attacks 34 | * Public or private harassment 35 | * Publishing others' private information, such as a physical or email address, 36 | without their explicit permission 37 | * Other conduct which could reasonably be considered inappropriate in a 38 | professional setting 39 | 40 | ## Enforcement Responsibilities 41 | 42 | Community leaders are responsible for clarifying and enforcing our standards of 43 | acceptable behavior and will take appropriate and fair corrective action in 44 | response to any behavior that they deem inappropriate, threatening, offensive, 45 | or harmful. 46 | 47 | Community leaders have the right and responsibility to remove, edit, or reject 48 | comments, commits, code, wiki edits, issues, and other contributions that are 49 | not aligned to this Code of Conduct, and will communicate reasons for moderation 50 | decisions when appropriate. 51 | 52 | ## Scope 53 | 54 | This Code of Conduct applies within all community spaces, and also applies when 55 | an individual is officially representing the community in public spaces. 56 | Examples of representing our community include using an official e-mail address, 57 | posting via an official social media account, or acting as an appointed 58 | representative at an online or offline event. 59 | 60 | ## Enforcement 61 | 62 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 63 | reported to the community leaders responsible for enforcement at 64 | [INSERT CONTACT METHOD]. 65 | All complaints will be reviewed and investigated promptly and fairly. 66 | 67 | All community leaders are obligated to respect the privacy and security of the 68 | reporter of any incident. 69 | 70 | ## Enforcement Guidelines 71 | 72 | Community leaders will follow these Community Impact Guidelines in determining 73 | the consequences for any action they deem in violation of this Code of Conduct: 74 | 75 | ### 1. Correction 76 | 77 | **Community Impact**: Use of inappropriate language or other behavior deemed 78 | unprofessional or unwelcome in the community. 79 | 80 | **Consequence**: A private, written warning from community leaders, providing 81 | clarity around the nature of the violation and an explanation of why the 82 | behavior was inappropriate. A public apology may be requested. 83 | 84 | ### 2. Warning 85 | 86 | **Community Impact**: A violation through a single incident or series of 87 | actions. 88 | 89 | **Consequence**: A warning with consequences for continued behavior. No 90 | interaction with the people involved, including unsolicited interaction with 91 | those enforcing the Code of Conduct, for a specified period of time. This 92 | includes avoiding interactions in community spaces as well as external channels 93 | like social media. Violating these terms may lead to a temporary or permanent 94 | ban. 95 | 96 | ### 3. Temporary Ban 97 | 98 | **Community Impact**: A serious violation of community standards, including 99 | sustained inappropriate behavior. 100 | 101 | **Consequence**: A temporary ban from any sort of interaction or public 102 | communication with the community for a specified period of time. No public or 103 | private interaction with the people involved, including unsolicited interaction 104 | with those enforcing the Code of Conduct, is allowed during this period. 105 | Violating these terms may lead to a permanent ban. 106 | 107 | ### 4. Permanent Ban 108 | 109 | **Community Impact**: Demonstrating a pattern of violation of community 110 | standards, including sustained inappropriate behavior, harassment of an 111 | individual, or aggression toward or disparagement of classes of individuals. 112 | 113 | **Consequence**: A permanent ban from any sort of public interaction within the 114 | community. 115 | 116 | ## Attribution 117 | 118 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 119 | version 2.1, available at 120 | [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]. 121 | 122 | Community Impact Guidelines were inspired by 123 | [Mozilla's code of conduct enforcement ladder][Mozilla CoC]. 124 | 125 | For answers to common questions about this code of conduct, see the FAQ at 126 | [https://www.contributor-covenant.org/faq][FAQ]. Translations are available at 127 | [https://www.contributor-covenant.org/translations][translations]. 128 | 129 | [homepage]: https://www.contributor-covenant.org 130 | [v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html 131 | [Mozilla CoC]: https://github.com/mozilla/diversity 132 | [FAQ]: https://www.contributor-covenant.org/faq 133 | [translations]: https://www.contributor-covenant.org/translations 134 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | source "http://rubygems.org" 4 | gemspec 5 | 6 | unless ENV["CI"] 7 | gem "byebug", require: false, platforms: :mri 8 | gem "yard", require: false 9 | end 10 | 11 | gem "hanami-devtools", require: false, github: "hanami/devtools" 12 | gem "i18n", "~> 1.0", require: false 13 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright © 2014 Hanami Team 2 | 3 | MIT License 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Hanami::Validations 2 | 3 | Internal support gem for `Hanami::Action` params validation. 4 | 5 | ## Status 6 | 7 | [![Gem Version](https://badge.fury.io/rb/hanami-validations.svg)](https://badge.fury.io/rb/hanami-validations) 8 | [![CI](https://github.com/hanami/validations/actions/workflows/ci.yml/badge.svg)](https://github.com/hanami/validations/actions?query=workflow%3Aci+branch%3Amain) 9 | [![Test Coverage](https://codecov.io/gh/hanami/validations/branch/main/graph/badge.svg)](https://codecov.io/gh/hanami/validations) 10 | [![Depfu](https://badges.depfu.com/badges/af6c6be539d9d587c7541ae7a013c9ff/overview.svg)](https://depfu.com/github/hanami/validations?project=Bundler) 11 | 12 | ## Contact 13 | 14 | * Home page: http://hanamirb.org 15 | * Community: http://hanamirb.org/community 16 | * Guides: https://guides.hanamirb.org 17 | * Mailing List: http://hanamirb.org/mailing-list 18 | * API Doc: http://rubydoc.info/gems/hanami-validations 19 | * Bugs/Issues: https://github.com/hanami/validations/issues 20 | * Chat: http://chat.hanamirb.org 21 | 22 | ## Installation 23 | 24 | __Hanami::Validations__ supports Ruby (MRI) 3.1+ 25 | 26 | Add this line to your application's Gemfile: 27 | 28 | ```ruby 29 | gem "hanami-validations" 30 | ``` 31 | 32 | And then execute: 33 | 34 | ```shell 35 | $ bundle 36 | ``` 37 | 38 | Or install it yourself as: 39 | 40 | ```shell 41 | $ gem install hanami-validations 42 | ``` 43 | 44 | ## Usage 45 | 46 | Installing hanami-validations enables support for `params` validation in 47 | [hanami-controller][controller]’s `Hanami::Action` classes. 48 | 49 | ```ruby 50 | class Signup < Hanami::Action 51 | params do 52 | required(:first_name) 53 | required(:last_name) 54 | required(:email) 55 | end 56 | 57 | def handle(req, *) 58 | puts req.params.class # => Signup::Params 59 | puts req.params.class.superclass # => Hanami::Action::Params 60 | 61 | puts req.params[:first_name] # => "Luca" 62 | puts req.params[:admin] # => nil 63 | end 64 | end 65 | ``` 66 | 67 | See [hanami-controller][controller] for more detail on params validation. 68 | 69 | [controller]: http://github.com/hanami/controller 70 | 71 | ## Contributing 72 | 73 | 1. Fork it ( https://github.com/hanami/validations/fork ) 74 | 2. Create your feature branch (`git checkout -b my-new-feature`) 75 | 3. Commit your changes (`git commit -am 'Add some feature'`) 76 | 4. Push to the branch (`git push origin my-new-feature`) 77 | 5. Create a new Pull Request 78 | 79 | ## Copyright 80 | 81 | Copyright © 2014–2024 Hanami Team – Released under MIT License 82 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "rake" 4 | require "bundler/gem_tasks" 5 | require "rspec/core/rake_task" 6 | require "hanami/devtools/rake_tasks" 7 | 8 | namespace :spec do 9 | RSpec::Core::RakeTask.new(:unit) do |task| 10 | file_list = FileList["spec/**/*_spec.rb"] 11 | file_list = file_list.exclude("spec/{integration,isolation}/**/*_spec.rb") 12 | 13 | task.pattern = file_list 14 | end 15 | end 16 | 17 | task default: "spec:unit" 18 | -------------------------------------------------------------------------------- /hanami-validations.gemspec: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | lib = File.expand_path("../lib", __FILE__) 4 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 5 | require "hanami/validations/version" 6 | 7 | Gem::Specification.new do |spec| 8 | spec.name = "hanami-validations" 9 | spec.version = Hanami::Validations::VERSION 10 | spec.authors = ["Luca Guidi"] 11 | spec.email = ["me@lucaguidi.com"] 12 | spec.summary = "Validations mixin for Ruby objects" 13 | spec.description = "Validations mixin for Ruby objects and support for Hanami" 14 | spec.homepage = "http://hanamirb.org" 15 | spec.license = "MIT" 16 | 17 | spec.files = `git ls-files -- lib/* LICENSE.md README.md CHANGELOG.md hanami-validations.gemspec`.split($/) 18 | spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } 19 | spec.require_paths = ["lib"] 20 | spec.metadata["rubygems_mfa_required"] = "true" 21 | spec.required_ruby_version = ">= 3.1" 22 | 23 | spec.add_dependency "dry-validation", ">= 1.10", "< 2" 24 | 25 | spec.add_development_dependency "bundler", ">= 1.6", "< 3" 26 | spec.add_development_dependency "rake", "~> 13" 27 | spec.add_development_dependency "rspec", "~> 3.9" 28 | spec.add_development_dependency "rubocop", "~> 1.0" 29 | end 30 | -------------------------------------------------------------------------------- /lib/hanami-validations.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative "hanami/validations" 4 | -------------------------------------------------------------------------------- /lib/hanami/validations.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "dry/validation" 4 | 5 | # @see Hanami::Validations 6 | # @since 0.1.0 7 | module Hanami 8 | # @since 0.1.0 9 | # @api private 10 | module Validations 11 | require_relative "validations/version" 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /lib/hanami/validations/version.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Hanami 4 | module Validations 5 | # The current hanami-validations version. 6 | # 7 | # @since 0.1.0 8 | # @api public 9 | VERSION = "2.2.0" 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /script/ci: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euo pipefail 3 | IFS=$'\n\t' 4 | 5 | prepare_build() { 6 | if [ -d coverage ]; then 7 | rm -rf coverage 8 | fi 9 | } 10 | 11 | print_ruby_version() { 12 | echo "Using $(ruby -v)" 13 | echo 14 | } 15 | 16 | run_code_quality_checks() { 17 | bundle exec rubocop . 18 | } 19 | 20 | run_unit_tests() { 21 | bundle exec rake spec:unit 22 | } 23 | 24 | run_isolation_tests() { 25 | local pwd=$PWD 26 | local root="$pwd/spec/isolation" 27 | 28 | if [ -d $root ]; then 29 | for test in $(find $root -name '*_spec.rb') 30 | do 31 | run_isolation_test $test 32 | 33 | if [ $? -ne 0 ]; then 34 | local exit_code=$? 35 | echo "Failing test: $test" 36 | exit $exit_code 37 | fi 38 | done 39 | fi 40 | } 41 | 42 | run_isolation_test() { 43 | local test=$1 44 | 45 | printf "\n\n\nRunning: $test\n" 46 | ruby $test --options spec/isolation/.rspec 47 | } 48 | 49 | run_test() { 50 | local test=$1 51 | 52 | printf "\n\n\nRunning: $test\n" 53 | COVERAGE=true bundle exec rspec $test 54 | } 55 | 56 | upload_code_coverage() { 57 | bundle exec rake codecov:upload 58 | } 59 | 60 | main() { 61 | prepare_build 62 | print_ruby_version 63 | run_code_quality_checks 64 | run_unit_tests 65 | run_isolation_tests 66 | # upload_code_coverage 67 | } 68 | 69 | main 70 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | RSpec.configure do |config| 4 | config.expect_with :rspec do |expectations| 5 | expectations.include_chain_clauses_in_custom_matcher_descriptions = true 6 | end 7 | 8 | config.mock_with :rspec do |mocks| 9 | mocks.verify_partial_doubles = true 10 | end 11 | 12 | config.shared_context_metadata_behavior = :apply_to_host_groups 13 | 14 | config.filter_run_when_matching :focus 15 | 16 | config.disable_monkey_patching! 17 | config.warnings = true 18 | 19 | config.default_formatter = "doc" if config.files_to_run.one? 20 | 21 | config.profile_examples = 10 22 | 23 | config.order = :random 24 | Kernel.srand config.seed 25 | end 26 | 27 | require "i18n" 28 | require "pathname" 29 | SPEC_ROOT = Pathname.new(__dir__) 30 | 31 | require "hanami/validations" 32 | -------------------------------------------------------------------------------- /spec/support/errors.yml: -------------------------------------------------------------------------------- 1 | en: 2 | bookshelf: 3 | errors: 4 | taken: "oh noes, it's already taken" 5 | network: "there is a network error (%{code})" 6 | rules: 7 | age: 8 | invalid: "must be greater than 18" 9 | email: 10 | invalid: "not a valid email" 11 | -------------------------------------------------------------------------------- /spec/unit/hanami/validations/version_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | RSpec.describe "Hanami::Validations::VERSION" do 4 | it "returns current version" do 5 | expect(Hanami::Validations::VERSION).to eq("2.2.0") 6 | end 7 | end 8 | --------------------------------------------------------------------------------