Sinatra:提交时参数散列中缺少表单数据

Sinatra: form data is missing from the params hash upon submission

我正在用 Sinatra 编写一个非常基本的 CRUD 应用程序(这是一个制作 CRUD 应用程序的 CRUD 应用程序,物有所值)。创建功能工作正常,但更新功能不起作用。控制器未在参数哈希中接收表单数据。我可以看到在 Chrome Dev Tools 中收集的表单数据,但是当它到达控制器时,参数哈希看起来像 {"splat"=>[], "captures"=>["23"], "id"=>"23"} 而不是 {"crudapp"=>{"title"=>"Promises", "description"=>"tbd", "model"=>"Promise"}, "columns"=>[{"key_name"=>"name", "data_type"=>"String"}, {"key_name"=>"description", "data_type"=>"String"}, {"key_name"=>"fulfillment", "data_type"=>"Boolean"}]}。我错过了什么?相关代码如下。

edit.erb

<div class="entry-header">edit an app</div>
<form method="post" action="/crudapps/<%= @crudapp.id %>">
  <input type="hidden" name="crudapp[user_id]" value="<%= @crudapp.user_id %>">

  <ul class="basic-form">
    <li>
      <label for="crudapp[title]">Application title</label>
      <input class="fieldbox" type="text" name="crudapp[title]" value="<%= @crudapp.title %>">
    </li>
    <li>
      <label for="crudapp[description]">Description</label>
      <textarea name="crudapp[description]"><%= @crudapp.description %></textarea>
    </li>
    <li>
      <label for="crudapp[model]">Item name</label>
      <input class="fieldbox" type="text" name="crudapp[model]" value="<%= @crudapp.model %>">
    </li>

    <input type="hidden" name="columns[0][id]" value="<%= @crudapp.columns[0].id %>">

    <li>
      <label for="columns[][key_name]">First attribute name</label>
      <input class="fieldbox" type="text" name="columns[0][key_name]" value="<%= @crudapp.columns[0].key_name %>">
    </li>
    <li>
      <label for="columns[0][data_type]">First attribute data type</label>
      <select name="columns[0][data_type]">
        <option value="String" <%= 'selected' if @crudapp.columns[0].data_type=='String' %>>String</option>
        <option value="Number" <%= 'selected' if @crudapp.columns[0].data_type=='Number' %>>Number</option>
        <option value="Date" <%= 'selected' if @crudapp.columns[0].data_type=='Date' %>>Date</option>
        <option value="Boolean" <%= 'selected' if @crudapp.columns[0].data_type=='Boolean' %>>Boolean</option>
      </select>
    </li>

    <input type="hidden" name="columns[1][id]" value="<%= @crudapp.columns[1].id %>">

    <li>
      <label for="columns[][key_name]">Second attribute name</label>
      <input class="fieldbox" type="text" name="columns[1][key_name]" value="<%= @crudapp.columns[1].key_name %>">
    </li>
    <li>
      <label for="columns[1][data_type]">Second attribute data type</label>
      <select name="columns[1][data_type]">
        <option value="String" <%= 'selected' if @crudapp.columns[1].data_type=='String' %>>String</option>
        <option value="Number" <%= 'selected' if @crudapp.columns[1].data_type=='Number' %>>Number</option>
        <option value="Date" <%= 'selected' if @crudapp.columns[1].data_type=='Date' %>>Date</option>
        <option value="Boolean" <%= 'selected' if @crudapp.columns[1].data_type=='Boolean' %>>Boolean</option>
      </select>
    </li>

    <input type="hidden" name="columns[2][id]" value="<%= @crudapp.columns[2].id %>">

    <li>
      <label for="columns[][key_name]">Third attribute name</label>
      <input class="fieldbox" type="text" name="columns[][key_name]" value="<%= @crudapp.columns[2].key_name %>">
    </li>
    <li>
      <label for="columns[2][data_type]">Third attribute data type</label>
      <select name="columns[2][data_type]">
        <option value="String" <%= 'selected' if @crudapp.columns[2].data_type=='String' %>>String</option>
        <option value="Number" <%= 'selected' if @crudapp.columns[2].data_type=='Number' %>>Number</option>
        <option value="Date" <%= 'selected' if @crudapp.columns[2].data_type=='Date' %>>Date</option>
        <option value="Boolean" <%= 'selected' if @crudapp.columns[2].data_type=='Boolean' %>>Boolean</option>
      </select>
    </li>
    <li>
      <label for="crudapp[github]">GitHub link</label>
      <input class="fieldbox" type="text" name="crudapp[github]" value="<%= @crudapp.github %>">
    </li>
    <li>
      <label for="crudapp[web]">Web link</label>
      <input class="fieldbox" type="text" name="crudapp[web]" value="<%= @crudapp.web %>">
    </li>
  </ul>

  <div class="entry-submit-margin">
    <input class="entry-submit" type="submit" value="submit">
  </div>
