module Lipsiadmin module Controller module Ext # Return column config, and store config/data for ExtJS ColumnModel and Store # # Examples: # # # app/controllers/backend/debtors_controller.rb # def index # @column_store = column_store_for Debtor do |cm| # cm.add :id # cm.add "full_name_or_company.upcase", "Full Name", :sortable => true, :dataIndex => :company # cm.add :surname # Header will be autogenerated # cm.add :email, "Email", :sortable => true # cm.add :piva, "Piva", :sortable => true # cm.add :created_at, "Creato il", :sortable => true, :renderer => :date, :align => :right # cm.add :updated_at, "Aggiornato il", :sortable => true, :renderer => :datetime, :align => :right # end # # respond_to do |format| # format.js # format.json do # render :json => @column_store.store_data(params) # # # or you can manually do: # # debtors = Debtor.search(params) # # debtors_count = debtors.size # # debtors_paginated = debtors.paginate(params) # # render :json => { :results => @column_store.store_data_from(debtors_paginated), :count => debtors_count } # end # end # end # # # app/views/backend/index.rjs # page.grid do |grid| # grid.id "debtors-grid" # If you don't set this columns are not saved in cookies # grid.title "List al debtors" # grid.base_path "/backend/debtors" # grid.forgery_protection_token request_forgery_protection_token # grid.authenticity_token form_authenticity_token # grid.tbar :default # grid.store do |store| # store.url "/backend/debtors.json" # store.fields @column_store.store_fields # end # grid.columns do |columns| # columns.fields @column_store.column_fields # end # grid.bbar :store => grid.get_store, :pageSize => params[:limit] # Remember to add after defining store! # end # def column_store_for(model, &block) ColumnStore.new(model, &block) end class ColumnStore#:nodoc: attr_reader :data def initialize(model, &block)#:nodoc @model = model @data = [] yield self end # Method for add columns to the Column Model def add(*args) options = { :method => args[0] } options[:header] = args[1].is_a?(String) || args[1].is_a?(Symbol) ? args[1].to_s : nil args.each { |a| options.merge!(a) if a.is_a?(Hash) } # Add some defaults options[:header] ||= options[:method].to_s options[:sortable] = options[:sortable].nil? ? true : options[:sortable] # Try to translate header options[:header] = @model.human_attribute_name(options[:header].to_s) # Reformat DataIndex if options[:dataIndex].is_a?(Array) options[:dataIndex] = options[:dataIndex].collect do |f| f.is_a?(Symbol) ? "#{@model.table_name}.#{f}" : f end.join(",") end # Adding a name for our column options[:name] ||= "#{@model.table_name.singularize}[#{options[:method]}]" # Reformat query if options[:method].is_a?(Symbol) options[:dataIndex] ||= "#{@model.table_name}.#{options[:method]}" else # if we have eg. prodcedure.category.name we need to build # a sql finder action so we need to generate # procedures.categories.name columns = options[:method].split(".") if columns.empty? options[:dataIndex] ||= "#{@model.table_name}.#{options[:method]}" else options[:dataIndex] ||= columns[0..columns.length-2].collect(&:pluralize).join(".") + "." + columns.at(columns.size-1) end end # Reformat dataIndex options[:mapping] ||= options[:dataIndex].to_s.downcase.gsub(/[^a-z0-9]+/, '_'). gsub(/-+$/, '_'). gsub(/^-+$/, '_') # Now is necessary for our columns an ID options[:id] = options[:mapping] @data << options end # Return an array config for build an Ext.grid.ColumnModel() config def column_fields @data.clone.inject([]) do |fields, data| # Prevent to removing in the original Hash field = data.clone field.delete(:method) field.delete(:mapping) fields << field fields end end # Return an array config for build an Ext.data.GroupingStore() def store_fields @data.inject([]) do |fields, data| hash = { :name => data[:dataIndex], :mapping => data[:mapping] } hash.merge!(:type => data[:renderer]) if data[:renderer] && (data[:renderer] == :date || data[:renderer] == :datetime || data[:renderer] == :time_to_date) fields << hash fields end end # Return data for a custom collection for the ExtJS Ext.data.GroupingStore() json def store_data_from(collection) collection.inject([]) do |store, c| store << @data.inject({ :id => c.id }) do |options, data| options[data[:mapping]] = (c.instance_eval(data[:method].to_s) rescue I18n.t("lipsiadmin.labels.not_found")) options end store end end # Return a searched and paginated data collection for the ExtJS Ext.data.GroupingStore() json # You can pass options like: # # Examples # # store_data(params, :conditions => "found = 1") # store_data(params, :include => :posts) # def store_data(params, options={}) @model.send(:with_scope, :find => options) do collection = @model.search(params) collection_count = collection.length collection_paginated = collection.paginate(params) { :results => store_data_from(collection_paginated), :count => collection_count } end end end end end end