Skip to content

Instantly share code, notes, and snippets.

@cpuguy83
Last active December 18, 2015 04:29
Show Gist options
  • Save cpuguy83/5725468 to your computer and use it in GitHub Desktop.
Save cpuguy83/5725468 to your computer and use it in GitHub Desktop.
Serializes model for use with https://github.com/rjackson/pivot.js
class Foo < ActiveRecord::Base
include Pivotable
# calls method on self, labeled as the method name
pivot :name
# calls method on self and labels it with a custom name
pivot :some_awful_field_name, as: :a_better_field_name
# Calls value from another object/method than self
# Without the call to `as` this example would be named "some_related_object_bar", but with the `as`
# it will just be labeled "bar"
pivot :bar, from: :some_related_object, as: :bar
end
Foo.first.to_pivotable_csv
#=> "name, a_better_field_name, bar\noutput, values here\n"
Foo.all.to_pivotable_csv
#=> "name, a_better_field_name, bar\noutput, values, here\nfor, each, of\nyour,records,,\n
# Serializes model for use with pivot.js
# https://github.com/rjackson/pivot.js
require 'csv'
module Pivotable
extend ActiveSupport::Concern
included do
attr_reader :pivotable_attrs
@pivotable_field_options ||= []
end
def pivot_attrs!
self.class.pivotable_field_options.map do |f|
if f[:from] == :self
value = send(f[:field])
else
value = send(f[:from]).try(:send, f[:field])
end
{ f[:as] => value }
end.inject(&:merge)
end
def to_pivotable_csv(opts={})
@pivotable_attrs ||= pivot_attrs!
if pivotable_attrs
CSV.generate do |csv|
csv << pivotable_attrs.keys unless opts[:header] == false
csv << pivotable_attrs.values
end
end
end
class UnknownKeyError < StandardError; end
module ClassMethods
def pivot_field(field, opts={})
opts[:field] = field
opts[:from] ||= :self
opts[:as] ||= "#{opts[:from]}_#{opts[:field]}"
opts.except(:from, :as, :field).each_key { |k| raise UnknownKeyError, "#{key}" }
@pivotable_field_options ||= []
@pivotable_field_options << opts
end
alias_method :pivot, :pivot_field
def pivot_fields(*fields)
fields.each {|f| pivot_field(f) }
end
def pivotable_field_options
@pivotable_field_options
end
def to_pivotable_csv
objects_csv = all.each.map do |s|
s.to_pivotable_csv(header: false)
end.inject(:<<)
CSV.generate { |ccsv| ccsv << @pivotable_field_options.map { |o| o[:field] } } << objects_csv
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment