0
votes

I know that this question has been asked many times before, but due to my inexperience I am unable to correct the problem using those responses. I had it working in a previous Rails project and cannot see what has changed. I started a new project using PostgreSQL rather than MySQL and I am now using Rails 3.2.8 (was 3.2.1).

Firebug showing: TypeError: aData is undefined at:

var aData = _fnGetObjectDataFn( oSettings.sAjaxDataProp )( json );
for ( var i=0, iLen=aData.length ; i<iLen ; i++ ) 

I gather that this is probably caused by Datatables not getting the correct JSON. A snippet shows below, which validates in JSONLint.

[{"code":"STATE 30","created_at":"2012-12-10T06:01:34Z","id":1,"name":"ALBANY     HIGHWAY","rank":null,"state":"WA","updated_at":"2012-12-10T06:01:34Z"},{"code":"ANNE BEADELL HIGHWAY","created_at":"2012-12-10T06:01:34Z","id":2,"name":"ANNE BEADELL HIGHWAY","rank":null,"state":"SA","updated_at":"2012-12-10T06:01:34Z"},...

I see that it doesn't include iTotalRecords, iTotalDisplayRecords and aaData. Is this the problem? I presume the JSON options are set by the def as_json, buy I don't explicity reference that in my render ??. The http get (as seen in Firebug) includes sEcho but not iTotalRecords.

My code is based on RailsCasts #340:

Controller: ( see the list action).

class HighwaysController < ApplicationController
  respond_to :html, :json

def index
  @highways = Highway.all
  respond_to do |format|
    format.html # index.html.erb
    format.json { render json: @highways }
  end
end

def list
  @highways = Highway.all
  logger.debug "Highway Count: #{@highways.size}"
  respond_to do |format|
    format.html # index.html.erb
    format.json { render json: HighwaysDatatable.new(view_context)}
  end
end

Associated Ruby code:

class HighwaysDatatable
  delegate :params, :h,:link_to,:number_to_currency,to: :@view

  def initialize(view)
    @view = view
  end

  def as_json(options = {})
    {
     sEcho: params[:sEcho].to_i,
     iTotalRecords: Highway.count,
     iTotalDisplayRecords: highways.total_entries,
     aaData: data
    }
  end

  private

  def data
    highways.map do |highway|
      [
       h(highway.id),
       h(highway.name),
       h(highway.state),
       h(highway.code),
       h(highway.rank),
       h(highway.created_at),
       h(highway.updated_at)
      ]
    end
  end

  def highways
    @highways ||= fetch_highways
  end

  def fetch_highways
    ...  (as per RailsCasts code - code wrapped and did not show properly)    
  end
   highways
 end

 def page
   params[:iDisplayStart].to_i/per_page + 1
 end

 def per_page
   params[:iDisplayLength].to_i > 0 ? params[:iDisplayLength].to_i : 10
 end

 def sort_column
  columns = %w[name state code rank]
  columns[params[:iSortCol_0].to_i]
 end

 def sort_direction
    params[:sSortDir_0] == "desc" ? "desc" : "asc"
 end
end

and the list view:

<% @page_title = "Highways List" %>

  <h2>Highways</h2>

  <%= javascript_tag do %>
    window.highwaysURL = '<%= j highways_url %>';
  <% end %>

  <div id="EditLink">
    <%= link_to "Edit Highway", :controller => :highways, :action => :edit, :id => 1 %>
  </div>  
  <div>
    </br>
      <%= link_to 'Neighbours', '/neighbours/' %>
      <%= link_to 'Localities', '/localities/' %>
    </br>
  </div>
  <div id="tools">

  </div>      


 <table id="highways" class="display" data-source="<%= highways_url(format: "json") %>">
    <thead>
      <tr>
        <th>Id</th>
        <th>Highway</th>
        <th>State</th>
        <th>Code</th>
        <th>Rank</th>
        <th>Created At</th>
        <th>Updated At</th>
      </tr>
    </thead>
    <tbody>

    </tbody>    
 </table>

 <div id=editarea class='result'    ></div> 

My gemfile (with comments removed):

source 'https://rubygems.org'

gem 'rails', '3.2.8'
gem 'pg'
group :assets do
  gem 'sass-rails',   '~> 3.2.3'
  gem 'coffee-rails', '~> 3.2.1'
  gem 'uglifier', '>= 1.0.3'
end
gem 'libv8', '~> 3.11.8'
gem 'therubyracer', require: 'v8'
gem 'jquery-rails'
gem 'will_paginate'
gem 'debugger'

and application.js for Asset Pipeline:

//= require jquery
//= require jquery-ui
//= require jquery.dataTables
//= require TableTools
//= require ZeroClipboard
//= require datatable_highways
//= require datatable_localities
//= require datatable_neighbours
//= require_tree .

It's probably something simple, but it has been holding me up for some time. Thanks in anticipation.

UPDATE

The DataTables debugger bookmarklet indicates that the 'list' view is rendering the following which does not include the json parameters expected by DataTables.

http://localhost:3000/highways.json 

and I believe it should be:

http://localhost:3000/highways/list.json.

I am not sure if this is a controller or a view problem.

UPDATE

I have made various changes but still have the same problem. BUT I see two things in the log which are significant:

Entering localhost:3000/highways/list shows that 2 views are rendered.

 Processing by HighwaysController#list as HTML [1m[36mHighway Load (4.8ms)[0m  [1mSELECT "highways".* FROM "highways" ORDER BY name  
 Highway Count: 229
 Rendered highways/list.html.erb within layouts/highways (32.6ms)

then

Processing by HighwaysController#index as JSON
Parameters: {"sEcho"=>"1", "iColumns"=>"5", "sColumns"=>"", "iDisplayStart"=>"0",...    

The first is HTML (via action 'list') the second as JSON (via action 'index').

So there are two problems:

  1. The first render has an associated data request which causes an 'already initialised' warning from DataTables, and

  2. My routes.rb explicit match statement is catching the HTML to render the view, but the JSON response (from the AJAX call for the data rows) falls through and is handled by resources :highways and it then uses the 'index' action in the controller

routes.rb

match 'highways/list'=> 'highways#list' 
...
resources :highways

How do I stop the data request when I just want the view (column headings etc) rendered?
What route do I need to send the JSON response to the 'list' action in the controller?

1
Resolved. Went back to a minimal set up, 1 table using Ryan Bates #340 code - so using index action/view to get around the 2 render issue above. Still not working. Removed gem to rweng github and loaded DataTables files to ./vendor/assets. Now works. The index or list action can probably be fixed with an explicit route, but I could not get past 'missing template' when I tried to coerce it through the list action.need2surf

1 Answers

0
votes

Resolved. Went back to a minimal set up, 1 table using Ryan Bates #340 code - so using index action/view to get around the 2 render issue above. Still not working. Removed gem to rweng github and loaded DataTables files to ./vendor/assets. Now works. The index or list action can probably be fixed with an explicit route, but I could not get past 'missing template' when I tried to coerce it through the list action.