简体   繁体   中英

Patching complete todos in Ruby on Rails 4

I'm trying to add the ability to complete a todo item by patching in :complete method. Is it possible to use a checkbox for this rather than the link_to I have below? I would very much like a checkbox so it feels like the task is ticked off.

My View

<%= link_to "Mark as complete", complete_todo_path(todo.id), method: :patch %>

My Controller

def complete
  @todo.update_attribute(:completed_at, Time.now)
  redirect_to dashboard_path, notice: "Todo item completed"
end

My Resources

resources :todos do
 member do
     patch :complete
 end
end

EDIT:

I have gone about this another way but now face a different problem...

I have migrated a :completed boolean, I then added it to my form like so (simple_form)

<%= f.input :completed, as: :boolean %>

This allows me to update completed, not completed.

But how do I get this to show in my view? I don't want to have to click into each todo(edit) I want to do it from the index but not sure how to go about this?

From a RESTful standpoint there is no need for an additional route here.

Instead your would simply send a PATCH request to the normal member route:

PATCH /todos/:id, { todo: { complete: true } }

Also you want to do it like a real rockstar you might want to use a enum instead of a boolean:

class AddStatusToTodo < ActiveRecord::Migration
  def change
    add_column :todos, :status, :integer, default: 0, index: true
    remove_column :todos, :complete
  end
end

class Todo < ActiveRecord::Base
  enum status: [:incomplete, :complete, :removed] #etc
end

This lets you setup many states without creating several boolean columns and gives you a bunch of functionality almost for free.

To set this up on the view side you could simply create a form for each element:

<% @todos.each do |todo| %>
  <%= form_for(todo) do |f| %>
    <%= f.label :status %>
    <%= f.check_box(:status, class: 'complete-todo') %>
  <% end %>
<% end %>

We could use a classical submit button here but to give a good UX we want to use ajax. Having a form element gives us the perfect foundation since we can simply enhance its behavior:

// Setup jQuery to send the csrf-token
$.ajaxSetup({
    beforeSend: function(xhr){
      var token = $('meta[name="csrf-token"]').attr('content');
      xhr.setRequestHeader('X-CSRF-Token', token);
    }
});

// Handle clicks on the checkbox and send patch request in background
$().on('click', '.complete-todo', function(event){
  var $input, $form, promise;
  $input = $(this);
  $form = $input.closest('form');
  promise = $.ajax($form.attr('action'), {
    method: 'PATCH',
    data: {
      todo: {
        status: $input.is(':checked') ? 'complete' : 'incomplete'
      }
    }
  });
  // setup callbacks as needed
  promise.done(function(data, textStatus, jqXHR){
    console.log('Excellent!', data, textStatus, jqXHR);
  });
  promise.fail(function(jqXHR, textStatus, errorThrown){
    console.log('Oh Noes!', jqXHR, textStatus, errorThrown);
  });
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM