plumatic / schema

Clojure(Script) library for declarative data description and validation
Other
2.41k stars 257 forks source link

coerce integer to a double #334

Closed sonwh98 closed 8 years ago

sonwh98 commented 8 years ago
(def Product
  {(s/optional-key :db/id) #?(:clj datomic.db.DbId
                              :cljs s/Any)
   :product/name  s/Str
   :product/sku s/Str
   :url s/Str
   :product/price #?(:cljs s/Num
                     :clj Double)})

(defn number-matcher [schema]
  (println schema)
  (when (= schema Double)
    (coerce/safe (fn [x]
                   (println "parseDouble" (parseDouble x))
                   (cond
                     (re-matches #"^\d+\.*\d+$" x) (parseDouble x)
                     (re-matches #"^\d+$" x) (parseDouble (str x ".0"))
                     (integer? x) (parseDouble (str x ".0")))))))

(def coercer (coerce/coercer Product number-matcher))

(defn coerce-product [product-map]
  (coercer product-map))

(coerce-product {:product/name "dfafda", :product/sku "d", :url "http://pngimg.com/upload/orange_PNG791.png", :product/price 1})

coerce-product does not seem to coerce :product/price from integer to double. It works if :product/price is a String but dhe conerce/safe closure does not get executed when price is an integer. How can I coerce an integet to a double?

davegolland commented 8 years ago

What happens if you leave off the coerce/safe?

It seems like the re-matches might throw an exception if the x it is testing against is not a String (or CharSequence).

Would it work if you prefixed the re-matches with a check to make sure x is a string? e.g.:

 (cond 
   (and (string? x) (re-matches #"^\d+\.*\d+$" x)) (parseDouble x)
    ...)
w01fe commented 8 years ago

I think @davegolland has the right answer. You could also reorder the clauses to put the integer? one first. If this doesn't resolve the issue, please feel free to reopen with more context. Thanks!