Domanda

I have a Rails 3.2.14 app where I have calls, calls have units, units have statuses, and calls times in the model such as in_service_time.

I'm trying to write a controller action called in_service which updates the unit's status to "In Service" and time stamps call.in_service_time to Time.zone.now and does all of this via put remote (Ajax).

What I've written so far seems to work by updating the unit status and time stamping the call.in_service_time. But using :remote => true doesn't render the partials as I've specified in the in_service action. I have to wait for the screen to refresh via a getScript call in my index.html.erb for the call status to update. If I use :remote => false it reloads the page immediately without problems. If I use the :remote => true I also throw an exception in my development.log for NihlClass.

Below are excerpts of the code in question, the full code can be found here to keep things easier to read: full code

index.html.erb

<div id="active">
  <%= render "assigned_calls" %>
</div>

<div id="inactive">
  <%= render "unassigned_calls" %>
</div>


<script>
  $(function() {
    setInterval(function(){
      $.getScript("/calls").fail(function(jqxhr, settings, exception) {
        window.location = "/users/sign_in?duplicate_session=true";
      });
    }, 10000);
  });
</script>

index.js.erb

$("#active").html("<%= escape_javascript render("assigned_calls") %>");
$("#inactive").html("<%= escape_javascript render("unassigned_calls") %>");

routes.rb excerpt

resources :calls do
    member do
      post 'close'
      post 'cancel'
      post 'note'
      get 'opencall'
      get  'new_return'
      get 'duplicate_call'
      get 'edit_times'
      put 'update_billing'
      post 'dispatch_call'
      put 'en_route'
      put 'on_scene'
      put 'to_hospital'
      put 'at_hospital'
      put 'in_service'
    end

calls_controller.rb excerpt

def in_service
    @call = Call.find(params[:id])
    @unit = @call.units.first
    @call.update_attributes(in_service_time: Time.zone.now)
    @call.save
    @unit.status = Status.find_by_unit_status("In Service")
    @unit.save
    respond_to do |format|
       format.html { redirect_to calls_url }
       format.js { render "index" }
     end
   end

_assigned_calls.html.erb

<div class="page-header">
  <span class="badge badge-important"><%= @unassigned.count %></span> <strong>Unassigned calls</strong>
  <span class="badge badge-info"><%= @assigned.count %></span> <strong>Active calls</strong>
  <span class="badge badge-warning"><%= @scheduled.count %></span> <strong>Scheduled calls</strong>
  <%= render "search" %>
  <h2>Active Calls</h2>



</div>

