Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

undefined method `fetch' for nil:NilClass #307

Closed
Nittarab opened this issue Sep 26, 2018 · 10 comments
Closed

undefined method `fetch' for nil:NilClass #307

Nittarab opened this issue Sep 26, 2018 · 10 comments
Assignees
Labels

Comments

@Nittarab
Copy link

Nittarab commented Sep 26, 2018

I'm using a lot of Datatable in my project. I can't understand what is going wrong the simplest Datatable that i have.
The error: undefined method 'fetch' for nil:NilClass is geted only when the table arr ordered by id
This is my datatable

class UsersDatatable < ApplicationDatatable
  include DatatableHelper
  include ApplicationHelper
  def_delegators :@view, :link_to, :user_path, :edit_user_path, :check_box_tag

  def view_columns
    # Declare strings in this format: ModelName.column_name
    # or in aliased_join_table.column_name format
    @view_columns ||= {
      id: { source: 'User.id', searchable: false },
      name: { source: 'User.name' },
      surname: { source: 'User.surname' },
      email: { source: 'User.email' },
      role_name: { source: 'Role.name' }
    }
  end

  def data
    records.map do |record|
      {
        DT_RowId: m_dt_check_box_tag('users[]', record.id, false, class: 'dt-row-checkbox'),
        name: link_to(record.name, record),
        surname: link_to(record.surname, record),
        email: link_to(record.email, record),
        role_name: link_to(record.roles_name.join(','), record),
        view: icon_to(SHOW_ICON, record),
        edit: icon_to(EDIT_ICON, edit_user_path(record)),
        delete: icon_to(DELETE_ICON,
                        record,
                        style: 'color:#f00',
                        method: :delete,
                        data: { confirm: I18n.t('datatable.confirm.delete') }),
        permission: permission(record, options[:current_user])
      }
    end
  end

  private

  def get_raw_records
    current_ability ||= Ability.new(options[:current_user])
    User.includes(users_roles: :role).accessible_by(current_ability)
  end

I define de columns in this way:

App.Users = {
    initColumns: function(){
        var columns = [
            {
                data: 'DT_RowId',
                title: "<label class='m-checkbox m-checkbox--bold m-checkbox--single'>" +
                    "<input id='dt-rows-checkbox' data-state='0' type='checkbox'><span></span></label>"
            },
            {data: 'name', title: I18n.t('js.users.datatable.columns.name')},
            {data: 'surname', title: I18n.t('js.users.datatable.columns.surname')},
            {data: 'email', title: I18n.t('js.users.datatable.columns.email')},
            {data: 'role_name', title: I18n.t('js.users.datatable.columns.role_name')},
            {data: null}
        ];
        return columns;
    },
    link_to_index_json: 'users.json?',
    tableId: '#users-table',

    index: function index() {
        App.Datatable.initDataTable(this.tableId, this.initColumns(), this.link_to_index_json);
    }
};
$(document).on("turbolinks:load", function () {
    if ($(".users.index").length > 0) {
        App.Users.index();
    }
});

And the datatable is inizialized in this whay:


