Почему я вижу ошибку несоответствия параметров в Luminus (Clojure)? - PullRequest
0 голосов
/ 22 марта 2020

Редактировать (исправлено) ...

Если вы следуете учебнику по гостевой книге Luminus или адаптируете его части, вы можете столкнуться с ошибкой типа Parameter Mismatch: :name parameter data not found., и она может не go прочь, независимо от того, какие параметры вы используете. Вы можете обнаружить, что пытаетесь вызвать функцию, которая не существует, и что Conman / Hug SQL не знает, что с ней делать.

Ответ на мой вопрос находится в разделе ниже :


Соответствующий раздел кода находится в myapp.routes.home/create-user!

(defn create-user! [{:keys [params]}]
  (if-let [errors (validate-user params)]
    (-> (response/found "/users")
        (assoc :flash (assoc params :errors errors)))
    (do
      (db/create-user!
       (assoc params
              :created_at (java.util.Date.)
              :updated_at (java.util.Date.)
              :pass (generate-password 8)))
      (response/found "/users"))))

Код ниже был неправильным:

:pass (generate-password 8)) ; <-- 2 parentheses at the end of line.
       (response/found "/users"))))) ; <-- 5 parentheses at the end of line.

Я исправил его, изменив его как показано ниже:

:pass (generate-password 8))) ; <-- 3 parentheses at the end of line.
       (response/found "/users")))) ; <-- 4 parentheses at the end of line.

Так что оказалось, что я передаю неверное количество аргументов в db / create-user! и кажется, что Конман понятия не имел, как вызвать запрос.

