Rails合并(和手动分配)分配nil

时间:2018-08-14 19:17:32

标签: ruby-on-rails strong-parameters ruby-on-rails-5.1 rails-models

我正在尝试在Rails 5.1中使用强参数在控制器中创建模型(对于strong_params,某些内容与以前有所不同)。但是,当我检查参数时,合并的参数不存在,并且我得到了一个ForbiddenAttributesError追溯到下面的Model.new行。该模型中唯一的一件事就是验证所有属性的存在。

when(value){
    0 -> return "app1"
    1 -> return "app2"
}

我可能做错了,因为我什至尝试将具有参数的强参数放入具有属性的模型中(我可以之前检查过),但仍然失败,因为在模型中对attr_1和attr_2的验证失败。

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,它们肯定已经设置好了。

出于故障排除的目的,我将应用程序before_action简化为:

def create
  puts @user.inspect  (not nil)
  @model = Model.new(name: strong_params[:name], attribute_1: @attr_1, attribute_2: @attr_2)

使用上面的代码,检查params对象,然后在require()。permit()之后返回它,我得到了ForbiddenAttributesError(没有任何指示)。如果删除这些行,则会从模型中收到缺少属性的错误,指示缺少@ attr_1和@ attr_2。

更新2

更改了问题的标题,因为在故障排除期间我可能会感到困惑。我认为问题只是合并正在分配nil ...,但是奇怪的是,(我本人本来)建议的手动分配以及此处的另一个答案也是如此。属性键在那里,但是它们被分配为零。另外,请注意,我的示例使用的是单个模型,而实际上有两个模型,即Model1和Model2。我正在将Model1的值分配给Model2。

以下是该错误的更好示例:

def application_before_action
  @attr_1 = Model.first
  @attr_2 = Model.last

控制台中的输出:

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

很明显,id和时间戳为nil是因为尚未保存模型。

html model2.errors.full_messages是:[“ attribute_1不能为空”,“ attribute_2不能为空”]

解决方案

以前来自纯红宝石环境,我被误认为是模型的ActiveRecord默认访问器。删除访问器似乎已经解决了问题。

2 个答案:

答案 0 :(得分:2)

您可以只为奇数值一个一个地分配奇数值,而不必用params哈希值搞乱:

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

通常,这是一种将参数与会话中的值合并的可读性更高的方法。

您的强参数方法不起作用的原因是它以各种可能的方式被打破了。要点是,您不会返回列入白名单和合并的参数哈希。您要归还整个shebang。

您似乎还对.require.permit.merge改变了原始哈希表示不满意,但并没有改变,而是返回了一个新的哈希(实际上是一个ActionContoller具体参数实例)。

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

答案 1 :(得分:0)

您可以在合并之前转换为哈希

params.require(:model).permit(:name).to_h.merge(attribute_1: @attr_1, attribute_2: @attr_2)

您必须非常确定要分配非用户输入,尽管否则您将否定强参数的用途。