Search code examples
ruby-on-railsdatabase-migration

save to database does not work after migration in rails


I wanted to create a todo application with rails and I decided to add a log in function. I added the users table and two migrations: one to add the column "user_id" to the todo table and one to make "user_id" not null. This means that in order to create a todo, it has to have a user ID. Create column:

    class AddColumnOnCreateTodos < ActiveRecord::Migration[6.1]
  def change
    add_column(:todos, :user_id, :integer)
  end
end

change to not null:

   class ChangeColumnOnCreateTodos < ActiveRecord::Migration[6.1]
      def change
        change_column_null(:todos, :user_id, false)
      end
    end

Now, everything works just fine. I can access the current logged in user and the column got added with the not null constraint. However, somehow the create function in my todo_controller does not work. Every time I want to create a new todo, the SQL statement is the following:

INSERT INTO "todos" ("title", "description", "created_at", "updated_at") VALUES (?, ?, ?, ?) 

The create method of my todo_controller looks like this:

 def create
    @todo = Todo.new(todo_params)
    if @todo.save
      redirect_to to_dos_path
    else
      render :new
    end
  end

And the todo_params like this:

private
  def todo_params
    user = Current.user.id
    puts user
    params.require(:todo).permit(:title, :description, user)
  end

It somehow does not know that the user_id column was added. I'm new to rails, so what am I missing? I did reset the entire database, did a rollback, migration, rake db:reset db:migrate, etc. I don't know why it doesn't work.


Solution

  • You have added a not null constraint, but you are creating the Todo without the user foreign key, that's why its not saving.

    You need to create the Todo through association, but you need to have this association first in your user model:

    has_many :todos
    

    This will allow you to create a todo through association

    user = Current.user.id
    todo = user.todos.create(todo_params)
    

    Another note about the permit method in todo_params, permit is used to allow the parameters coming with your request to be used in creating or updating records, only the attributes inside the permit function will be used to create your todo. So adding user in permit won't really change anything since this value doesn't initially exist within the request parameters.

    Another solution is to merge the permitted params with the user_id, so it can be used in creating the todo

    def todo_params
      user = Current.user.id
      params.require(:todo).permit(:title, :description).merge(user_id: user.id)
    end