Ruby 2.0.0, Rails 4.0.3, jquery-datatables-rails 2.2.3 (DataTables 1.10.2)
I would like to have two buttons on my form, one to display all items and another to display only those items currently assigned to the current user. Given that I am even going down the right path for this, and I am not certain I am, I have two issues. Or am I on the wrong path?
In the controller action, I am attempting to pass the current user to the view which is created by the ItemsDatatable controller. Debugging shows the index action running twice. The first time, user is set as expected. The second time, user is nil so it is never passed to ItemsDatatable. Why is that and how do I fix it? (If I unconditionally set user in the controller index action, it is passed.)
The second problem is more esoteric. If I am able to set @user in initialize, how do I pass that to as_json and onto the other ItemsDatatable actions? I suppose this is specific to jquery-datatables-rails and I might have to ferret out its logic to decide how to do that? Or is there a Rails way of doing that nicely?
FYI, this is the DataTables pattern from RailsCasts 340 that has been updated for DataTables 1.10.2.
Thanks for the help.
Home page buttons:
<%= link_to 'Status-My Items', items_path(select: "mine"), :class => 'btn btn-primary' %>
<%= link_to 'Status-All Items', items_path(select: "all" ), :class => 'btn btn-primary' %>
ItemsController index action:
def index
user ||= params[:select] == "mine" ? current_user : nil
respond_to do |format|
format.html
format.json { render json: ItemsDatatable.new(view_context, user) }
end
end
ItemsDatatable controller:
class ItemsDatatable < ApplicationController
delegate :params, :h, :link_to, :edit_item_path, :new_item_path, :location, to: :@view
def initialize(view, user)
@view = view
@user = user
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 = Date.today
items.map do |item|
[
link_to(item.stock_number, edit_item_path(item))
]
end
end
def items
@items ||= fetch_items
end
def fetch_items
items = Item.order("#{sort_column} #{sort_direction}")
items = items.page(page).per_page(per_page)
if params[:search][:value].present?
items = items.where("stock_number 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]
columns[params[:order]['0'][:column].to_i]
end
def sort_direction
params[:order]['0'][:dir] == "desc" ? "desc" : "asc"
end
end
Looks to me like the answer to both questions is to use session storage:
The view:
<%= link_to 'My Items', items_path(my_view: current_user.id),
class: 'btn btn-primary' %>
<%= link_to 'All Items', items_path(my_view: "all"),
class: 'btn btn-primary' %>
The controller:
session[:my_view] ||= params[:my_view]
Where used:
unless @view.session[:my_view] == "all"
user = User.find(@view.session[:my_view]).name
items = items.where("clshadow = \'#{user}\'")
end
@view.session[:my_view] = nil