Question

I have a Course model which belongs_to a Grade. I'm trying to create a Course in my seeds.rb file by doing:

Course.create(
  ActionController::Parameters.new(
    grade: Grade.all.sample
  ).permit(:grade_id)
)

This creates a new Course object but grade_id is nil. What am I doing wrong?

Was it helpful?

Solution

Strong parameters does two things: one is the white listing of parameters side of things (so the keys in the hash must match the arguments passed to permit, even if setting grade ends up setting grade_id.

The second thing it does is restrict the types of parameters that are passed - a lot of the recent security problems have occurred when an attacker is able to set a parameter to a carefully constructed hash/array/etc when you were only expecting a string or a number.

As a result anything that isn't a scalar value is stripped out, with arrays/hashes only allowed if you've indicated that you're expecting an array/hash. In particular your activerecord objects will be stripped out.

You could switch to setting grade_id instead it just not use strong parameters here - there's no untrusted user input in this case.

OTHER TIPS

@Frederick Cheung beat me to the cause. I will supplement his answer by providing some output from the Rails console to support this.

It does not allow record instances

[11] pry(main)> u = User.first
  User Load (0.5ms)  SELECT "user_users".* FROM "users" ORDER BY "users"."id" ASC LIMIT 1
=> #<User id: 1, ...>
[12] pry(main)> x = ActionController::Parameters.new(user: u)
=> {"user"=>
  #<User id: 1, ...>}
[13] pry(main)> x.permit(:user)
Unpermitted parameters: user
=> {}

But if we switch to the scalar integer value for the record id it works fine.

[14] pry(main)> x = ActionController::Parameters.new(user: u.id)
=> {"user"=>1}
[15] pry(main)> x.permit(:user)
=> {"user"=>1}

If you are creating a Course instance to seed the database, then you don't need to create it from as ActionController::Parameters

You can simply pass the attributes to Course.create like this:

Course.create(grade: Grade.all.sample)

Since you will not be using ActionController::Parameters at all, then you don't need to worry about strong parameters or permit at all (in your seeds).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top