Обновление: я разместил это на github jquery-datatables-rails, так как это похоже на проблему с этим драгоценным камнем или, что более вероятно, с моим использованием. Я также размещаю обновленную копию здесь с дополнительным описанием, чтобы попросить о помощи. Обратите внимание, что хотя блок response_to выполняется дважды, код с данными выполняется только при втором выполнении блока.
Я пытаюсь передать переменную с именем my_view методу индекса контроллера элементов, чтобы я мог выборочно отображать результаты. Текущий код работает, вроде... В конце концов, представление не сохраняется, и любое действие в результирующей таблице, например прокрутка, приводит к тому, что таблица возвращается к отображению всех элементов вместо желаемого выбора.
Основная проблема заключается в том, что метод index всегда выполняется дважды при каждом нажатии кнопки. В первый раз переменная my_view установлена правильно. Второй раз всегда ноль. Гем jquery-datatables-rails выполняется на обоих проходах и, вероятно, задействован. Кажется, что я получаю две разные транзакции. Я даже пробовал переменные экземпляра, и они также равны нулю во время второго прохода. Я не понимаю, как и почему это происходит.
Чтобы «исправить» эту проблему, я устанавливаю session[:my_view] во время первого прохода, а затем не устанавливаю его снова при втором проходе. Затем во время выполнения ItemsDatatable.new я должен очистить session[:my_view], иначе он будет сохранен для следующей транзакции, дающей неверные результаты. Однако это приводит к проблеме, о которой я говорил, в том, что любое изменение в представлении, такое как прокрутка, приводит к возврату к отображению всех элементов вместо желаемого выбора.
Любопытно, что у меня нет других методов контроллера с такой аномалией, или, по крайней мере, я этого не заметил. Может ли кто-нибудь сказать мне, почему метод индекса выполняется дважды и как я могу решить эту проблему? Благодарю вас!
РЕДАКТИРОВАТЬ ОБНОВЛЕНИЕ: у меня есть еще один контроллер в пространстве имен администратора, который использует response_to с параметрами HTML/JSON. Он также выполняется дважды, поэтому кажется, что это может (?) быть связано. Все еще кажется странным поведение, чтобы потерять все переменные и выполнить его во второй раз, но я не знаю. Связано ли это и как я могу это решить? Спасибо...
Вот мои кнопки:
<%= link_to 'My Items', items_path(my_view: current_associate.id), class: 'btn btn-primary kc-wide' %>
<%= link_to 'All Items', items_path(my_view: "all"), class: 'btn btn-primary kc-wide' %>
И Items Controller с методом index:
class ItemsController < ApplicationController
def index
session[:my_view] ||= params[:my_view]
respond_to do |format|
format.html
format.json { render json: ItemsDatatable.new(view_context) }
end
end
end
Связанные маршруты, на всякий случай?
POST /items_index(.:format) items#index
items GET /items(.:format) items#index
POST /items(.:format) items#create
new_item GET /items/new(.:format) items#new
edit_item GET /items/:id/edit(.:format) items#edit
item GET /items/:id(.:format) items#show
PATCH /items/:id(.:format) items#update
PUT /items/:id(.:format) items#update
DELETE /items/:id(.:format) items#destroy
Код Rails с данными:
class ItemsDatatable < ApplicationController
before_action :check_if_associate
delegate :params, :h, :link_to, :edit_item_path, :new_item_path, :location, to: :@view
def check_params(params)
# When using the .json suffix in URI, need to stub params so that I can see that JSON information
params[:draw] = 1 if params[:draw].blank?
params[:columns] = Array.new(1, {data: 0, name: '', searchable: true, orderable: true, search: {value: '', regex: false}}) if params[:columns].blank?
params[:order] = Array.new(1, {column: 0, dir: 'asc'}) if params[:order].blank?
params[:start] = 0 if params[:start].blank?
params[:length] = 10 if params[:length].blank?
params[:search] = {value: '', regex: false} if params[:search].blank?
end
def initialize(view)
@view = view
check_params(params)
@view
end
def as_json(options = {})
{
draw: params[:draw].to_i,
recordsTotal: Item.count,
recordsFiltered: items.total_entries,
data: data
}
end
private
def data
todays_date = Time.zone.now.to_date
items.map do |item|
status = item.status
# If current associate has it, show where it is.
if item.checkedout?(@view.current_associate)
status = "#{item.status}-#{item.lastloc}"
end
# If it's checked out but someone else has it, show who has it.
if item.not_available? and !item.checkedout?(@view.current_associate)
status = "#{item.status}-#{item.location}"
end
# Override the above if in return status, just showing that.
status = item.status == "Rtn" ? "Rtn" : status
odometer = item.odometer.to_s.gsub(/(\d)(?=(\d{3})+(?!\d))/, "\\1,")
msrp = item.msrp.to_s.gsub(/(\d)(?=(\d{3})+(?!\d))/, "\\1,")
age_date = item.age_date.nil? ? todays_date : item.age_date.to_date
[
link_to(item.stock_number, edit_item_path(item)),
ERB::Util.h(item.year),
ERB::Util.h(item.make),
ERB::Util.h(item.model),
ERB::Util.h(item.color),
ERB::Util.h(status),
ERB::Util.h(odometer),
ERB::Util.h(msrp),
ERB::Util.h((todays_date - age_date).to_i)
]
end
end
def items
@items ||= fetch_items
end
def fetch_items
items = Item.order("#{sort_column} #{sort_direction}")
items = items.includes(:item_location, item_location: [:locator])
items = items.includes(:key, key: [:key_location])
items = items.page(page).per_page(per_page)
unless @view.session[:my_view].blank? || @view.session[:my_view] == "all"
associate = Associate.find(@view.session[:my_view]).name
associate = associate.gsub(/'/, "''") # .gsub(/'/, "\\\\\'")
items = items.where("clshadow = \'#{associate}\'")
end
@view.session[:my_view] = nil
if params[:search][:value].present?
items = items.where("stock_number ilike :search or yrshadow ilike :search or mkshadow ilike :search or mdshadow ilike :search or coshadow ilike :search or status ilike :search", search: "%#{params[:search][:value]}%")
end
items
end
def page
params[:start].to_i/per_page + 1
end
def per_page
params[:length].to_i > 0 ? params[:length].to_i : 10
end
def sort_column
columns = %w[stock_number yrshadow mkshadow mdshadow coshadow status odometer msrp age_date]
columns[params[:order][0][:column].to_i]
end
def sort_direction
params[:order][0][:dir] == "desc" ? "desc" : "asc"
end
end
Связанный код JavaScript:
var itemstable = $('#itemstable').DataTable({
responsive: true,
autoWidth: false,
pagingType: 'full',
jQueryUI: true,
processing: true,
serverSide: true,
ajax: {
url: 'items_index.json',
type: 'POST',
contentType: 'application/json',
dataType: 'json',
data: function(d) {
return JSON.stringify(d);
}
},
columns: [null, null, null, null, null, null,
{className: 'dt-right'},
{className: 'dt-right'},
{className: 'dt-right'}
]
});
И вид:
<div class="span9">
<p>
<table id="itemstable" class="display dt-responsive no-wrap table-striped" width="80%">
<thead>
<tr>
<th class="all">Stock No.</th>
<th class="all">Year</th>
<th class="all">Make</th>
<th class="min-tablet">Model</th>
<th class="min-tablet">Color</th>
<th class="all">Status</th>
<th class="desktop">Mileage</th>
<th class="desktop">MSRP</th>
<th class="desktop">Aged</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
<%= link_to 'My Items', items_path(my_view: current_associate.id),
class: 'btn btn-primary kc-wide' %>
<%= link_to 'All Items', items_path(my_view: "all"),
class: 'btn btn-primary kc-wide' %>
<%= link_to 'Recent Items', x_logs_path,
class: 'btn btn-primary kc-wide' %>
<%= link_to 'Home', '/', class: 'btn btn-primary kc-wide' %>
</div>