Search code examples
ruby-on-railsdevise

To Do list with nested attributes


UPDATE: so after almost 24hs trying, I finally found the problem. It was the model (reject_of: :new_record?) which I intended to reject blanks, but now I see rejects new records. So every time I was creating a new instance the List's model was rejecting it.

I'm trying to make a ToDo app which has Users, Todo Lists and Todo items. I'm using devise to require log in, email confirmation etc. Lists have nested attributes from items, since both will be created at the same time in the same form. Further on I will make the forum dynamic. The thing is when I try to create the list gives me this error: undefined method `user_id=' for nil:NilClass. What am I doing wrong?

My controller and models are the following:

class ListsController < ApplicationController

  before_action :set_list, except: [:index, :new, :create]
  before_action :authenticate_user!, except: [:index, :show]

  def index
    @lists = List.all
    @users = User.all
  end

  def show

  end

  def new
    @list = List.new
    @list.todos.new
  end

  def edit
  end

  def create
    @list = current_user.lists.new(list_params)
    @list.todos.first.user_id = current_user.id

    if @list.save
        redirect_to @list, notice: "List was successfuly created!"
    else
        render action: :new
    end
  end

  def update

    if @list.update(list_params)
     redirect_to @list, notice: "List was successfuly updated!"
    else
     render action: :edit
    end
  end

  def destroy
    @list.destroy
    redirect_to lists_url, notice: "List was successfuly destroyed!"
  end

  def is_closed?
    @list.close
  end

  private

  def set_list
    @list = List.find(params[:id])
  end

  def list_params
    params.require(:list).permit(:title, :public, :close, todos_attributes: [:list_id, :user_id, :task, :close]  )
  end

end

class User < ApplicationRecord


  has_many :lists, dependent: :destroy
  has_many :todos, dependent: :destroy


  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable, :lockable, :timeoutable, :confirmable
end

class Todo < ApplicationRecord
    belongs_to :list, inverse_of: :todos
    belongs_to :user

    validates :task, presence: :true
end

class List < ApplicationRecord
    belongs_to :user
    has_many :todos, inverse_of: :list, dependent: :destroy
    accepts_nested_attributes_for :todos, reject_if: :new_record?, allow_destroy: true

    validates :title, presence: true
    validates_associated :todos
end

And my schema:

ActiveRecord::Schema.define(version: 20170403051028) do

  create_table "lists", force: :cascade do |t|
    t.string   "title"
    t.boolean  "public"
    t.boolean  "close"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.integer  "user_id"
    t.index ["user_id"], name: "index_lists_on_user_id"
  end

  create_table "todos", force: :cascade do |t|
    t.boolean  "close"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.integer  "list_id"
    t.text     "task"
    t.integer  "user_id"
    t.index ["list_id"], name: "index_todos_on_list_id"
    t.index ["user_id"], name: "index_todos_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.integer  "sign_in_count",          default: 0,  null: false
    t.datetime "current_sign_in_at"
    t.datetime "last_sign_in_at"
    t.string   "current_sign_in_ip"
    t.string   "last_sign_in_ip"
    t.string   "confirmation_token"
    t.datetime "confirmed_at"
    t.datetime "confirmation_sent_at"
    t.string   "unconfirmed_email"
    t.integer  "failed_attempts",        default: 0,  null: false
    t.string   "unlock_token"
    t.datetime "locked_at"
    t.string   "name"
    t.datetime "created_at",                          null: false
    t.datetime "updated_at",                          null: false
    t.index ["confirmation_token"], name: "index_users_on_confirmation_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
    t.index ["unlock_token"], name: "index_users_on_unlock_token", unique: true
  end

end

Solution

  • UPDATE: so after almost 24hs trying, I finally found the problem. That was at the model (reject_of: :new_record?) wich I intended to reject blanks, but now I see it rejects new records. So everytime I was creating a new instance the List's model was rejecting it.