Кроме того, я небрежно исправил некоторые вещи в своих миграциях - редактируя имевшиеся миграции. Я заметил, что Конман, похоже, не замечает, изменяете ли вы старые миграции и запросы. sql файлов. Если вы обнаружите, что запросы. sql не отражает API вашего БД (поэтому вы по-прежнему получаете сообщение о параметре ID, когда вы устанавливаете для поля идентификатора значение автоинкремента, тогда вам нужно заставить Conman восстановить ваш API БД.

Это можно сделать в REPL следующим образом:

user> (ns myapp.db.core)
nil
myapp.db.core> (conman/bind-connection *db* "sql/queries.sql")

Оригинальный пост ниже

Действительно простое приложение, которое я собираю на основе более или менее основанного на учебник по гостевой книге Luminus , и я просто пытаюсь протестировать форму create-user! в http://localhost: 3000 / users . Всякий раз, когда я отправляю форму, я получаю некоторые варианты Parameter Mismatch: :username parameter data not found. Не указывается c до :username. Какие бы параметры я ни отправлял, я получаю :first_name parameter data not found. или что-то подобное.

The error page I see

Вот расширенный раздел параметров: The params it says I'm sending

Я сделал println в myapp.routes.home/create-user!, и я знаю, что все параметры присутствуют до этого момента. Я не уверен как отследить это дальше. Буду признателен за любые советы по отладке отсюда, а также, если кто-то видит что-то, что я делаю неправильно, это было бы очень полезно.

Трассировка стека:

$ lein run
2020-03-22 16:34:47,244 [main] DEBUG org.jboss.logging - Logging Provider: org.jboss.logging.Slf4jLoggerProvider 
2020-03-22 16:34:47,897 [main] INFO  myapp.env - 
-=[myapp started successfully using the development profile]=- 
2020-03-22 16:34:48,471 [main] INFO  luminus.http-server - starting HTTP server on port 3000 
2020-03-22 16:34:48,496 [main] DEBUG io.undertow - starting undertow server io.undertow.Undertow@591ea3da 
2020-03-22 16:34:48,503 [main] INFO  org.xnio - XNIO version 3.3.6.Final 
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by org.xnio.nio.NioXnio$2 (file:/Users/mattlally/.m2/repository/org/jboss/xnio/xnio-nio/3.3.6.Final/xnio-nio-3.3.6.Final.jar) to constructor sun.nio.ch.KQueueSelectorProvider()
WARNING: Please consider reporting this to the maintainers of org.xnio.nio.NioXnio$2
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
2020-03-22 16:34:48,616 [main] DEBUG io.undertow - Configuring listener with protocol HTTP for interface 0.0.0.0 and port 3000 
2020-03-22 16:34:48,659 [main] INFO  org.projectodd.wunderboss.web.Web - Registered web context / 
2020-03-22 16:34:48,659 [main] INFO  myapp.nrepl - starting nREPL server on port 7000 
2020-03-22 16:34:48,676 [main] INFO  myapp.core - #'myapp.db.core/*db* started 
2020-03-22 16:34:48,677 [main] INFO  myapp.core - #'myapp.handler/init-app started 
2020-03-22 16:34:48,677 [main] INFO  myapp.core - #'myapp.handler/app-routes started 
2020-03-22 16:34:48,677 [main] INFO  myapp.core - #'myapp.core/http-server started 
2020-03-22 16:34:48,677 [main] INFO  myapp.core - #'myapp.core/repl-server started 
java.lang.Exception: Exception in :create-user!
    at conman.core$try_query$fn__33540$fn__33541.invoke(core.clj:32)
    at clojure.lang.AFn.applyToHelper(AFn.java:156)
    at clojure.lang.RestFn.applyTo(RestFn.java:132)
    at clojure.core$apply.invokeStatic(core.clj:669)
    at clojure.core$apply.invoke(core.clj:660)
    at myapp.db.core$eval35973$f__33568__auto____36000.doInvoke(core.clj:13)
    at clojure.lang.RestFn.invoke(RestFn.java:425)
    at myapp.routes.home$create_user_BANG_.invokeStatic(home.clj:46)
    at myapp.routes.home$create_user_BANG_.invoke(home.clj:41)
    at muuntaja.middleware$wrap_params$fn__28296.invoke(middleware.clj:52)
    at muuntaja.middleware$wrap_format$fn__28300.invoke(middleware.clj:73)
    at myapp.middleware$wrap_formats$fn__31491.invoke(middleware.clj:42)
    at ring.middleware.anti_forgery$wrap_anti_forgery$fn__27132.invoke(anti_forgery.clj:94)
    at reitit.ring$ring_handler$fn__38011.invoke(ring.cljc:292)
    at clojure.lang.AFn.applyToHelper(AFn.java:154)
    at clojure.lang.AFn.applyTo(AFn.java:144)
    at clojure.lang.AFunction$1.doInvoke(AFunction.java:31)
    at clojure.lang.RestFn.invoke(RestFn.java:408)
    at clojure.lang.Var.invoke(Var.java:384)
    at ring.middleware.reload$wrap_reload$fn__24791.invoke(reload.clj:39)
    at selmer.middleware$wrap_error_page$fn__24806.invoke(middleware.clj:18)
    at prone.middleware$wrap_exceptions$fn__25047.invoke(middleware.clj:159)
    at ring.middleware.flash$wrap_flash$fn__28337.invoke(flash.clj:39)
    at immutant.web.internal.undertow$wrap_undertow_session$fn__39192.invoke(undertow.clj:72)
    at ring.middleware.keyword_params$wrap_keyword_params$fn__31059.invoke(keyword_params.clj:53)
    at ring.middleware.nested_params$wrap_nested_params$fn__31117.invoke(nested_params.clj:89)
    at ring.middleware.multipart_params$wrap_multipart_params$fn__31249.invoke(multipart_params.clj:173)
    at ring.middleware.params$wrap_params$fn__31273.invoke(params.clj:67)
    at ring.middleware.cookies$wrap_cookies$fn__30892.invoke(cookies.clj:214)
    at ring.middleware.absolute_redirects$wrap_absolute_redirects$fn__31411.invoke(absolute_redirects.clj:47)
    at ring.middleware.resource$wrap_resource_prefer_resources$fn__31309.invoke(resource.clj:25)
    at ring.middleware.content_type$wrap_content_type$fn__31359.invoke(content_type.clj:34)
    at ring.middleware.default_charset$wrap_default_charset$fn__31383.invoke(default_charset.clj:31)
    at ring.middleware.not_modified$wrap_not_modified$fn__19539.invoke(not_modified.clj:61)
    at ring.middleware.x_headers$wrap_x_header$fn__30560.invoke(x_headers.clj:22)
    at ring.middleware.x_headers$wrap_x_header$fn__30560.invoke(x_headers.clj:22)
    at ring.middleware.x_headers$wrap_x_header$fn__30560.invoke(x_headers.clj:22)
    at myapp.middleware$wrap_internal_error$fn__31485.invoke(middleware.clj:21)
    at immutant.web.internal.undertow$create_http_handler$reify__39303.handleRequest(undertow.clj:239)
    at org.projectodd.wunderboss.web.undertow.async.websocket.UndertowWebsocket$2.handleRequest(UndertowWebsocket.java:109)
    at io.undertow.server.session.SessionAttachmentHandler.handleRequest(SessionAttachmentHandler.java:68)
    at io.undertow.server.Connectors.executeRootHandler(Connectors.java:211)
    at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:809)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
    at java.base/java.lang.Thread.run(Thread.java:835)
