我正在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方法的允许哈希中。
我通常要做的是这个(必要的(: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非常聪明,可以接受那些参数并在该表中创建联接关联。
顺便说一下,这是使用简单的形式,因此应该对代码进行一些修改以获取所需的输入
您不需要手动创建联接表记录。
对于每个has_many
和has_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
,除非您要进行更高级的操作,然后只需选择现有记录。