Skip to content

Instantly share code, notes, and snippets.

@niklas
Last active September 9, 2015 11:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save niklas/c404b91f21a8410eaa45 to your computer and use it in GitHub Desktop.
Save niklas/c404b91f21a8410eaa45 to your computer and use it in GitHub Desktop.
A View for every User
class CompleteCapture < ActiveRecord::Base
TablesName = /\Acomplete_capture(\d+)s\z/
SubClassName = /\ACompleteCapture(\d+)\z/
self.abstract_class = true
cattr_accessor :company
include CapturedAt
class << self
def valid?
name =~ SubClassName && !abstract_class? && self < CompleteCapture
end
def subclass_names
@subclass_names ||= Set.new
end
def tables
connection.tables.grep(TablesName)
end
def inherit_for(company)
cn = :"CompleteCapture#{company.id}"
klass = if Object.const_defined?(cn)
Object.const_get cn
else
cl = Class.new(self)
subclass_names << cn
Object.const_set cn, cl
unloadable(cn)
cl
end
klass.company = company
klass.create_or_update_view!
klass
end
def create_or_update_view!
return if view_exists?
select_list = ["captures.*"].tap do |s|
company.ratio_definitions.each do |rdef|
s << rdef.sql_select_fragment
end
company.value_definitions.each do |vdef|
s << vdef.sql_select_fragment
end
end
join_list = company.value_definitions.map(&:sql_join_fragment)
relation = company.captures.select(select_list).joins(join_list)
connection.execute %Q~CREATE OR REPLACE VIEW #{table_name} AS #{relation.to_sql}~
end
def drop_view!
if view_exists?
connection.execute %Q~DROP VIEW IF EXISTS #{table_name}~
end
end
def view_exists?
connection.query("SELECT COUNT(*) FROM pg_views WHERE viewname='#{table_name}'").first.first.to_i > 0
end
# scopes
def for_company(company)
where(company_id: company.id)
end
def recent(n)
order('captured_at DESC').limit(n)
end
def chronologically
order('captured_at ASC, created_at ASC')
end
end
end
class Company < ActiveRecord::Base
module DefineCapturesExtension
def build(a={})
cap = super()
cap.define_values
cap.attributes = a
cap
end
def create!(a={})
cap = build(a)
cap.save!
cap
end
# FIXME this still feels dirty, move this into Capture
def build_human(human_attributes={})
human_attributes = human_attributes.stringify_keys
extra_attributes = human_attributes.slice *Capture::WhiteListThatAcceptsAllDynamicValues.accessible_attributes
human_attributes.delete_if {|k,v| Capture::WhiteListThatAcceptsAllDynamicValues.accessible_attributes.include?(k) }
cap = build extra_attributes
cap.human_values = human_attributes
cap
end
def build_humans(human_list=[])
human_list.map do |human_attributes|
build_human(human_attributes)
end
end
def create_humans!(human_list)
build_humans(human_list).each(&:save!)
end
def each
super do |cap|
cap.define_values
yield cap
end
end
def complete
Rails.logger.debug { "in Company::DefineCapturesExtension:\n #{ [self, proxy_owner, proxy_reflection, proxy_target].map(&:inspect).join("\n") }" }
self
end
end
has_many :captures, :inverse_of => :company, :extend => DefineCapturesExtension, :dependent => :destroy, order: 'captured_at ASC, created_at ASC'
# Returns Array of Ratio Definitions the Company has sufficient Values set for
def values_for_ratio(rdef)
rdef.value_definitions.select do |vdef|
has_values_for?(vdef)
end
end
# returns Array of Value Definitions the Company has set
def values_for_value(vdef)
captures_including_values.select {|c| c.read_value_for(vdef).present? }
end
# Cache the Captures including values
def captures_including_values
@captures_including_values ||= captures.including_values_for(self)
end
def complete_captures
tries = 0
begin
complete_captures_class.for_company(self)
rescue NameError => missing
tries += 1
if tries < 3
CompleteCapture.inherit_for self
retry
else
raise missing
end
end
end
def complete_captures_class
"CompleteCapture#{id}".constantize
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment