accepts_nested_attributes_for works in app but not with specs

14 views Asked by At

My shop model with accepts_nested_attributes_for

class Shop < ApplicationRecord
  has_many :open_slots, dependent: :delete_all
  validates :name, presence: true
  belongs_to :user
  accepts_nested_attributes_for :open_slots
end

schema file :

ActiveRecord::Schema[7.0].define(version: 20_230_923_091_441) do
  # These are extensions that must be enabled in order to support this database
  enable_extension 'plpgsql'

  create_table 'open_slots', force: :cascade do |t|
    t.integer 'day_number'
    t.time 'start_time'
    t.time 'end_time'
    t.bigint 'shop_id', null: false
    t.datetime 'created_at', null: false
    t.datetime 'updated_at', null: false
    t.index ['shop_id'], name: 'index_open_slots_on_shop_id'
  end

  create_table 'shops', force: :cascade do |t|
    t.string 'name'
    t.datetime 'created_at', null: false
    t.datetime 'updated_at', null: false
    t.bigint 'user_id', null: false
    t.index ['user_id'], name: 'index_shops_on_user_id'
  end

  create_table 'users', force: :cascade do |t|
    t.string 'email', default: '', null: false
    t.string 'encrypted_password', default: '', null: false
    t.string 'reset_password_token'
    t.datetime 'reset_password_sent_at'
    t.datetime 'remember_created_at'
    t.datetime 'created_at', null: false
    t.datetime 'updated_at', null: false
    t.string 'authentication_token', limit: 30
    t.index ['authentication_token'], name: 'index_users_on_authentication_token', unique: true
    t.index ['email'], name: 'index_users_on_email', unique: true
    t.index ['reset_password_token'], name: 'index_users_on_reset_password_token', unique: true
  end

  add_foreign_key 'open_slots', 'shops'
end

ShopsController where I permit open_slots_attributes

module Api
  module V1
    class ShopsController < BaseController
      acts_as_token_authentication_handler_for User, except: %i[index show]
     

      def create
        @shop = Shop.new(shop_params)
        @shop.user = current_user
        authorize @shop
        if @shop.save
          @presenter = ::ShowShopPresenter.new(@shop.id)

          render :show, status: :created
        else
          render_error
        end
      end

      private

      def render_error
        render json: { errors: @shop.errors.full_messages },
               status: :unprocessable_entity
      end


      def shop_params
        params.require(:shop).permit(:name, open_slots_attributes: [:day_number, :start_time, :end_time])
      end
    end
  end
end

With postman, is create Shop and open slots without problem. But when i run specs, it create only shop and not open slots

spec file :

describe 'POST/create' do
    let!(:user) { create(:user) }
    let(:valid_params) do
      {
        "shop":
           {
             name: name
           }
      }
    end
    let(:name) {}
    subject(:create_shop) { post '/api/v1/shops', params: valid_params }
    context 'when user is sign in' do
      before do
        sign_in user
      end
      context 'and name is missing' do
        it 'return error' do
          create_shop
          expect(response.status).to eq 422
          expect(JSON.parse(response.body)['errors']).to include("Name can't be blank")
        end
      end
      context 'and name is right' do
        let(:name) { 'test name' }
        it 'returns status code 201' do
          create_shop
          expect(response.status).to eq 201
        end
        it 'create new shop' do
          expect { create_shop }.to change { Shop.count }.by(1)
        end
        context 'and when valid open_slots_attribute are present' do
            before do
                valid_params["open_slots_attributes"] = 
                {
                    "start_time": "12:30",
                    "end_time": "18:30",
                    "day_number": 1
                },
                {
                    "start_time": "12:30",
                    "end_time": "18:30",
                    "day_number": 2
                },
                {
                    "start_time": "12:30",
                    "end_time": "18:30",
                    "day_number": 6
                }
            end
            it 'create open slots for shop' do
                expect { create_shop }.to change { OpenSlot.count }.by(3)
            end
        end
      end
    end
    context 'when user is not sign in' do
      let(:name) { 'test name' }
      it 'return authentication error' do
        create_shop
        expect(response.status).to eq 401
      end
    end
  end

the error : 1) Shops POST/create when user is sign in and name is right and when valid open_slots_attribute are present create open slots for shop Failure/Error: expect { create_shop }.to change { OpenSlot.count }.by(3) expected OpenSlot.countto have changed by 3, but was changed by 0 # ./spec/api/v1/shops_controller_spec.rb:137:inblock (6 levels) in <top (required)>'`

i tried to allow shop_params in the before but it didn't work

1

There are 1 answers

0
smathy On

Change valid_params["open_slots_attributes"] to valid_params["shop"]["open_slots_attributes"]