</form>

application_controller.rb

class ApplicationController < Sinatra::Base

   # lots of other routes omitted

   post "/crudapps/:id" do
     if logged_in?
       @crudapp = Crudapp.find(params[:id])
       if current_user.id == @crudapp.user_id
         if !params[:crudapp] # This data is absent, so we always land here.
           flash[:message] = "edit functionality is down!"
         else
           @crudapp.update(params[:crudapp])
           params[:columns].each do |params_column|
             column = Column.find_or_create_by(id: params_column[:id])
             @crudapp.columns << @column.update(params_column)
           end
         end
         redirect "/crudapps/#{@crudapp.id}"
       else
         flash[:message] = "you must be the app's creator to edit"
         redirect "/crudapps"
       end
     else
       flash[:message] = "please log in to edit an app"
       redirect "/login"
     end
   end 
end

从 Slack 聊天中回顾我们的解决方案!

HTML:

这部分缺少一个索引
<li>
  <label for="columns[][key_name]">Third attribute name</label>
  <input class="fieldbox" type="text" name="columns[][key_name]" value="<%= @crudapp.columns[2].key_name %>">
</li>

输入标签的name属性应该是columns[2][key_name](少了2)。这导致查询参数字符串变得无法解析,因此 Rack 假定它是某种二进制或 non-standard 格式,并将其作为 request.body 传递给处理程序。

我编写了一个简单的 Rack 应用程序来将参数回显给请求者,并使用 curl 发送带有和不带 2 的请求负载:

$ curl --data-raw 'crudapp%5Buser_id%5D=1&crudapp%5Btitle%5D=Conundrum&crudapp%5Bdescription%5D=It%27s+uber+for+problem-solving%21%21%21+friend&crudapp%5Bmodel%5D=Problem&columns%5B0%5D%5Bid%5D=85&columns%5B0%5D%5Bkey_name%5D=summary&columns%5B0%5D%5Bdata_type%5D=String&columns%5B1%5D%5Bid%5D=86&columns%5B1%5D%5Bkey_name%5D=pros-and-cons&columns%5B1%5D%5Bdata_type%5D=String&columns%5B2%5D%5Bid%5D=87&columns%5B%5D%5Bkey_name%5D=solution&columns%5B2%5D%5Bdata_type%5D=String&crudapp%5Bgithub%5D=&crudapp%5Bweb%5D=' localhost:4567
{}
$ curl --data-raw 'crudapp%5Buser_id%5D=1&crudapp%5Btitle%5D=Conundrum&crudapp%5Bdescription%5D=It%27s+uber+for+problem-solving%21%21%21+friend&crudapp%5Bmodel%5D=Problem&columns%5B0%5D%5Bid%5D=85&columns%5B0%5D%5Bkey_name%5D=summary&columns%5B0%5D%5Bdata_type%5D=String&columns%5B1%5D%5Bid%5D=86&columns%5B1%5D%5Bkey_name%5D=pros-and-cons&columns%5B1%5D%5Bdata_type%5D=String&columns%5B2%5D%5Bid%5D=87&columns%5B2%5D%5Bkey_name%5D=solution&columns%5B2%5D%5Bdata_type%5D=String&crudapp%5Bgithub%5D=&crudapp%5Bweb%5D=' localhost:4567
{"crudapp"=>{"user_id"=>"1", "title"=>"Conundrum", "description"=>"It's uber for problem-solving!!! friend", "model"=>"Problem", "github"=>"", "web"=>""}, "columns"=>{"0"=>{"id"=>"85", "key_name"=>"summary", "data_type"=>"String"}, "1"=>{"id"=>"86", "key_name"=>"pros-and-cons", "data_type"=>"String"}, "2"=>{"id"=>"87", "key_name"=>"solution", "data_type"=>"String"}}}

希望对您有所帮助!