Rails 4:collection_check_box错误

时间:2015-06-01 21:38:58

标签: ruby-on-rails ruby forms nested-forms actionview

我正在构建一个启动新广告系列的表单。通过此Campaign,您可以选择Zip文件和/或某些PDF文件。 Zip和PDF文件都存储在Uploads表中。

到目前为止,似乎我可以选择一个Zip文件,但是,一旦我为PDF添加collection_check_box,创建一个广告系列,我就会收到以下错误...

expected Array (got String) for param `upload_ids'

我的表格看起来像这样..

<%= form_for @campaign, url: {action: "create"} do |f| %>
   <%= f.label :name, class: "right-label" %>
   <%= f.text_field :name %>

   <%= f.label :comment, "Comments" %>
   <%= f.text_area :comment %>


   <%= f.label :zip_file, class: "right-label" %>

   <%= f.collection_select :upload_ids, Upload.where(file_type: ".zip"), :id, :file_name, include_blank: "Include a Zip File" do |b| %>
        <%= b.option + File.basename(b.text, '.*') %>
    <% end %>

   <%= f.label :pdf_files %>

<ul><%= f.collection_check_boxes :upload_ids, Upload.where(file_type: ".pdf"), :id, :file_name do |b| %>
    <li><%= b.label do %>
        <%= b.check_box + File.basename(b.text,'.*') %>
    </li>
        <% end %>
    <% end %>
</ul>

以下是服务器上显示的错误。

[2015-06-01 14:50:57] ERROR Rack::Utils::ParameterTypeError: expected Array (got String) for param `upload_ids'
    /Users/Josh/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/rack-1.6.1/lib/rack/utils.rb:142:in `normalize_params'
    /Users/Josh/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/rack-1.6.1/lib/rack/utils.rb:156:in `normalize_params'
    /Users/Josh/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/rack-1.6.1/lib/rack/utils.rb:117:in `block in parse_nested_query'
    /Users/Josh/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/rack-1.6.1/lib/rack/utils.rb:114:in `each'
    /Users/Josh/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/rack-1.6.1/lib/rack/utils.rb:114:in `parse_nested_query'
    /Users/Josh/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/rack-1.6.1/lib/rack/request.rb:369:in `parse_query'
    /Users/Josh/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/rack-1.6.1/lib/rack/request.rb:215:in `POST'
    /Users/Josh/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/rack-1.6.1/lib/rack/methodoverride.rb:39:in `method_override_param'
    /Users/Josh/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/rack-1.6.1/lib/rack/methodoverride.rb:27:in `method_override'
    /Users/Josh/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/rack-1.6.1/lib/rack/methodoverride.rb:15:in `call'
    /Users/Josh/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/rack-1.6.1/lib/rack/runtime.rb:18:in `call'
    /Users/Josh/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/activesupport-4.2.1/lib/active_support/cache/strategy/local_cache_middleware.rb:28:in `call'
    /Users/Josh/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/rack-1.6.1/lib/rack/lock.rb:17:in `call'
    /Users/Josh/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/actionpack-4.2.1/lib/action_dispatch/middleware/static.rb:113:in `call'
    /Users/Josh/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/rack-1.6.1/lib/rack/sendfile.rb:113:in `call'
    /Users/Josh/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/railties-4.2.1/lib/rails/engine.rb:518:in `call'
    /Users/Josh/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/railties-4.2.1/lib/rails/application.rb:164:in `call'
    /Users/Josh/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/rack-1.6.1/lib/rack/lock.rb:17:in `call'
    /Users/Josh/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/rack-1.6.1/lib/rack/content_length.rb:15:in `call'
    /Users/Josh/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/rack-1.6.1/lib/rack/handler/webrick.rb:89:in `service'
    /Users/Josh/.rbenv/versions/2.2.2/lib/ruby/2.2.0/webrick/httpserver.rb:138:in `service'
    /Users/Josh/.rbenv/versions/2.2.2/lib/ruby/2.2.0/webrick/httpserver.rb:94:in `run'
    /Users/Josh/.rbenv/versions/2.2.2/lib/ruby/2.2.0/webrick/server.rb:294:in `block in start_thread'

修改

如果我删除其中一个集合块(zip或pdf),我的广告系列创建就会成功。

上面的Zip文件和PDF文件选择方法似乎与我的“upload_ids”存在冲突。即使我的模型关系声明了广告系列has_many: uploads, through: uploadablehas_many: uploadable,它也试图同时接受Zip和PDF / - upload_id的一个实例。

我仍然不确定如何解决这个问题。任何帮助表示赞赏。

控制器/ campaigns_controller.rb

class CampaignsController < ApplicationController
      def index
        @campaigns = Campaign.all.order("created_at DESC")
      end

      def new
        @campaign = Campaign.new
      end

      def create
        @campaign = Campaign.new(campaign_params)

        if @campaign.save
            flash[:success] = "Campaign Successfully Launched!"
            redirect_to @campaign
        else
            flash[:error] = "There was a problem launching your Campaign."
            redirect_to new_campaign_path
        end
      end

      def show
        @campaign = Campaign.find(params[:id])
      end

  private

      def campaign_params
        params.require(:campaign).permit(:name, :comment)
      end
end

日志/ development.log

Started GET "/campaigns/new" for ::1 at 2015-06-01 18:54:19 -0700
Processing by CampaignsController#new as HTML
  [1m[35mUpload Load (0.2ms)[0m  SELECT "uploads".* FROM "uploads"
  [1m[36mUpload Load (0.3ms)[0m  [1mSELECT "uploads".* FROM "uploads" WHERE "uploads"."file_type" = $1[0m  [["file_type", ".zip"]]
  [1m[35mUpload Load (0.1ms)[0m  SELECT "uploads".* FROM "uploads" WHERE "uploads"."file_type" = $1  [["file_type", ".pdf"]]
  Rendered campaigns/_form.html.erb (6.6ms)
  Rendered campaigns/new.html.erb within layouts/application (7.5ms)
  Rendered layouts/_header.html.erb (0.2ms)
  Rendered layouts/_footer.html.erb (0.0ms)
Completed 200 OK in 82ms (Views: 80.4ms | ActiveRecord: 0.5ms)

更新#1

另一位开发者朋友指出,我不能对collection_selects使用“upload_ids”。这在我上面的实验中也很明显。那么如何允许用户将对象与来自单独模型/表的其他2个对象相关联?

我将一个collection_select对象参数更改为uploadable_ids,但这是我放置的随机名称。我不知道该放哪个参数。现在我收到了flash [:error] "There was a problem launching your Campaign."

更新#2

我已经尝试了许多建议,包括这篇文章的建议,但仍然在努力让这个工作。 select_tag投掷和undefined method暂时如此,我只是使用select。我尝试添加upload_ids[]但是抛出了一个错误,需要更多的参数。

我也很困惑我是否需要向控制器添加任何内容。当我决定查询哪个Campaign与哪些文件相关联时,我的Active Record关联是否足够?

以下是表单当前状态下的zip和pdf部分..

<%= f.label :data_file, class: "right-label" %>

<%= f.select :upload_ids, 
    options_from_collection_for_select(
    Upload.where(file_type: ".zip"), :id, :file_name), 
    {include_blank: "Include a Zip File"}, {mulitple: true} %>

<%= f.label :additional_files %>

<%= f.collection_check_boxes(:upload_ids, 
    Upload.where(file_type: ".pdf"), :id, :file_name, 
    { mulitple: true }) do |b| %>
            <%= b.label do %>
              <%= b.check_box + File.basename(b.text,'.*') %>
            <% end %>
<% end %>

如果它有任何附加帮助,这里是模型关系:

class Campaign < ActiveRecord::Base
  has_many  has_many :uploadable
  has_many :uploads, through: :uploadable
end

class Uploadable < ActiveRecord::Base
  belongs_to :campaign
  belongs_to :upload
end

class Upload < ActiveRecord::Base
  has_many :uploadable
  has_many :campaigns, through: :uploadable
end

1 个答案:

答案 0 :(得分:1)

我看到的主要问题是您的复选框正在提交数组参数(您可以选择多个复选框),但您的collection_select正在尝试提交单数值。两者的混合是导致Rack :: Utils :: ParameterTypeError

的原因

您的uploads关联是一个has_many,因此使用数组参数是正确的做法。您可以做的最简单的事情是通过添加multiple: true选项使选择多选。请注意,这必须与您的include_blank选项分开使用。

要保持单独选择,我认为您需要下拉到调用select_tag并指定upload_ids[]作为输入名称。您仍然可以使用options_from_collection_for_select生成选项标记。