Stuart Pontins
Stuart Pontins

Reputation: 285

Saving boolean change in rails 4

I'm trying to update my :completed field in rails 4 from the dashboard#home rather than the todos#edit. I have tried both PATCH and POST - none save, but with POST I don't get a 404 error when I click the checkbox, and with PATCH I do 'PATCH http://localhost:3000/dashboard 404 (Not Found)'. I'm not sure which one I have to use because I've seen some use POST and some PATCH.

My Route

patch 'todos/:id' => 'todos#completed'

My dashboard#home.html.erb

<%= check_box_tag 'todo[completed]', todo.id, todo.completed, data: { remote: true, url: url_for(controller: :todos, action: :completed, id: todo), method: "PATCH" }, id: todo.id %>
<%= label_tag todo.id, "COMPLETE", :class => 'strikethrough' %>

My Todo Complete Action

  def completed
    if @todo.update_attributes(:completed => params[:completed])
      flash[:success] = "Wowzers."
      redirect_to action: :show
    else
      flash.now[:error] = "Not so wowzers..."
      render :new
    end
  end

My Rails Console as PATCH

Started PATCH "/todos/e3309e65a5f225ec696807ee1f5be3" for 80.193.7.142 at 2016-04-30 20:11:42 +0000
Cannot render console from 80.193.7.142! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
Processing by TodosController#update as JS
  Parameters: {"todo"=>{"completed"=>"19"}, "id"=>"e3309e65a5f225ec696807ee1f5be3"}
  Todo Load (0.2ms)  SELECT  "todos".* FROM "todos" WHERE "todos"."slug" = ?  ORDER BY "todos"."id" ASC LIMIT 1  [["slug", "e3309e65a5f225ec696807ee1f5be3"]]
  User Load (0.1ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ?  ORDER BY "users"."id" ASC LIMIT 1  [["id", 1]]
   (0.1ms)  begin transaction
DEPRECATION WARNING: You attempted to assign a value which is not explicitly `true` or `false` ("19") to a boolean column. Currently this value casts to `false`. This 
will change to match Ruby's semantics, and will cast to `true` in Rails 5. If you would like to maintain the current behavior, you should explicitly handle the values 
you would like cast to `false`. (called from block in update at /home/g9stuart4/recital/app/controllers/todos_controller.rb:46)
   (0.0ms)  commit transaction
Redirected to http://g9stuart4.koding.io:3000/dashboard
Completed 302 Found in 6ms (ActiveRecord: 0.4ms)


Started PATCH "/dashboard" for 80.193.7.142 at 2016-04-30 20:11:43 +0000
Cannot render console from 80.193.7.142! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255

ActionController::RoutingError (No route matches [PATCH] "/dashboard"):
  actionpack (4.2.5.1) lib/action_dispatch/middleware/debug_exceptions.rb:21:in `call'
  web-console (2.3.0) lib/web_console/middleware.rb:20:in `block in call'
  web-console (2.3.0) lib/web_console/middleware.rb:18:in `catch'
  web-console (2.3.0) lib/web_console/middleware.rb:18:in `call'
  actionpack (4.2.5.1) lib/action_dispatch/middleware/show_exceptions.rb:30:in `call'
  railties (4.2.5.1) lib/rails/rack/logger.rb:38:in `call_app'
  railties (4.2.5.1) lib/rails/rack/logger.rb:20:in `block in call'
  activesupport (4.2.5.1) lib/active_support/tagged_logging.rb:68:in `block in tagged'
  activesupport (4.2.5.1) lib/active_support/tagged_logging.rb:26:in `tagged'
  activesupport (4.2.5.1) lib/active_support/tagged_logging.rb:68:in `tagged'
  railties (4.2.5.1) lib/rails/rack/logger.rb:20:in `call'
  actionpack (4.2.5.1) lib/action_dispatch/middleware/request_id.rb:21:in `call'
  rack (1.6.4) lib/rack/methodoverride.rb:22:in `call'
  rack (1.6.4) lib/rack/runtime.rb:18:in `call'
  activesupport (4.2.5.1) lib/active_support/cache/strategy/local_cache_middleware.rb:28:in `call'
  rack (1.6.4) lib/rack/lock.rb:17:in `call'
  actionpack (4.2.5.1) lib/action_dispatch/middleware/static.rb:116:in `call'
  rack (1.6.4) lib/rack/sendfile.rb:113:in `call'
  railties (4.2.5.1) lib/rails/engine.rb:518:in `call'
  railties (4.2.5.1) lib/rails/application.rb:165:in `call'
  rack (1.6.4) lib/rack/lock.rb:17:in `call'
  rack (1.6.4) lib/rack/content_length.rb:15:in `call'
  rack (1.6.4) lib/rack/handler/webrick.rb:88:in `service'
  /home/g9stuart4/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/webrick/httpserver.rb:138:in `service'

Any information is greatly appreciated.

Upvotes: 1

Views: 496

Answers (2)

Stuart Pontins
Stuart Pontins

Reputation: 285

This is how I solved it.

My Controller

  def completed
    if @todo.update_attribute(:completed, [true, false])
      flash[:success] = "Wowzers."
      redirect_to dashboard_path
    else
      flash.now[:error] = "Not so wowzers..."
      render :new
    end
  end

My Checkbox & Input.

<%= check_box_tag 'todo[completed]', todo.id, todo.completed, data: { remote: true, url: url_for(controller: :todos, action: :completed, id: todo), method: "POST" }, id: todo.id %>
<%= label_tag todo.id, "COMPLETE", :class => 'strikethrough' %>

My Routes

post 'todos/:id' => 'todos#completed'

I also rolled back my migration and added null: false and default: 0 on to my checkbox, as when I was tinkering around I kept getting null a lot which I believe to be part of the problem.

Anyhow, checkboxes now check and uncheck accordingly and update the database.

Upvotes: 1

margo
margo

Reputation: 2927

The custom route can be added to the todos resources route.

resources :todos do
  member do
    put 'completed'
  end
end

Try running rake routes in the terminal to see what this produces.

The parameters hash is nested; the 'completed' value is nested within 'todo' so this line

if @todo.update_attributes(:completed => params[:completed])

should be

if @todo.update_attributes(:completed => params[:todo][:completed])

Are you sure you can add the url as data-attribute? I've not seen that before, which makes me think that is why you are getting the 404 error.

I would have thought you would need to surround the checkbox-tag with a form tag or use the button_to helper which you could then style to look like a checkbox. Font awesome has icons which you could use.

Upvotes: 0

Related Questions