Rails强参数中相关模型创建时的不允许参数

问题描述 投票:0回答:2

我正在Rails中使用表单来创建一个Model的实例,并在创建时创建到另一个模型的联接表。在我的Accounts控制器中,在确认已创建Account的新实例之后,我基于从另一模型中以表格形式选择的复选框,创建了一个新的联接表。

这是我的代码:

型号:

class Account < ApplicationRecord
    has_many :account_authorizations
    has_many :authorizations, through: :account_authorizations
    accepts_nested_attributes_for :authorizations
end
class Authorization < ApplicationRecord

    has_many :account_authorizations
    has_many :accounts, through: :account_authorizations
end
class AccountAuthorization < ApplicationRecord
    belongs_to :account 
    belongs_to :authorization 
end

我的Accounts控制器:

class AccountsController < ApplicationController
  before_action :find_account, only: [:show, :update, :destroy]

  def index
    @accounts = Account.all

  end

  def show 
  end

  def new 
     @authorizations = Authorization.all
  end

  def create 
    byebug 
    @account = Account.new(account_params) 
    if @account.save 
      authorization_ids = params.permit![:authorization][:ids]
      authorization_ids.each do |auth_id| 
      AccountAuthorization.create(authorization_id: auth_id, account_id: params[:id]) if !auth_id.empty?
      end
      flash[:notice] = "Account created sucsessfully"
      redirect_to account_path(@account) 
    else    
      flash[:error] = @item.errors.full_messages.to_sentence
      render :new 
    end
  end

  def edit   
  end

  def update
     @account = Account.update(account_params) 
    if @account.valid?
      flash[:notice] = "Account created sucsessfully"
      redirect_to accounts_path(@account) 
    else    
      flash[:error] = @item.errors.full_messages.to_sentence
      render :edit 
    end
  end

  def destroy
    @account.delete
    redirect_to accounts_path
  end



private 

def find_account 
  @account = Account.find(params[:id])
end

def account_params
    params.permit(
      :account_name,
      :account_address_line1,
      :account_address_line2,
      :account_city,
      :account_state,
      :account_zipcode,
      :account_ppu,
      :account_notes,
      :contact_first_name,
      :contact_last_name,
      :contact_phone,
      :contact_email
    )
  end

end 

我尝试使用.permit!在参数上,但这不允许Authorization中的id传递到AccountAuthorization的新连接实例中。

不通过的属性是:

Unpermitted parameters: :authenticity_token, :authorization, :commit

我还尝试过将它们放在strong_params方法的允许哈希中。

ruby-on-rails nested-attributes strong-parameters
2个回答
0
投票

我通常要做的是这个(必要的(:account)非常重要):

def account_params
 params.require(:account).permit(
  :account_name,
  # Rest of the params you want to permit...
  authorization_ids: []
 )
end

这将允许您在控制器操作中进行定期保存。

def create 
 @account = Account.new(account_params) 
 if @account.save 
  flash[:notice] = "Account created successfully"
  redirect_to account_path(@account) 
 else    
  flash[:error] = @item.errors.full_messages.to_sentence
  render :new 
 end
end

并且在表单中,如果您将其显示为复选框。

<% Authorization.all.each do |authorization| %>
 <%= check_box_tag 'account[authorization_ids][]', authorization.id, @account.authorizations.include?(authorization), id: dom_id(authorization), type: "checkbox" %>
<% end %>

这将遍历所有授权记录并将其显示在屏幕上,如果选择它们,它们将存储在authorization_ids参数中,并且rails非常聪明,可以接受那些参数并在该表中创建联接关联。

顺便说一下,这是使用简单的形式,因此应该对代码进行一些修改以获取所需的输入


0
投票

您不需要手动创建联接表记录。

对于每个has_manyhas_many_and_belongs_to_many关联,Rails创建一个[ID]设置器,该设置器使用ID数组。 Rails将从输入中自动创建/删除联接表行。

这与_ids完美匹配。

accounts / _form.html.erb

collection helpers

accounts / new.html.erb

<%= form_for(account) do |f| %>
  # ... other fields
  <%= f.collection_select(:authorization_ids, Authorization.all, :id, :name, multiple: true) %>
<% end %>

accounts / edit.html.erb

<%= render partial: 'form', account: @account %>

app / controllers / accounts_controller.rb

<%= render partial: 'form', account: @account %>

由于此操作从params哈希中切出了键class AccountsController < ApplicationController before_action :find_account, only: [:show, :edit, :update, :destroy] # ... def create @account = Account.new(account_params) if @account.save flash[:notice] = "Account created sucsessfully" redirect_to @account else # render :new does not redirect so you need to use flash.now # to display the flash message in this request flash.now[:error] = @item.errors.full_messages.to_sentence render :new end end def edit end # This is how you update a resource. def update if @account.update(account_params) flash[:notice] = "Account updated successfully" redirect_to @account else flash.now[:error] = @item.errors.full_messages.to_sentence render :edit end end def destroy @account.delete redirect_to accounts_path end private def account_params params.require(:account).permit( # ... account_ids: [] ) end end ,所以不会出现不允许的参数错误。 :account是Rails CSRF保护令牌,authenticity_token是单击以提交表单的Submit按钮的值。这些不应列入白名单或发送给您的模型

您通过将关键字参数(commit)传递到account_ids: [],并将一个空数组作为值,将授权ID的阵列列入白名单。由于这是一个关键字参数,因此它必须位于位置参数列表之后。

您也不需要.permit,除非您要进行更高级的操作,然后只需选择现有记录。

© www.soinside.com 2019 - 2024. All rights reserved.