klenwell information services : kaminari

# Kaminari Install

Home page: https://github.com/amatsuda/kaminari

## Install Gem

	# Gemfile
	gem 'kaminari'
	
	# For Bootstrapified select picker
	gem 'bootstrap-select-rails', git: 'https://github.com/Slashek/bootstrap-select-rails', branch: "master"


	# Command line
	bundle install
	hg commit -m "Adds kaminari gem."
	
## Intialize

	bundle exec rails generate kaminari:config
	bundle exec rails generate kaminari:views bootstrap3
	hg add ./app
	hg add ./config
	hg commit -m "Adds kaminari templates."
	
## Configure

Find the configuration file at `config/initializers/kaminari_config.rb`

To access in app:

	Kaminari.config.default_per_page
	
## Implement

Using kaminari involves many steps...

### Controller

	respond_to do |format|
	  format.html do
		@users = paginate_users(@users)
	  end
	  format.csv do
		filename = "user_#{Time.zone.today.strftime('%m%d%Y')}.csv"
		headers['Content-Disposition'] = "attachment; filename=#{filename}"
		headers['Content-Type'] ||= 'text/csv'
	  end
	end
	
	private

	def paginate_users(users)
	  return users unless users.present?
  
	  # Get page
	  page_number = params.fetch(:page, 1)
  
	  # Get records-per-page
	  per_page = params.fetch(:per, Kaminari.config.default_per_page)
	  per_page = per_page == 'all' ? users.length : per_page
  
	  # Paginate
	  users = Kaminari.paginate_array(users) if users.class == Array
	  users.page(page_number).per(per_page)
	end
	
### View

	/ Slim index view: index.html.slim
	table.table.table-striped.table-bordered.table-hover
	  thead
		/! Top Pagination Nav
		- if self.formats == [:html]
		  tr
			td colspan='9'
			  .col-sm-2
				.header-block.header-text
				  .report-options
					= records_per_page_select(request.original_url, %w(25 50 100 all))
				  strong #{ pluralize(@users.total_count, 'wire') } found
			  .col-sm-8.text-center
				.header-block.header-text
				  = paginate @users
			  .col-sm-2
				.header-block.header-text.pull-right
				  = link_to_excel url_for(params.merge(format: 'csv'))

### Helper

	# application_helper.rb
	def records_per_page_select(original_url, pagination_options=%w(25 50 100))
	  # Duplicate params so we don't create problem elsewhere.
	  get_params = params.except('per', 'utf8', 'page', 'controller', 'action')
  
	  form_tag(original_url, id: 'per-page-form', class: 'form-horizontal', method: :get) do
		('<div class="col-sm-1 input-group pull-right header-block">' \
		 '<span class="input-group-addon">Displaying</span>' +
		 hash_to_hidden_fields(get_params) +
		 select_tag('per', options_for_select(pagination_options, params[:per]),
					class: 'selectpicker') +
		 '</div>'
		).html_safe
	  end
	end
  
	# Taken from: hash_to_hidden_fields gem
	def hash_to_hidden_fields(hash)
	  cleaned_hash = hash.reject { |_, v| v.nil? }
  
	  # It doesn't feel especially Railsy, but this is the simplest way I found to rebuild a
	  # nested hash (like params) as a flat mapping for the loop below to generate hidden fields.
	  pairs = CGI.unescape(cleaned_hash.to_query).split(Rack::Utils::DEFAULT_SEP)
  
	  tags = pairs.map do |pair|
		key, value = pair.split('=', 2)
		hidden_field_tag(key, value)
	  end
  
	  tags.join("\n").html_safe
	end
	
### Asset Files

Stylesheet:

	/* application.css.scss */
	*= require bootstrap-select

Javascript
	
	// application.js
	//= require bootstrap-select
	
	// Defines our application namespace
	var myApp = {};
	
	// Reserved for application-wide JS
	(function(module) {
	  module.ready = function() {
		// Bootstrapify any selectpickers
		$('.selectpicker').selectpicker();
	
		$('.clear-form').click(function() {
		  $(this).closest('form').find("input[type=text], textarea").val('');
	
		  // To reset selectpicker drop-downs
		  $('.selectpicker').selectpicker('val', '');
	
		  // Workaround for IE9: https://github.com/silviomoreto/bootstrap-select/issues/775
		  // TODO: when fix reaches gem, remove this.
		  $('.selectpicker').val('');
		  $('.selectpicker').selectpicker('render');
	
		  return false;
		});
	
		// Cause all per-page select picker changes to resubmit form
		$("#per-page-form").change(function() {
		  $(this).submit();
		});
	  }
	}(myApp.application={}));
	
	// Accepted Rails 4/Turbolinks event binding
	$(document).on('page:change page:restore', myApp.application.ready);