<% @assigned.each do |call| %>
  <div class="widget">
    <div class="widget-header">
      <div class="pull-right">

        <%= link_to 'View', call, :class => 'btn btn-close'%>
        <% if dispatch? %>
        <%= link_to 'Edit', edit_call_path(call), :class => 'btn btn-close'%>
        <%= link_to 'Close', close_call_path(call), confirm: 'Are you sure you want to close the call?', :method => :post, :class => 'btn btn-danger' %>
        <%= link_to 'Cancel', cancel_call_path(call), confirm: 'Are you sure you want to cancel the call?', :method => :post, :class => 'btn btn-warning' %>
        <% end %>
      </div>
      <i class="icon-phone"></i>
      <h3><%= link_to call.incident_number, call %> <span><%= status(call) %></span></h3> 
      <% if call.traffic_type == "Emergency" %>
      <span class="badge badge-important"><%= call.traffic_type %></span>
      <% else %>
      <span class="badge badge-info"><%= call.traffic_type %></span>
     <% end %>
    </div>

    <div class="widget-content">
      <div class="row">
        <div class="span3">
         <h4>Patient Name: <small><%= call.patient_name %></small></h4>
          <div class="large-display">
            <% if call.call_status == "open" %>
            <div class="large <%= elapsed_overdue(call.elapsed_time) %>"><%= TimeFormatter.format_time(call.elapsed_time)%></div>
            <div class="small">Elapsed Time</div>
            <% else %>
              <% if call.closed_at? %>
            <div class="large <%= elapsed_overdue(call.run_time) %>"><%= TimeFormatter.format_time(call.run_time)%></div>
            <div class="small">Run Time</div>
              <% end %>
            <% end %>
          </div>
        </div>

        <div class="span2">
          <address>
            <strong><%= transferred_from(call) %></strong><br>
            <%= transferred_from_address(call) %>
          </address>
        </div>

        <div class="span1"><i class="icon-arrow-right dim"></i></div>

        <div class="span2">
          <address>
            <strong><%= transferred_to(call) %></strong><br>
            <%= transferred_to_address(call) %>
          </address>
        </div>

        <div class="span3">
          <% if call.service_level.level_of_service == "WC" %>
          <div class="left-icon dim"><i class="icon-user"></i></div>
          <% else %>
          <div class="left-icon dim"><i class="icon-ambulance"></i></div>
          <% end %>
          Assigned to <strong>Unit <%= call.units.map(&:unit_name).join(", ") %></strong><br />
          <% call.units.each do |unit| %>
            <div class="<%= set_status(unit.status) %>"><%= unit_status(unit) %></div>
          <% end %>
        </div>
      </div>

      <hr />

      <div class="row">
        <div class="span2">
          <div class="large-display">
            <div class="medium <%= transfer_due(call.transfer_date) %>"><%= call.transfer_date.strftime("%m/%d/%y %H:%M") %></div>
            <div class="small">Transfer Date</div>
          </div>
        </div>

        <div class="span1">
          <div class="large-display">
            <div class="small"><%= call.nature.try(:determinant) %></div>
            <div class="small">Nature</div>
          </div>
        </div>


        <div class="span5">
          <% if call.unit_ids.present? %>
            <div class="large-display">
              <div class="progress progress-striped"><%= progress_bar(call) %></div>
              <div class="small"><%= call.units.first.status.unit_status %></div>
              <div><%= link_to 'En Route', en_route_call_path(call), :class => 'btn btn-warning btn-medium', :method => :put, :remote => true %><%= link_to 'On Scene', on_scene_call_path(call), :class => 'btn btn-primary btn-medium', :method => :put, :remote => true %><%= link_to 'To Hospital', to_hospital_call_path(call), :class => 'btn btn-warning btn-medium', :method => :put, :remote => true %><%= link_to 'At Hospital', at_hospital_call_path(call), :class => 'btn btn-danger btn-medium', :method => :put, :remote => true %><%= link_to 'In Service', in_service_call_path(call), :class => 'btn btn-success btn-medium', :method => :put, :remote => true %></div>
              <div>ER: <%= call.en_route_time.try(:strftime, "%m/%d/%y-%k:%M") %> OS: <%= call.on_scene_time.try(:strftime, "%m/%d/%y-%k:%M") %> TO: <%= call.to_hospital_time.try(:strftime, "%m/%d/%y-%k:%M") %> AT: <%= call.at_hospital_time.try(:strftime, "%m/%d/%y-%k:%M") %>  IS: <%= call.in_service_time.try(:strftime, "%m/%d/%y-%k:%M") %></div>
            </div>
          <% end %>
        </div>



        <div class="span3">
          <div class="left-icon dim"><i class="icon-user"></i></div>
          <%= render partial: "medics_for_call", locals: {call: call} %>
        </div>
      </div>
    </div>
  </div>
<% end %>

development.log excerpt

NoMethodError - undefined method `count' for nil:NilClass:
  app/views/calls/_assigned_calls.html.erb:2:in `_app_views_calls__assigned_calls_html_erb___2549181816739942207_70125964034780'
È stato utile?

Soluzione

You're never setting @unassigned in your in_service action. So sending count to it throws an exception.

Rendering an action's view (render "index") from a different action does not execute the action's controller code.

EDIT: How to make it DRY:

class CallsController < ApplicationController
  ...

  def index
    setup_scheduling_variables
    @units = Unit.order("unit_name")
    @overdue = @assigned.select{|call| call.elapsed_time > 3600}
    @inservice = Unit.in_service
  end


  def in_service
    ...
    respond_to do |format|
       format.html { redirect_to calls_url }
       format.js do 
         setup_scheduling_variables
         render "index" 
       end
     end
   end

private

  def setup_scheduling_variables
    @assigned = params[:search].present? ? Call.search(params[:search]) : Call.assigned_calls.until_end_of_day.order("transfer_date ASC")
    @unassigned = Call.unassigned_calls.until_end_of_day
    @scheduled = Call.scheduled_calls
  end
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top