Caused by: clojure.lang.ExceptionInfo: Parameter Mismatch: :username parameter data not found. {}
    at hugsql.core$validate_parameters_BANG_.invokeStatic(core.clj:83)
    at hugsql.core$validate_parameters_BANG_.invoke(core.clj:69)
    at hugsql.core$prepare_sql.invokeStatic(core.clj:185)
    at hugsql.core$prepare_sql.invoke(core.clj:173)
    at hugsql.core$db_fn_STAR_$y__33452.doInvoke(core.clj:457)
    at clojure.lang.RestFn.invoke(RestFn.java:445)
    at hugsql.core$db_fn_STAR_$y__33452.invoke(core.clj:448)
    at conman.core$try_query$fn__33540$fn__33541.invoke(core.clj:30)
    ... 45 more

Ответы [ 2 ]

1 голос
/ 23 марта 2020

Я также столкнулся с этой проблемой, когда вы хотите, чтобы возвращаемое значение выражения было чем-то отличным от сути блока кода. Он создает то, что я называю проблемой «зависшего выражения», и его легко потерять или пропустить последний маленький кусочек кода, особенно в большом блоке do (или аналогичном, таком как when, when-not, et * 1029). *). Даже с помощью средства форматирования кода (например, IntelliJ IDEA / Cursive) нелегко проверить правильность выравнивания кода и размещения скобок.

Чтобы сделать такие блоки кода проще для чтения, я создал супер-простой макрос with-result в в библиотеке Тупело . Реализация - это почти "Hello World" для изучения макросов:

(defmacro with-result
  "Evaluates `result` and returns it; also evaluates `forms` for their side-effects."
  [result & forms]
  `(let [result# ~result]
     (do ~@forms)
     result#))

Используя макрос with-result, ваш код станет следующим:


(ns tst.demo.core
  (:require [tupelo.core :as t]))

(defn create-user! [{:keys [params]}]
  (if-let [errors (validate-user params)]
    ; found existing user
    (-> (response/found "/users")
      (assoc :flash (assoc params :errors errors)))
    ; need to create new user
    (t/with-result (response/found "/users")
      (db/create-user!
        (assoc params
          :created_at (java.util.Date.)
          :updated_at (java.util.Date.)
          :pass (generate-password 8))))))

Вы можете видеть, что я добавил простые комментарии, которые помогут выделить каждую ветку if и обобщить, что она делает.

Вы также можете упростить задачу, вызвав (response/found ...) в одном месте:

(defn create-user! [{:keys [params]}]
  (let [errors   (validate-user params)
        response (response/found "/users")]
    (if errors
      (assoc response :flash (assoc params :errors errors))
      (t/with-result response
        (db/create-user!
          (assoc params
            :created_at (java.util.Date.)
            :updated_at (java.util.Date.)
            :pass (generate-password 8)))))))

. with-result также очень удобен для печати возвращаемого значения непосредственно перед выход из функции или для core.async кода, где канал core.async должен быть возвращен в конце большого кодового блока.

0 голосов
/ 23 марта 2020

В моем обращении к db / create-user !, в myapp.routes.home / create-user !, я случайно передал дополнительный аргумент. Это взрывалось, когда Конман пытался что-то с этим сделать. Код и пояснения в оригинальном посте. Краткий ответ: я неправильно сосчитал свои скобки. : /

...