Rails4:ajax-datatables-rails:NoMethodError(未定义的方法`map'代表nil:NilClass)

时间:2014-08-02 13:38:29

标签: ruby-on-rails datatable

我正在使用' jquery-datatables-rails','〜> 2.1.10.0.2'使用ajax-datatables-rails。我已经成功地在我的项目中实现了两个用例,但在第三个中我遇到了这个问题。

我的观点文件是:

<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>

    

我的datatable js文件是:

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;
});

我的控制器文件是:

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

我的数据表rb文件是:

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

我试过调试,发现控制器的索引查询返回3条记录,但仍然出现以下错误:

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'

我一直在敲打我的头2天,搜索网但无济于事。任何帮助将受到高度赞赏。

1 个答案:

答案 0 :(得分:7)

我在这里看到以下内容:

您的controller.rb文件不应从数据库中检索任何数据,因为这不会“神奇地”传递到数据表中。另外,我在你的datatable.rb文件中看到你需要访问current_user实例(可能由devise定义)。

这就是你完成这项任务的方法:

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

您可以在此处了解有关可以传递给数据表类的参数的更多信息:https://github.com/antillas21/ajax-datatables-rails#options

这个想法是:

  • view_context是必需的
  • 您可以根据需要传递键值的可选哈希值。在我描述的示例中,我将current_user实例分配给名为:user
  • 的键
  • 作为参数传递的哈希在datatable类中的options下可用,这就是我使用options[:user]检索初始化时传递的实例的原因。