Error Rails Minitest in simple post request

I am facing a very strange problem and I could not find the answer here. I am trying to do simple testing with Minitest in my Rails API application.

I have two simple models one is Movie:

class CreateMovies < ActiveRecord::Migration[7.0]
  def change
    create_table :movies do |t|
      t.string :title
      t.text :synopsis
      t.datetime :launch_date
      t.string :age_classification
      t.string :length
      t.string :genre
      t.string :director
      t.string :poster
      t.decimal :rating_avg

      t.timestamps
    end
  end
end

The other one is Sessions

class CreateSessions < ActiveRecord::Migration[7.0]
  def change
    create_table :sessions do |t|
      t.references :movie, null: false, foreign_key: true
      t.text :times
      t.text :dates

      t.timestamps
    end
  end
end

Testing "should create session" auto-generated testing function:

class SessionsControllerTest < ActionDispatch::IntegrationTest

  setup do
    @movie = movies(:one)
    @session = sessions(:one)
  end

  test "should create session" do
    assert_difference("Session.count") do
      post sessions_url, params: { session: { dates: @session.dates, movie_id: @session.movie_id, times: '21:00' } }, as: :json
    end

    assert_response 201
  end
end

I face the following error:

Minitest::UnexpectedError: ActiveRecord::RecordInvalid: Validation failed: Movie must exist

movies.yml

one:
  title: Avatar
  synopsis: A paraplegic Marine dispatched to the moon Pandora on a unique mission becomes torn between following his orders and protecting the world he feels is his home
  launch_date: 18/12/2009
  age_classification: +13
  length: 162
  genre: Action
  director: James Cameron
  poster: https://m.media-amazon.com/images/M/MV5BNjA3NGExZDktNDlhZC00NjYyLTgwNmUtZWUzMDYwMTZjZWUyXkEyXkFqcGdeQXVyMTU1MDM3NDk0._V1_SX300.jpg
  rating_avg: 8.0

sessions.yml

one:
  movie: one
  times: 16:00
  dates: 17/07/2022

I have ensured Movie exists when post line is executing but no clue why is this happening. Any ideas?

PD: Running on Ruby 3.1.2 and Ruby On Rails 7.0.4

I tried to forcefully create a new Movie just before the post statement it did not work. I also tried to output if the movie exists inside controller when it creates the session but it does not save the session because ActiveRecord::RecordInvalid: Validation failed: Movie must exist.

>Solution :

Your parameters are nested under session in the request, but your strong parameter method doesn’t reflect this nesting.

Change your session_params method to:

def session_params
  params.require(:session).permit(:movie_id, :times, :dates)
end

When you parameters look like this

params = { session: { dates: @session.dates, movie_id: @session.movie_id, times: '21:00' } }

and you only call params.permit(:movie_id, :times, :dates) then Rails would try to permit those key/value pairs on the other hash. Because those keys do not exist on the outer hash but only on the inner hash params.permit(:movie_id, :times, :dates) will return an empty {} hash.

But when you call params.require(:session).permit(:movie_id, :times, :dates), then the require(:session) will require that there is a session key on the outer hash and will return its inner hash. Then the chained permit(:movie_id, :times, :dates) call will permit those key/value pairs from the inner hash and will return:

{ dates: @session.dates, movie_id: @session.movie_id, times: '21:00' }

I suggest reading about strong parameters in the official Rails Guides.

Leave a Reply