initDataTable: function (tableId, columns_data, link, on_drawCallback = []) {
        var VIEW = 4;
        var EDIT = 1;
        var DELETE = 2;
        var CLONE = 8;
        var s = location.href;
        if (s[s.length - 1] === '/') {
            Turbolinks.visit(s.slice(0, -1));
        }
        var last_column = columns_data.length - 1;
        var table;

        if (!$.fn.dataTable.isDataTable(tableId)) {
            table = $(tableId).DataTable({
                serverSide: true,
                stateSave: true,
                pageLength: 10,
                dom: '<"pull-left m--padding-15 w-100-xsmall"l><"pull-right w-100-xsmall"B>rtip',
                ajax: link,
                columns: columns_data,
                columnDefs: [{
                    render: function (data, type, row) {
                        var perm = [];
                        if (row.permission & VIEW) perm.push(row.view);
                        if (row.permission & EDIT) perm.push(row.edit);
                        perm.push(row.download);
                        if (row.permission & CLONE) perm.push(row.clone);
                        if (row.permission & DELETE) perm.push(row.delete);
                        return '<div class="bottoni-tabelle" style="white-space: nowrap;">' + perm.join('  ') + '</div>';
                    },
                    width: "0%",
                    data: null,
                    sortable: false,
                    targets: last_column,
                    className: "cell-align-center"
                }]
            });

@pvin
Copy link

pvin commented Dec 6, 2018

@Nittarab hi Im getting the same error. Any fix?

@Nittarab
Copy link
Author

Nittarab commented Dec 6, 2018

@pvin Try to explain you situation, post your datatable.rb maybe I can help you.

@n-rodriguez
Copy link
Member

n-rodriguez commented Feb 9, 2019

The mapping is wrong :

You have :

    @view_columns ||= {
      id: { source: 'User.id', searchable: false },
      name: { source: 'User.name' },
      surname: { source: 'User.surname' },
      email: { source: 'User.email' },
      role_name: { source: 'Role.name' }
    }

and

  def data
    records.map do |record|
      {
        DT_RowId: m_dt_check_box_tag('users[]', record.id, false, class: 'dt-row-checkbox'),
        name: link_to(record.name, record),
        surname: link_to(record.surname, record),
        email: link_to(record.email, record),
        role_name: link_to(record.roles_name.join(','), record),
        view: icon_to(SHOW_ICON, record),
        edit: icon_to(EDIT_ICON, edit_user_path(record)),
        delete: icon_to(DELETE_ICON,
                        record,
                        style: 'color:#f00',
                        method: :delete,
                        data: { confirm: I18n.t('datatable.confirm.delete') }),
        permission: permission(record, options[:current_user])
      }
    end
  end

you should have

  def data
    records.map do |record|
      {
        id: m_dt_check_box_tag('users[]', record.id, false, class: 'dt-row-checkbox'),
        name: link_to(record.name, record),
        surname: link_to(record.surname, record),
        email: link_to(record.email, record),
        role_name: link_to(record.roles_name.join(','), record),
        DT_RowId: m_dt_check_box_tag('users[]', record.id, false, class: 'dt-row-checkbox'),
      }
    end
  end

@n-rodriguez n-rodriguez self-assigned this Feb 9, 2019
@abelavila140
Copy link

abelavila140 commented Feb 18, 2019

Having the same problem: this is my code

#categories_controller.rb

respond_to do |format|
      format.html
      format.json do
        render json: CategoryDatatable.new(params, view_context: view_context)
      end
    end




#category_datables.rb

class CategoryDatatable < AjaxDatatablesRails::ActiveRecord
  extend Forwardable

  def_delegators :@view, :link_to

  def view_columns
    @view_columns ||= {
       id: { source: 'Category.id', cond: :eq },
       name: { source: 'Category.name', cond: :like }
    }
  end

  def data
    records.map do |record|
      {
         id: record.id,
         name: record.name
      }
    end
  end

  def get_raw_records
    @view.current_user.school.categories
  end

  def initialize(params, options={})
    @view = options[:view_context]
    super
  end
end

The error im getting is NoMethodError (undefined method 'fetch' for nil:NilClass):

@pvin
Copy link

pvin commented Feb 18, 2019

Can you share ur js code?

@abelavila140
Copy link

This is my js:

:javascript
  $(function() {
    $('#datatable').DataTable({
      serverSide: true,
      ajax: $('#datatable').data('source'),
    });
  });

@pvin
Copy link

pvin commented Feb 18, 2019

Example

jQuery(document).ready(function() {
    $('#blogs-datatable').dataTable({
        "processing": true,
        "serverSide": true,
        "columnDefs": [{ "orderable": false, "targets": -1 }],
        "ajax": $('#blogs-datatable').data('source'),
        "pagingType": "full_numbers",
        "columns": [
            {"data": "id"},
            {"data": "title"},
            {"data": "description"},
            {"data": "comments"},
            {"data": "tag"}
        ]
        // pagingType is optional, if you want full pagination controls.
        // Check dataTables documentation to learn more about
        // available options.
    });
});

Have u added columns mentioned above??

Example

columns": [
{"data": "id"},
{"data": "name"} ]

@abelavila140
Copy link

I forgot to include the columns

@hrdwdmrbl
Copy link

I think it would be good for the library to detect this error and give a better error message. It had me for a while because I didn't suspect that a change in my JS would lead to an error like this in my backend.

For anyone reading this that wasn't satisfied with the answers above, the solution is to make sure you declare the columns parameter when declaring your DataTable.

$("#foo").DataTable({
  columns: [{data: "bar", ...}]
})

@ghost
Copy link

ghost commented Jan 4, 2021

Encountered this issue today. For me, a column defined in my JS code that was no longer in the backend(AjaxDatatablesRails::ActiveRecord class) caused the issue.

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants