Completing a Todo

This is a companion discussion topic for the original entry at

Where is it setting “completed_at”?

I’m confused on this too. Did you figure out where that came from?

class CompletionsController < ApplicationController
  def create
    current_user.todos.find(params[:todo_id]).touch :completed_at
    redirect_to todos_path

completed_at is set by the touch method:

Saves the record with the updated_at/on attributes set to the current time. Please note that no validation is performed and only the after_touch, after_commit and after_rollback callbacks are executed.

If attribute names are passed, they are updated along with updated_at/on attributes.

I’m still a bit green with Rails and the idea of multiple controllers handling concerns for a model, e.g. CompletionsController setting completed_at for todos, is pretty foreign to me. Is this a common pattern? What is the benefit of this setup versus creating a complete method in TodosController?

From what I’ve learned it is better to try and not create methods in controllers outside the default ones.

This makes our API follow the REST conventions (wiki) which makes the API cleaner (I guess this could have personal preference).

Hope that helps! :smile:

It is a very common pattern, and recommended by a lot of very experienced practitioners - if not everyone. While there might be some cases where you want to do things differently, you will want to stick to this pattern as much as you can.

Try to keep your controllers public interface to the 7 Rails restful actions. You will have a cleaner, more approachable, more standard code base when it comes to controllers, and you can use rails routing helpers resource and resources out of box.

I was doing this tutorial, and had ran the migration successfully, however when I ran the spec it says: -

Failure/Error: todo = Time.current) ActiveRecord::StatementInvalid: Could not find table 'todos'

Any idea why is this happening? If it’s the case where my test database does not have the table Todo, any idea why rake db:migrate which seem to have ran successfully on my development database but not on my test database?

You might have to run rake db:test:prepare to ensure the test DB matches development. Newer versions of Rails aim to do this automatically, but it’s not always reliable.

Is anyone having problems getting the User completes todo successfully to pass after implementing the CompletionsController?

class CompletionsController < ApplicationController
  def create
    current_user.todos.find(params[:todo_id]).touch :completed_at
    redirect_to todos_path

Still getting the following error


  1) User completes todo successfully
     Failure/Error: expect(page).to have_css(".todo li.completed", text: "Buy milk")
       expected to find css ".todo li.completed" with text "Buy milk" but there were no matches
     # ./spec/features/user_completes_todo_spec.rb:13:in `block (2 levels) in <top (required)>'

It looks like the database is being updated correctly

Processing by CompletionsController#create as HTML
  Parameters: {"authenticity_token"=>"4NnIeG5+9nDuSoRqaNDc1ygq7nh4WWoX5vWNlPW7CsQzPqKuQUxVSSoZ6qrWhgyWVM3Ge7yCq56fkxWTX5UsDw==", "todo_id"=>"3"}
  Todo Load (0.3ms)  SELECT  "todos".* FROM "todos" WHERE "todos"."email" = ? AND "todos"."id" = ? LIMIT 1  [["email", ""], ["id", 3]]
   (0.2ms)  begin transaction
  SQL (0.8ms)  UPDATE "todos" SET "updated_at" = '2016-08-31 12:43:49.631686', "completed_at" = '2016-08-31 12:43:49.631686' WHERE "todos"."id" = ?  [["id", 3]]
   (50.2ms)  commit transaction
Redirected to http://localhost:3000/todos

Any suggestions?

SOLVED. All down to a silly spelling mistake :frowning: