Rails多次选择放入额外的空白参数

时间:2015-10-24 00:42:52

标签: ruby-on-rails forms ruby-on-rails-4 put

我正在尝试使用collection_select创建HTML多重选择,以便能够更新具有另一个实体(Student)的集合的实体(SubscriptionList)作为嵌套属性。这是由HABTM ActiveRecord的关系支持的 我通过脚手架为学生创建了以下表格:

  
<div class="field">
  <%= f.label :first_name %><br>
  <%= f.text_field :first_name %>
</div>
<div class="field">
  <%= f.label :last_name %><br>
  <%= f.text_field :last_name %>
</div>
<div class="field">
  <%= f.label :file_number %><br>
  <%= f.text_field :file_number %>
</div>
<div class="field">
  <%= f.label :subscription_list %><br>
  <%= f.collection_select(:subscription_lists, SubscriptionList.all, :id, :name, {}, {:multiple => true}) %>
</div>

<div class="actions">
  <%= f.submit %>
</div>
  

并正确绘制多重选择。
但是,如果我填写表格并尝试将实体投入,我将其作为参数:

{“utf8”=&gt;“✓”,“_ method”=&gt;“patch”,“authenticity_token”=&gt;“vXYMRYI1UtX7WJRZM0OPIhHQSSEyNOPyUxkUvScdu45PTL7qVhvlJfQYNvaKG5rw + mvHAAAbf6ViTQ6tE4lV1Q ==”,“student”=&gt; {“first_name”=&gt; ;“Mariana”,“last_name”=&gt;“González”,“file_number”=&gt;“12345678”,“subscription_lists”=&gt; [“”,“3”]},“commit”=&gt;“更新学生“,”“控制器”=&gt;“学生”,“行动”=&gt;“更新”,“id”=&gt;“14”}

所以,我的学生

"first_name"=>" Mariana", "last_name"=>"González", "file_number"=>"12345678", "subscription_lists"=>["", "3"]}

我发现接收["", "3"]作为值非常奇怪。为什么我收到第一个""值?

我也在这里发布了我的控制器(为简洁而删除update以外的其他操作)

class StudentsController < ApplicationController
  before_action :set_student, only: [:show, :edit, :update, :destroy, :enrollments]

  # PATCH/PUT /students/1
  # PATCH/PUT /students/1.json
  def update
    puts "\n\n\n\n\n\n\n\n\nThese are the params: #{params.inspect}"
    puts "\n\n\n\n\nThis is student_params object: #{student_params.inspect}\n\n\nand its class #{student_params.class}"
    #puts "\n\n\n\n\n\n\n\n\nWill look for SL with ID: #{params[:subscription_lists_id]}"
    all_ids = student_params.subscription_lists.collect {|sl| sl.id }
    @student.subscription_lists = SubscriptionList.find(all_ids)
    #@student.subscription_lists = SubscriptionList.where(id: all_ids)
    respond_to do |format|
      if @student.update(student_params)
        format.html { redirect_to @student, notice: 'Student was successfully updated.' }
        format.json { render :show, status: :ok, location: @student }
      else
        format.html { render :edit }
        format.json { render json: @student.errors, status: :unprocessable_entity }
      end
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_student
      @student = Student.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def student_params
      #params[:student]
      #params.require(:foo).permit(:bar, {:baz => [:x, :y]})
      #params.require(:student).permit(:first_name, :last_name, :file_number, :subscription_lists)

      params.require(:student).permit!    # No strong parameters...
    end
end

事实上,我宁愿收到Student嵌套的SubscriptionList集合,而不仅仅是接收一组id,但我不确定这是否可行。

任何帮助都会非常感激。
最好的问候

2 个答案:

答案 0 :(得分:1)

关于您的问题已在collection select always adding blank value中得到解答。

当您未选择任何内容时,您将获得[""],或者您选择默认选项。为避免这种情况,您必须在集合选择之前添加hidden_field

<div class="field">
  <%= f.label :subscription_lists %><br>
  <%= f.hidden_field :subscription_lists %>
  <%= f.collection_select(:subscription_lists, SubscriptionList.all, :id, :name, {}, {:multiple => true}) %>
</div>

hidden_field没有被选中时, def update if student_params["subscription_lists"].any? student_params["subscription_lists"].reject!(&:empty?) end respond_to do |format| if @student.update(student_params) format.html { redirect_to @student, notice: 'Student was successfully updated.' } format.json { render :show, status: :ok, location: @student } else format.html { render :edit } format.json { render json: @student.errors, status: :unprocessable_entity } end end end 可以帮助您。你什么时候选择它?请试试这个。

SELECT DISTINCT model FROM cars

我希望这对你有所帮助。

答案 1 :(得分:0)

这就是我最终要做的事情,主要是关注this tutorial

对于控制器:

class StudentsController < ApplicationController
  before_action :set_student, only: [:show, :edit, :update, :destroy, :enrollments]

  # PATCH/PUT /students/1
  # PATCH/PUT /students/1.json
  def update
    puts "\n\n\n\n\n\n\n\n\nThese are the params: #{params.inspect}"
    puts "\n\n\n\n\nThis is student_params object: #{student_params.inspect}\n\n\nand its class #{student_params.class}"

    @subscription_lists = SubscriptionList.where(:id => params[:subscriptions])
    @student.subscription_lists.destroy_all   # disassociate the already added
    @student.subscription_lists << @subscription_lists

    respond_to do |format|
      if @student.update(student_params)
        format.html { redirect_to @student, notice: 'Student was successfully updated.' }
        format.json { render :show, status: :ok, location: @student }
      else
        format.html { render :edit }
        format.json { render json: @student.errors, status: :unprocessable_entity }
      end
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_student
      @student = Student.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def student_params
      params.require(:student).permit(:first_name, :last_name, :file_number, subscription_lists: [:id])
    end
end

形式:

  <div class="field">
    <%= f.label :subscription_list %><br>
    <%= select_tag "subscriptions", options_from_collection_for_select(SubscriptionList.all, 'id', 'name',@student.subscription_lists.map { |j| j.id }), :multiple => true %>
  </div>

希望它有用