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:
The first render has an associated data request which causes an 'already initialised' warning from DataTables, and
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?