bradbajuz
bradbajuz

Reputation: 185

Rails AJAX Update on Select

I have an Index view that lists orders in a collection. Each order has a status. I want to be able to update the status of an order from the Index page, AJAX style.

Not sure why the ID is NULL when trying to update the record.

index.html.erb

<h1>Recent Orders</h1>

<section class="order-results">
  <ol class="list-group">
    <%= render partial: 'pf_order', collection: @pf_orders %>
  </ol>
</section>

_pf_orders.html.erb

<%= form_for(pf_order, url: update_receiver_status_path(pf_order)) do |f| %>
    <%= f.select :receiver_status, options_for_select(receiver_statuses, f.object.receiver_status), {include_blank: true}, {class: 'form-control'} %>
<% end %>

pf_orders_controller.rb

def index
  @pf_orders = PfOrder.all
end

def update_receiver_status
  @status = PfOrder.find_by(id: params[:id])
  @status.update_attributes(pf_order_params)
end

pf_orders.coffee

jQuery ($) ->
  $(document).ready ->
    $("#pf_order_receiver_status").bind 'change', ->
      $.ajax
        type: 'PATCH'
        url: 'pf_orders/update_receiver_status'
        data: 'pf_order[receiver_status]=' + $('#pf_order_receiver_status').val()

routes.rb

patch 'pf_orders/update_receiver_status', as: 'update_receiver_status'

LOGS

Started PATCH "/pf_orders/update_receiver_status" for 127.0.0.1 at 2016-10-01 17:36:11 -0400
Processing by PfOrdersController#update_receiver_status as */*
  Parameters: {"pf_order"=>{"receiver_status"=>"Completed"}}
  PfOrder Load (1.0ms)  SELECT  "pf_orders".* FROM "pf_orders" WHERE "pf_orders"."id" IS NULL LIMIT $1  [["LIMIT", 1]]
Completed 500 Internal Server Error in 4ms (ActiveRecord: 1.0ms)



NoMethodError (undefined method `update_attributes' for nil:NilClass):

Upvotes: 0

Views: 229

Answers (2)

bradbajuz
bradbajuz

Reputation: 185

Here's how I got this to work correctly:

pf_orders_controller.rb

def update_receiver_status
  @pf_order = PfOrder.find(params[:id])
  if @pf_order.update_attributes(pf_order_params)
    render json: @pf_order.as_json, status: :ok
  else
    render json: {pf_order: @pf_order.errors, status: :unprocessable_entity}
  end
end

def pf_order_params
  params.fetch(:pf_order, {}).permit(:sequence_number, :message_guid, :hl7_document, :download, :post_status_code, :patient_id, :receiver_status)
end

_pf_order.html.erb

Got rid of the form_for

<%= label :receiver_status, 'Status:' %>
          <%= select_tag :receiver_status,
                         options_for_select(receiver_statuses, pf_order[:receiver_status]),
                         onchange: "$.post('#{update_receiver_status_pf_order_path(pf_order)}',
                         {'_method':'patch', 'pf_order[receiver_status]':this.value} );",
                         class: 'form-control' %>

I removed the jQuery from pf_orders.coffee

routes.rb

resources :pf_orders do
  patch :update_receiver_status, on: :member
end

Thanks to Alexandre Angelim for the correct route and pointing me in the right direction.

Upvotes: 1

Alexandre Angelim
Alexandre Angelim

Reputation: 6753

You're not submitting the order's id anywhere. You can verify that in your logs Parameters: {"pf_order"=>{"receiver_status"=>"Completed"}}.

If you'd like to stick with RESTful routes(and I strongly believe you should), you're request should go to /pf_orders/:id/update_receiver_status.

You can change your route to:

patch 'pf_orders/:id/update_receiver_status', as: 'update_receiver_status'

or just add a custom route to your pf_orders resources:

resources :pf_orders do
  patch :update_receiver_status, on: :member
end

The last thing to do is retrieve the order's id in your javascript. That will already be reflected in your form's action URL, so it's easier to retrieve it from there.

jQuery ($) ->
  $(document).ready ->
    $("#pf_order_receiver_status").bind 'change', ->
      $.ajax
        type: 'PATCH'
        url: $('#pf_order_receiver_status').closest('form').attr('action')
        data: 'pf_order[receiver_status]=' + $('#pf_order_receiver_status').val()

Upvotes: 1

Related Questions