rails 7、form_with & params: 2个值是如何在params[:modelname]之外的?

rails 7, form_with & params: How did 2 values get outside of the params[:modelname]?

我有一个场景,在管理员限制创建 'new' 邀请时,管理员无法输入其中的 2 个值。它们旨在稍后在用户 'registrars' 上设置。创建工作正常。

有问题的 2 个值是:responded 和:attending (RA)。 Responded 默认设置为 false,而 attending 没有设置,因此默认为 nil。

然后我有一个邀请的编辑页面,管理员可以在其中更新任何信息。我们的想法是,如果邀请犯了无法撤消的错误,那么管理员可以设置或重置为默认值。

编辑页面适用于所有值,但 RA 不会保存到数据库。它不会引发任何异常,并且在 invites_controller 的逻辑中继续进行,就好像它已被保存一样。

注意:我可以将这些更新并保存到值 w/out rails c

中的任何问题

我添加了一个 binding.break 来查看参数,我认为这是问题所在: >params[:invite] 不包括 RA。但是如果我这样做 >params 我可以看到 ActionController::Parameters

的 'outside'
(rdbg) params
#<ActionController::Parameters 
  {"_method"=>"patch", 
    "authenticity_token"=>"keSUCTMDKkOYCVzCRKwaFuQN6EL9of-0SlyEIKEn6OHr_8766q23xh0LhcpU1GzPoM1xdr8XmGfuRQAmMw4gzg", 
    "invite"=>#<ActionController::Parameters 
      {
        "username"=>"Jim", 
        "titulation"=>"Mr Jim", 
        "guest_count"=>"1", 
        "escort_count"=>"1", 
        "password"=>""
      } 
    permitted: false>, 
    "attending"=>"true", 
    "responded"=>"true", 
    "commit"=>"Update Invite", 
    "controller"=>"invites", 
    "action"=>"update", 
    "id"=>"8"
  } permitted: false>



(rdbg) params[:invite]    # ruby
#<ActionController::Parameters 
{
  "username"=>"Jim", 
  "titulation"=>"Mr Jim", 
  "guest_count"=>"1", 
  "escort_count"=>"1", 
  "password"=>""
}
permitted: false>
(rdbg)

此处的架构部分:

  create_table "invites", force: :cascade do |t|
    t.string "username"
    t.string "titulation"
    t.integer "guest_count"
    t.integer "escort_count"
    t.boolean "responded"
    t.boolean "attending"
    t.string "password"
    t.string "password_digest"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

invite.rb(型号)

class Invite < ApplicationRecord
  validates :username, presence: true, uniqueness: { case_sensitive: false }, length: { minimum: 3, maximum: 25 }
  
  has_secure_password

  attribute :responded, default: false
end

invite_controller.rb:

注意:因为 'new' 页面不允许管理员设置 RA 值,所以我有 invite_params 用于创建,invite_extended_params 用于更新 ... 定义新 如果 logged_in_admin? @邀请= Invite.new 别的 flash[:notice] = "只有管理员可以访问该页面。" redirect_to root_path 结尾 结束

  def create
    @invite = Invite.new(invite_params) # does not include responded & attending
    if @invite.save
      flash[:notice] = "Created new invite for #{@invite.titulation}"
      redirect_to invite_path(@invite.id)
    end
  end

  def show
    @invite = Invite.find(params[:id])
  end

  def edit
    @invite = Invite.find(params[:id])
    if @invite.responded
      flash.now[:alert] = "Warning, this invite has responded. Make sure you know what you're doing."
    end
  end
  
  def update
    @invite = Invite.find(params[:id])
    if @invite.update(invite_extended_params) # includes responded & attending
      binding.break
      flash[:notice] = "Update was saved."
      redirect_to invite_path(@invite.id)
    else
      flash.now[:alert] = "Something went wrong"
      render 'edit'
    end
  end

  private

  def invite_params
    params.require(:invite).permit(:username, :titulation, :guest_count, :escort_count, :password)
  end

  def invite_extended_params
    params.require(:invite).permit(:username, :titulation, :guest_count, :escort_count, :password, :responded, :attending)
  end

end

编辑页面代码:

<%= form_with(model: @invite, class: "shadow p-3 mb-3 bg-info rounded", local: true) do |form| %>


  <div class="form-group row">
    <%= form.label :username, class: "col-2 col-form-label text-light" %>
    <div class="col-10">
      <%= form.text_field :username, class: "form-control shadow rounded", placeholder: "Enter Unique username" %>
    </div>
  </div>

  <div class="form-group row">
    <%= form.label :titulation, class: "col-2 col-form-label text-light" %>
    <div class="col-10">
      <%= form.text_field :titulation, class: "form-control shadow rounded", placeholder: "Enter Titulation" %>
    </div>
  </div>

  <div class="form-group row">
    <%= form.label :guest_count, class: "col-2 col-form-label text-light" %>
    <div class="col-10">
      <%= form.number_field :guest_count, class: "form-control shadow rounded", placeholder: "How many Guests for this invite?" %>
    </div>
  </div>

  <div class="form-group row">
    <%= form.label :escort_count, class: "col-2 col-form-label text-light" %>
    <div class="col-10">
      <%= form.number_field :escort_count, class: "form-control shadow rounded", placeholder: "How many +1's for this invite?" %>
    </div>
  </div>

  <div class="form-group row">
    <%= form.label :password, class: "col-2 col-form-label text-light" %>
    <div class="col-10">
    <%= form.text_field :password, class: "form-control shadow rounded", placeholder: "Preset password" %>
    </div>
  </div>

  <div class="form-group row">
    <div class="col-2 col-form-label text-light"> Attendance:
    <div class="col-10">
      <%= radio_button_tag(:attending, true) %>
      <%= label_tag(:attending, "Yes") %>
      <%= radio_button_tag(:attending, false) %>
      <%= label_tag(:attending, "No") %>
    </div>
  </div>

    <div class="form-group row">
    <div class="col-2 col-form-label text-light"> Responded:
    <div class="col-10">
      <%= radio_button_tag(:responded, true, @invite.responded) %>
      <%= label_tag(:responded, "Yes") %>
      <%= radio_button_tag(:responded, false, !@invite.responded) %>
      <%= label_tag(:responded, "No") %>
    </div>
  </div>

<%= form.submit 'Update Invite' %>

<% end %>

单选按钮作为没有表单上下文的标签添加到 html,因此它们不包含在表单的邀请参数中。

要修复更改它们以使用 form.radio_button。例如,更改 ...

 <%= radio_button_tag(:attending, true) %>

 <%= form.radio_button(:attending, true) %>