-
Notifications
You must be signed in to change notification settings - Fork 37
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
Multi-field validation #21
Comments
For the validate function something like [:password :confirmation] would mean a nested map having a confirmation as a key inside password. I don't think password confirmation will be a good idea. Is it possible for the DSL to let the user decide how the returned error keys should be named in case we don't want the same name as the key itself something ? For example: In a web form, if the error key is that of a field I would show the error below that field using the key of the error. but if the error is generic and not specific to one key, I would show such error somewhere else. probably at a common place other than below each fields. How about having a macro called "as-key" to which we pass desired key and list of arguments ?
|
Hi @amogh-talpallikar , Those are all valid points and I still don't have an answer to them. I've posted this mostly to get some initial feedback and ideas. Your comments and suggestions are appreciated. The proposed change would require an update on how nested validations work, as you point out, but would keep backwards compatibility with existing validators. Another option is to have each validator take an optional last argument which is the map being validated. That would make writing such a validator trivial: (defn less-than [k value subject]
(< value (k subject)))
(b/validate subject
:from [[(partial less-than :to)]]
:to [[v/required]]) But in this case I'm still not convinced about the syntax. Will need to give it some more thought. |
In fact I just played with this implementation and it works: (defn less-than [k]
(fn [value subject]
(< value (k subject))))
(core/valid? {:from 20 :to 10}
:from [v/required (less-than :to)])
;; false
(defn same-as [k]
(fn [value subject]
(= value (k subject))))
(core/valid? {:password 123 :confirmation 123}
:password [v/required (same-as :confirmation)])
;; true The implementation itself is terribly simple. The drawback is that it breaks compatibility with existing validators - validator functions would receive a minimum of 2 arguments: the value in the key provided and the original map being validated, called the subject. I don't have a problem with backwards compatibility in future releases if this is a feature important enough to have. Let me know your thoughts. |
Hi Leonardo. Our team is using bouncer to perform validations in simple web app we're working on. Now I want to implement a validation function which checks uniqueness of a value inside DB (email, login, etc). At first it looks simple, but I faced a problem: I don't have a whole map in validation fn, just the value on which validation is performed. But I need a whole map to perform query like this: (db/q {:select "COUNT(*)"
:from "users"
:where (format "login = '%s' AND id <> %d" value (:id subject)) Could you push a experimental branch with two-arguments validation functions to GitHub? We are ready to test this branch inside our project. Mike. |
Hey Mike, and while using, |
Hi @mlapshin , As @amogh-talpallikar pointed out, there is a workaround. Nevertheless, I have pushed an experimental version to a new branch on github here. All validator functions receive one extra argument at the end, the original map. All tests are passing though there are a couple missing. Also, if you're using any clojure.core functions as validators - such as It looks like this: (require '[bouncer
[core :as core]
[validators :as v]
[utils :refer [bouncify]]])
(core/validate {:age -1 :year ""}
:name v/required
:year v/number
:age v/positive
:dob (bouncify (complement nil?))) It would be a big help if you could give this branch a go and let me know what you think about the API. Thanks |
Hi @mlapshin , I'm wondering if you had a chance to try the new branch out? I'm more and more inclined and making bouncer go in that direction for the next release but some feedback would be great before I make the decision. Also if we do go in that direction, |
Hi guys, I'm closing this issue as I haven't heard anything back yet. Feel free to re-open in case this is still an issue. Thanks |
Bumped into this issue recently; used the workaround solution above (thanks @amogh-talpallikar ), which works. If there are no plans to rollout the new API, some documentation about mult-field validation would be really helpful |
I've bumped into this too. The workaround above won't work if you've been defining common sets of validators to include in larger validation suites, as they're defined using (def {field name validation-set}), with no access to the map being validated. This means I've to copy the same validator to different locations in my project. I've not tried the multi-field validation branch as I'm not sure what stage it's at vs. the main branch. |
Currently if I want to validate that
:from
is less than:to
in a map I have to write a custom validator on the following lines:I hadn't implemented this feature so far as I didn't come up with an API I was happy with. After some thought I have some ideas that would allow the previous example to be written as:
This would be flexible enough to allow for other usages. For example, password confirmation could be validated as such:
Validator functions used in multi-field validations need an arity equal to the length of keywords in the vector preceding the validators.
How does this API look to you?
The text was updated successfully, but these errors were encountered: