Rails 合并(和手动分配)分配 nil
Rails merge (and manual assignment) assigning nil
我正在尝试使用 Rails 5.1 中的强参数在控制器中创建模型(某些内容与之前的 strong_params 有所不同)。但是,当我检查参数时,合并的参数不存在,并且我得到一个 ForbiddenAttributesError 跟踪到下面的 Model.new 行。模型中唯一的事情是验证所有属性的存在。
class ModelController < ApplicationController
before_action :application_controller_action
def create
@model = Model.new(strong_params)
if @model.valid?
result = @model.save
else
render html: 'MODEL NOT VALID'
end
render html: 'DONE'
end
private
def strong_params
# attr_1 and attr_2 are set in the application controller and are available here.
params.require(:model).permit(:name, :attribute_1, :attribute_2).merge(attribute_1: @attr_1, attribute_2: @attr_2)
# Inserting the following two lines causes a ForbiddenAttributesError
puts params.inspect # DOES NOT INCLUDE @attr_1 and/or @attr_2
return params
end
我可能做错了什么,因为我什至尝试将强参数放入具有属性的模型中(我可以在之前检查)但它仍然失败,因为 attr_1 和attr_2 模型失败。
def create
puts @user.inspect (not nil)
@model = Model.new(name: strong_params[:name], attribute_1: @attr_1, attribute_2: @attr_2)
更新:
好的,我在故障排除中遇到了一些奇怪的错误。合并似乎没有正常工作,但我确定它在某一时刻。
我首先检查的是@attr_1 和@attr_2,它们肯定已经设置好了。
出于故障排除目的,我已将应用程序 before_action 缩减为:
def application_before_action
@attr_1 = Model.first
@attr_2 = Model.last
使用上面的代码,检查参数 object 然后在 require().permit() 之后返回它,我得到一个 ForbiddenAttributesError(没有指示是什么)。如果删除这些行,我会从模型中得到一个缺少属性的错误,表明缺少@attr_1 和@attr_2。
更新 2
更改了问题的标题,因为我可能在排查过程中感到困惑。我认为问题只是合并正在分配 nil ... 但奇怪的是(我自己最初)建议的手动分配和这里的另一个答案。属性键在那里,但它们被分配为零。另外,注意到我的示例使用的是单个模型,而实际上有两个模型,即 Model1 和 Model2。我正在将值从 Model1 分配给 Model2。
下面是错误的更好演示:
def create
puts '0:'
puts @model1.inspect
puts '1:'
puts strong_params.inspect
@model2 = Model2.new(strong_params) do |m|
m.user_id = @attr_1
m.account_number = @attr_2
end
puts '3:'
puts @model2.inspect
if @model2.valid?
result = @model2.save
render html: 'SUCCESS' and return
else
render html: @model2.errors.full_messages and return
end
end
控制台输出:
0:
#<Model1 id: 29, attribute_1: 'test_value_1', attribute_2: 'test_value_2', created_at: "2018-08-15 03:55:08", updated_at: "2018-08-15 04:05:01">
1:
<ActionController::Parameters {"name"=>"test_name", "attribute_1"=>nil, "attribute_2"=>nil} permitted: true>
3:
#<Model2 id: nil, name: 'test_name', attribute_1: nil, attribute_2: nil, created_at: nil, updated_at: nil>
显然id和时间戳为nil是因为模型还没有保存
htmlmodel2.errors.full_messages分别是:["attribute_1 can't be blank"、"attribute_2 can't be blank"]
解决方案
之前来自纯 ruby 环境,我对模型的 ActiveRecord 默认访问器有误。删除访问器似乎已经解决了问题。
您可以将奇数一个一个地分配,而不是乱搞参数散列:
class ModelController < ApplicationController
before_action :application_controller_action
def create
@model = Model.new(strong_params) do |m|
m.attribute_1 = @attr_1
m.attribute_2 = @attr_2
end
if @model.valid?
result = @model.save
else
render html: 'MODEL NOT VALID'
end
# don't do this it will just give a double render error
render html: 'DONE'
end
private
private
def strong_params
params.require(:model).permit(:name, :attribute_1, :attribute_2)
end
end
一般来说,这是一种更易读的方法,例如将参数与会话中的值合并。
您的强参数方法不起作用的原因是它完全以各种可能的方式损坏。要点是您没有 returning 白名单和合并的参数哈希。你正在 return 整个 shebang。
您似乎还错误地认为 .require
、.permit
和 .merge
改变了原始散列 - 他们没有 - 他们 return 一个新的散列(实际上是一个 ActionContoller::Parameters 实例。
def strong_params
# attr_1 and attr_2 are set in the application controller and are available here.
permitted = params.require(:model).permit(:name, :attribute_1, :attribute_2)
.merge(attribute_1: @attr_1, attribute_2: @attr_2)
puts permitted.inspect
permitted # return is implicit
end
或者只是:
def strong_params
# attr_1 and attr_2 are set in the application controller and are available here.
params.require(:model).permit(:name, :attribute_1, :attribute_2)
.merge(attribute_1: @attr_1, attribute_2: @attr_2)
end
您可以在合并前转换为散列
params.require(:model).permit(:name).to_h.merge(attribute_1: @attr_1, attribute_2: @attr_2)
您必须非常确定您正在分配非用户输入,否则您将否定强参数的目的。
我正在尝试使用 Rails 5.1 中的强参数在控制器中创建模型(某些内容与之前的 strong_params 有所不同)。但是,当我检查参数时,合并的参数不存在,并且我得到一个 ForbiddenAttributesError 跟踪到下面的 Model.new 行。模型中唯一的事情是验证所有属性的存在。
class ModelController < ApplicationController
before_action :application_controller_action
def create
@model = Model.new(strong_params)
if @model.valid?
result = @model.save
else
render html: 'MODEL NOT VALID'
end
render html: 'DONE'
end
private
def strong_params
# attr_1 and attr_2 are set in the application controller and are available here.
params.require(:model).permit(:name, :attribute_1, :attribute_2).merge(attribute_1: @attr_1, attribute_2: @attr_2)
# Inserting the following two lines causes a ForbiddenAttributesError
puts params.inspect # DOES NOT INCLUDE @attr_1 and/or @attr_2
return params
end
我可能做错了什么,因为我什至尝试将强参数放入具有属性的模型中(我可以在之前检查)但它仍然失败,因为 attr_1 和attr_2 模型失败。
def create
puts @user.inspect (not nil)
@model = Model.new(name: strong_params[:name], attribute_1: @attr_1, attribute_2: @attr_2)
更新:
好的,我在故障排除中遇到了一些奇怪的错误。合并似乎没有正常工作,但我确定它在某一时刻。
我首先检查的是@attr_1 和@attr_2,它们肯定已经设置好了。
出于故障排除目的,我已将应用程序 before_action 缩减为:
def application_before_action
@attr_1 = Model.first
@attr_2 = Model.last
使用上面的代码,检查参数 object 然后在 require().permit() 之后返回它,我得到一个 ForbiddenAttributesError(没有指示是什么)。如果删除这些行,我会从模型中得到一个缺少属性的错误,表明缺少@attr_1 和@attr_2。
更新 2
更改了问题的标题,因为我可能在排查过程中感到困惑。我认为问题只是合并正在分配 nil ... 但奇怪的是(我自己最初)建议的手动分配和这里的另一个答案。属性键在那里,但它们被分配为零。另外,注意到我的示例使用的是单个模型,而实际上有两个模型,即 Model1 和 Model2。我正在将值从 Model1 分配给 Model2。
下面是错误的更好演示:
def create
puts '0:'
puts @model1.inspect
puts '1:'
puts strong_params.inspect
@model2 = Model2.new(strong_params) do |m|
m.user_id = @attr_1
m.account_number = @attr_2
end
puts '3:'
puts @model2.inspect
if @model2.valid?
result = @model2.save
render html: 'SUCCESS' and return
else
render html: @model2.errors.full_messages and return
end
end
控制台输出:
0:
#<Model1 id: 29, attribute_1: 'test_value_1', attribute_2: 'test_value_2', created_at: "2018-08-15 03:55:08", updated_at: "2018-08-15 04:05:01">
1:
<ActionController::Parameters {"name"=>"test_name", "attribute_1"=>nil, "attribute_2"=>nil} permitted: true>
3:
#<Model2 id: nil, name: 'test_name', attribute_1: nil, attribute_2: nil, created_at: nil, updated_at: nil>
显然id和时间戳为nil是因为模型还没有保存
htmlmodel2.errors.full_messages分别是:["attribute_1 can't be blank"、"attribute_2 can't be blank"]
解决方案
之前来自纯 ruby 环境,我对模型的 ActiveRecord 默认访问器有误。删除访问器似乎已经解决了问题。
您可以将奇数一个一个地分配,而不是乱搞参数散列:
class ModelController < ApplicationController
before_action :application_controller_action
def create
@model = Model.new(strong_params) do |m|
m.attribute_1 = @attr_1
m.attribute_2 = @attr_2
end
if @model.valid?
result = @model.save
else
render html: 'MODEL NOT VALID'
end
# don't do this it will just give a double render error
render html: 'DONE'
end
private
private
def strong_params
params.require(:model).permit(:name, :attribute_1, :attribute_2)
end
end
一般来说,这是一种更易读的方法,例如将参数与会话中的值合并。
您的强参数方法不起作用的原因是它完全以各种可能的方式损坏。要点是您没有 returning 白名单和合并的参数哈希。你正在 return 整个 shebang。
您似乎还错误地认为 .require
、.permit
和 .merge
改变了原始散列 - 他们没有 - 他们 return 一个新的散列(实际上是一个 ActionContoller::Parameters 实例。
def strong_params
# attr_1 and attr_2 are set in the application controller and are available here.
permitted = params.require(:model).permit(:name, :attribute_1, :attribute_2)
.merge(attribute_1: @attr_1, attribute_2: @attr_2)
puts permitted.inspect
permitted # return is implicit
end
或者只是:
def strong_params
# attr_1 and attr_2 are set in the application controller and are available here.
params.require(:model).permit(:name, :attribute_1, :attribute_2)
.merge(attribute_1: @attr_1, attribute_2: @attr_2)
end
您可以在合并前转换为散列
params.require(:model).permit(:name).to_h.merge(attribute_1: @attr_1, attribute_2: @attr_2)
您必须非常确定您正在分配非用户输入,否则您将否定强参数的目的。