0

I am trying to create multiple "Absence"s by posting:

Parameters: {"absences"=>[{"user_id"=>1, "lesson_id"=>25,
"excused"=>true}, {"user_id"=>2, "lesson_id"=>25, "excused"=>true}]}

However, I am not able to whitelist this format in the controller. I attempted to follow the solution from "How to use strong parameters with an objects array in Rails".

In my case:

def absence_params
  params.permit(absences: [:user_id, :lesson_id, :excused])
end

I get

ActiveModel::UnknownAttributeError (unknown attribute 'absences' for Absence.):

Then I tried:

Parameters: {"absence"=>[{"user_id"=>1, "lesson_id"=>25,
"excused"=>true}, {"user_id"=>2, "lesson_id"=>25, "excused"=>true}]}

def absence_params
  params.permit(:absence, array: [:user_id, :lesson_id, :excused])
end

and got:

Unpermitted parameters: :absence, :format

---- Resolved ----

  1. The gem 'cancancan' was not allowing me to create using an array.
  2. If you have an issue permitting an array in the strong params, try

params.require(:absences).map do |p|
  p.permit(:user_id, :lesson_id, :excused)
end

1 Answers1

2

Your parameters permit code is correct:

require "bundler/inline"

gemfile(ENV['INSTALL'] == '1') do
  source "https://rubygems.org"
  gem "actionpack", "6.0.2.2"
  gem "activesupport", "6.0.2.2"
end

require "active_support/core_ext"
require "action_controller/metal/strong_parameters"
require "minitest/autorun"


class BugTest < Minitest::Test
  def test_stuff

    params = ActionController::Parameters.new({
      "absences"=>[
        {"user_id"=>1, "unpermitted_param" => 123, "lesson_id"=>25, "excused"=>true},
        {"user_id"=>2, "lesson_id"=>25, "excused"=>true}
      ]
    })

    assert_equal(
      {
        "absences"=>[
          {"user_id"=>1, "lesson_id"=>25, "excused"=>true},
          {"user_id"=>2, "lesson_id"=>25, "excused"=>true}
        ]
      },
      params.permit(absences: [:user_id, :lesson_id, :excused]).to_h
    )
  end
end

The error comes from some other place, most likely you're trying to do something like Absence.create(absence_params), which will only work for single records.

To create an array at once you should adjust other relevant code accordingly, for example:

  1. Manually handle the array like:

    @absenses = params["absences"].map do |raw_absense_params|
      Absense.create!(raw_absense_params.permit(:user_id, :lesson_id, :excused))
    end
    
  2. Employ accepts_nested_attrubutes_for :absenses for the parent model if you have any (probably Lesson). The code for this will be cleaner, as Rails will handle most things for you, like cases when not all instances can be saved because of validation, etc.

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
Vasfed
  • 18,013
  • 10
  • 47
  • 53
  • Thank you for your answer! Unfortunately, I am getting "Unpermitted parameter: :format." and "ActiveModel::UnknownAttributeError (unknown attribute 'absences' for Absence.)" even when I do not attempt to use `absence_params` :/ – Kristiyan Tsvetanov Mar 23 '20 at 23:24
  • Turns out it was the gem 'cancancan' that did not accept arrays... Thanks! – Kristiyan Tsvetanov Mar 24 '20 at 21:36