Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Ruby Build a Todo List Application with Rails 4 Build a Todo List Application with Rails 4 Editing Todo Lists

edit_spec.rb Failure/Error: click_button "Update Todo list" (unable to open database file)

I had no problem running the create_spec.rb tests. However, with the edit_spec.rb test as given in the video, I get an unexpected failure with the following message:

   Failures:  

   1) Editing todo lists updates a todo list successfully with correct information
       Failure/Error: click_button "Update Todo list"
      ActiveRecord::StatementInvalid: SQLite3::CantOpenException: unable to open database file: UPDATE "todo_lists" SET "title" = ?, "description" = ?, "updated_at" = ? WHERE "todo_lists"."id" = ?

     # ./app/controllers/todo_lists_controller.rb:44:in `block in update'
     # ./app/controllers/todo_lists_controller.rb:43:in `update'
     # ./spec/features/todo_lists/edit_spec.rb:14:in `block (2 levels) in <top (required)>'

I have verified the following:

  1. test.sqlite3 exists in the /db directory.
  2. That I have given full control permissions to all users.
  3. database.yml in /config specifies test.sqlite3 for test:

Any suggestions would be greatly appreciated. (See edit_spec.rb in comment below.)

Here is my edit_spec.rb ... I believe it is exactly as given in the video.

    require 'spec_helper'

    describe "Editing todo lists" do
       it "updates a todo list successfully with correct information" do
         todo_list = TodoList.create(title: "Groceries", description: "Grocery List.")

         visit "/todo_lists"
         within "#todo_list_#{todo_list.id}" do
           click_link "Edit"
         end

         fill_in "Title", with: "New title"
         fill_in "Description", with: "New description"
         click_button "Update Todo list"

         todo_list.reload

         expect(page).to have_content("Todo list was successfully updated")
         expect(todo_list.title).to eq("New title")
         expect(todo_list.description).to eq("New description")
      end
    end
Clayton Perszyk
Clayton Perszyk
Treehouse Moderator 48,850 Points

The problem may be in your todo_lists_controller.rb file. It might help if you post that file in addition to the edit_spec.rb file.

Thanks for taking a look Clayton. My TodoListsController.rb was created through the scaffold command used in an earlier video in this program. As a Rails newbie I have been working through this program in a mechanical way.

Do you know what the "# PATCH/PUT /todo_lists/1" (and "/1.json") comments in this code means? I know from my error message that RSpec is giving me my failure originating from the statements that follow these two comments.

I cannot determine why this edit_spec.rb code can successfully create a todo record in the test.sqlite3 table but only give a failure when trying to update the record. i.e. todo_list = TodoList.create(title: "Groceries", description: "Grocery List.") does not fail; only on the update (button) does it fail.

    class TodoListsController < ApplicationController
      before_action :set_todo_list, only: [:show, :edit, :update, :destroy]

      # GET /todo_lists
      # GET /todo_lists.json
      def index
        @todo_lists = TodoList.all
      end

      # GET /todo_lists/1
      # GET /todo_lists/1.json
      def show
      end

     # GET /todo_lists/new
      def new
         @todo_list = TodoList.new
      end

      # GET /todo_lists/1/edit
      def edit
      end

      # POST /todo_lists
      # POST /todo_lists.json
      def create
        @todo_list = TodoList.new(todo_list_params)

        respond_to do |format|
          if @todo_list.save
            format.html { redirect_to @todo_list, notice: 'Todo list was successfully created.' }
            format.json { render :show, status: :created, location: @todo_list }
          else
             format.html { render :new }
             format.json { render json: @todo_list.errors, status: :unprocessable_entity }
          end
        end
      end

      # PATCH/PUT /todo_lists/1
      # PATCH/PUT /todo_lists/1.json
      def update
        respond_to do |format|
        if @todo_list.update(todo_list_params)
            format.html { redirect_to @todo_list, notice: 'Todo list was successfully updated.' }
            format.json { render :show, status: :ok, location: @todo_list }
          else
            format.html { render :edit }
            format.json { render json: @todo_list.errors, status: :unprocessable_entity }
          end
        end
      end

      # DELETE /todo_lists/1
      # DELETE /todo_lists/1.json
      def destroy
        @todo_list.destroy
        respond_to do |format|
          format.html { redirect_to todo_lists_url, notice: 'Todo list was successfully destroyed.' }
          format.json { head :no_content }
        end
      end

      private
        # Use callbacks to share common setup or constraints between actions.
        def set_todo_list
         @todo_list = TodoList.find(params[:id])
        end

        # Never trust parameters from the scary internet, only allow the white list through.
        def todo_list_params
          params.require(:todo_list).permit(:title, :description)
        end
    end

1 Answer

Clayton Perszyk
MOD
Clayton Perszyk
Treehouse Moderator 48,850 Points

Hey john2015,

I'm still relatively new to rails so i'm sorry if I can't give you definitive solution to your problem, but I might be able to help.

The comments you see above each of the controller actions tell you the HTTP verb + URI each action responds to when it receives a request from the browser. That is probably not a very illuminating answer, so i'll defer to the RailsGuides if you're interested in looking into it further: http://guides.rubyonrails.org/routing.html

I watched the video again and it looks like you may be missing some things. Here's what I got (BEWARE! There may be typos):

require 'spec_helper'

describe "Editing todo lists" do
    let!(:todo_list) { TodoList.create(title: "Groceries", description: "Grocery List.") }

    def update_todo_list(options={})
        options[:title] ||= "My todo list"
        options[:description] ||= "This is my todo list."
        todo_list = options[:todo_list]

        visit "/todo_lists"
        within "#todo_list_#{todo_list.id}" do
            click_link "Edit"
        end

        fill_in "Title", with: options[:title]
        fill_in "Description", with: options[:description]
        click_button "Update Todo list"
    end

    it "updates a todo list successfully with the correct information" do
        update_todo_list todo_list: todo_list,
                         title: "New title",
                         description: "New description"

        todo_list.reload

        expect(page).to have_content("Todo list was successfully updated")
        expect(todo_list.title).to eq("New title")
        expect(todo_list.description).to eq("New description")
    end
end

You're also receiving the error: ActiveRecord::StatementInvalid: SQLite3::CantOpenException; I googled it and it looks like your db file may not have the right permissions. But I'm not sure if that has something to do with your current edit_spec.rb, or if that is what the problem could actually be.