1

I am using 'jquery-datatables-rails', '~> 2.1.10.0.2' with ajax-datatables-rails. I have implemented two use cases in my project successfully, but in the third I am facing this issue.

My view file is:

<div class="container">
  <div class="row">
<h3>My Books</h3>
<div class="column">
  <div class="bs-docs-section">
    <div class="col-lg-12">
      <div class="bs-component">
        <div class="table-responsive">
          <table id="dataentriesDatatable" class="table table-striped table-hover table-bordered" data-source="<%= dataentries_path(format: :json) %>">
            <thead class="theaderGray">
            <tr>
              <th>Edit Book</th>
              <th>Name</th>
              <th>Subject</th>
              <th>Standard</th>
              <th>Book Entry Status</th>
            </tr>
            </thead>
            <tbody>
            </tbody>
          </table>
        </div>
      </div>
    </div>
  </div>
</div>

My datatable js file is:

var dtable = $('#dataentriesDatatable').dataTable({
"sDom": "<'row-fluid'<'span6'l><'span6'f>r>t<'row-fluid'<'span6'i><'span6'p>>",
"sPaginationType": "bootstrap",
"processing": true,
"serverSide": true,
"deferRender": true,
"bServerSide": true,
"ajax": $('#dataentriesDatatable').data('source'),
//"ajax": "../data/userarrays.txt",
"aoColumns": [
    { "bSortable": false },
    { "bSortable": false },
    { "bSortable": false },
    { "bSortable": false },
    { "bSortable": false }
]
});

var dtable_api = dtable.api();

// Grab the datatables input box and alter how it is bound to events
$(".dataTables_filter input")
.unbind() // Unbind previous default bindings
.bind("keypress keyup input", function(e) { // Bind our desired behavior
    // If the length is 3 or more characters, or the user pressed ENTER, search
    if(e.keyCode == 13 || e.keyCode == 36) {
        // Call the API search function
        dtable_api.search(this.value).draw();
    }
    // Ensure we clear the search if they backspace far enough
    // Sushant: commented for now
    /*if(this.value == "") {
     dtable_users_api.search("").draw();
     }*/
    return;
});

My controller file is:

class DataentriesController < ApplicationController
before_filter :authenticate_user!
before_action :set_dataentry, only: [:show, :edit, :update, :destroy]

# GET /dataentries
# GET /dataentries.json
def index
@dataentries = BookEntryAssignment.where(user_id: current_user.id)
#@dataentries = BookEntryAssignment.get_dataentry_book_entry_assignment(current_user.id)
#@dataentries = BookEntryAssignment.all
respond_to do |format|
  format.html
  format.json { render json: DataentriesDatatable.new(view_context) }
end
end

# GET /dataentries/1
# GET /dataentries/1.json
def show
end


private
# Use callbacks to share common setup or constraints between actions.
#def set_dataentry
#  @dataentry = Dataentry.find(params[:id])
#end

# Never trust parameters from the scary internet, only allow the white list through.
#def dataentry_params
#  params[:dataentry]
#end
end

My datatable rb file is:

class DataentriesDatatable < AjaxDatatablesRails::Base
# uncomment the appropriate paginator module,
# depending on gems available in your project.
include AjaxDatatablesRails::Extensions::Kaminari
def_delegators :@view, :form_authenticity_token, :link_to, :book_path, :form_for, :concat, :content_tag, :button_tag, :current_user, :image_tag, :asset_path


def sortable_columns
# list columns inside the Array in string dot notation.
# Example: 'users.email'
#@sortable_columns ||= ['book_entry_assignments.book_id']
end

def searchable_columns
# list columns inside the Array in string dot notation.
# Example: 'users.email'
#@searchable_columns ||= ['book_entry_assignments.book_id']
end

private

def data
records.map do |record|
  [
      display_image(record, record.book.image_path, record.book.image_name),
      record.book.name,
      record.book.subject.name,
      record.book.standard.name,
      data_entry_status(record),
      record.book.publish_status.titleize
  # other attributes
  # comma separated list of the values for each cell of a table row
  # example: record.attribute,
  ]
 end
end

def get_raw_records
# insert query here
BookEntryAssignment.where(user_id: current_user.id)
end


# ==== Insert 'presenter'-like methods below if necessary

def data_entry_status(instance)
status = String.new
#@book_entry_assignment = BookEntryAssignment.find_by(book_id: instance.id)
if !@book_entry_assignment.nil?
  status = instance.status.titleize
end
status
end

def display_image(instance, imagePath, imageName)
content_tag(:div, class: 'col-lg-4') do
  #content_tag(:a, :href => edit_book_path(instance), :alt => 'Edit Book') do
    image_tag("/assets/book_images/" +imageName, size: "130x150", alt: "Edit Book")
  #end
end
end

end

I have tried to debug and I find that the controller's index query is returning 3 records but still I get the following error:

NoMethodError (undefined method `map' for nil:NilClass):
  app/controllers/dataentries_controller.rb:13:in `block (2 levels) in index'
  app/controllers/dataentries_controller.rb:11:in `index'

I have been banging my head on this for 2 days, searched the net but to no avail. Any help will be highly appreciated.

4
  • 1
    records is nil so it is throwing error Commented Aug 2, 2014 at 14:41
  • Thanks Rajarshi, I know that, but why is it nil is my question as I have followed the framework's steps properly. In other two implementations that I have I do NOT get this error, they work fine. Commented Aug 3, 2014 at 6:25
  • I have debugged and seen that the index query in controller and get_raw_records are returning 3 records but still the records is nil. Commented Aug 3, 2014 at 7:15
  • I have edited my post as I have removed my model class because there is no corresponding table in DB for it. I still get the same error. This is the only difference between my 2 earlier successful implementations of datatable (wherein there was a model class and a table in DB) and this one. Commented Aug 3, 2014 at 19:01

1 Answer 1

7

I see the following here:

Your controller.rb file should not retrieve any data from the database, as this is not "magically" passed into the datatable. Also, I see that in your datatable.rb file you need access to the current_user instance (defined perhaps by devise).

This is how you would accomplish this task:

class DataentriesController < ApplicationController
  before_filter :authenticate_user!
  before_action :set_dataentry, only: [:show, :edit, :update, :destroy]

  def index
    respond_to do |format|
      format.html
      format.json { render json: DataentriesDatatable.new(view_context, { user: current_user }) }
    end
  end
end



class DataentriesDatatable < AjaxDatatablesRails::Base
  def get_raw_records
    BookEntryAssignment.where(user_id: options[:user].id)
  end
end

You can learn more about the arguments you can pass to a datatable class here: https://github.com/antillas21/ajax-datatables-rails#options

The idea is:

  • The view_context is required
  • You can pass in an optional hash of key values as you need it. In the example I describe, I assigned the current_user instance to a key named :user
  • This hash passed as argument is available under as options inside the datatable class, and that is why I use options[:user] to retrieve the instance passed on initialization.
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.