Last active
September 9, 2015 11:08
-
-
Save niklas/c404b91f21a8410eaa45 to your computer and use it in GitHub Desktop.
A View for every User
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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