extract subclass generation logic from custom fields group by

git-svn-id: https://dev.finn.de/svn/cockpit/branches/reporting_merge@1759 7926756e-e54e-46e6-9721-ed318f58905e
pull/6827/head
rkh 14 years ago
parent 788845f2ec
commit 676de3ac8b
  1. 6
      app/controllers/cost_reports_controller.rb
  2. 4
      app/models/cost_query/chainable.rb
  3. 57
      app/models/cost_query/custom_field_mixin.rb
  4. 3
      app/models/cost_query/group_by.rb
  5. 46
      app/models/cost_query/group_by/custom_field.rb
  6. 2
      app/models/cost_query/inherited_attribute.rb
  7. 2
      app/models/cost_query/sql_statement.rb

@ -1,6 +1,7 @@
class CostReportsController < ApplicationController
before_filter :find_optional_project, :only => [:index]
before_filter :generate_query, :only => [:index]
before_filter :load_all
helper :reporting
include ReportingHelper
@ -117,6 +118,11 @@ class CostReportsController < ApplicationController
end
end
def load_all
CostQuery::GroupBy.all
CostQuery::Filter.all
end
private
## FIXME: Remove this once we moved to Redmine 1.0
def find_optional_project

@ -6,8 +6,8 @@ class CostQuery < ActiveRecord::Base
include CostQuery::QueryUtils
extend CostQuery::InheritedAttribute
inherited_attribute :applies_for,
:default => :label_cost_entry_attributes #this attr. should point to a symbol useable for translations
# this attr. should point to a symbol useable for translations
inherited_attribute :applies_for, :default => :label_cost_entry_attributes
def self.accepts_property(*list)
CostQuery.accepted_properties.push(*list.map(&:to_s))

@ -0,0 +1,57 @@
module CostQuery::CustomFieldMixin
def self.extended(base)
base.inherited_attribute :factory
base.factory = base
super
end
def all
@all ||= generate_subclasses
end
def generate_subclasses
IssueCustomField.all.map do |field|
class_name = class_name_for field.name
parent.send(:remove_const, class_name) if CostQuery::GroupBy.const_defined? class_name
parent.const_set class_name, Class.new(self).prepare(field, class_name)
end
end
def on_prepare(&block)
@on_prepare = block if block
@on_prepare
end
def prepare(field, class_name)
label field.name
table_name(class_name.demodulize.underscore.tableize)
dont_inherit :group_fields
join_table (<<-SQL % [CustomValue.table_name, table_name, field.id, field.name]).gsub(/^ /, "\t")
-- BEGIN Custom Field Join: "%4$s"
LEFT OUTER JOIN (
\tSELECT
\t\tvalue AS %2$s,
\t\tcustomized_type,
\t\tcustom_field_id,
\t\tcustomized_id
\tFROM
\t\t%1$s)
AS %2$s
ON %2$s.customized_type = 'Issue'
AND %2$s.custom_field_id = %3$d
AND %2$s.customized_id = entries.issue_id
-- END Custom Field Join: "%4$s"
SQL
instance_eval(&factory.on_prepare)
self
end
def new(*)
fail "Only subclasses of #{self} should be instanciated." unless self < factory
super
end
def class_name_for(field)
"CustomField" << field.split(/[ \-_]/).map { |part| part.gsub(/\W/, '').capitalize }.join
end
end

@ -21,9 +21,6 @@ module CostQuery::GroupBy
]
end
# trigger eager loading
all
def self.all_grouped
all.group_by { |g| g.applies_for }.to_a.sort { |a,b| a.first.to_s <=> b.first.to_s }
end

@ -1,48 +1,6 @@
module CostQuery::GroupBy
class CustomField < Base
def self.all
@all ||= generate_subclasses
end
def self.generate_subclasses
IssueCustomField.all.map do |field|
class_name = class_name_for field.name
CostQuery::GroupBy.send(:remove_const, class_name) if CostQuery::GroupBy.const_defined? class_name
CostQuery::GroupBy.const_set class_name, Class.new(self).prepare(field, class_name)
end
end
def self.prepare(field, class_name)
label field.name
table_name(class_name.demodulize.underscore.tableize)
dont_inherit :group_fields
group_fields table_name
join_table(<<-SQL % [CustomValue.table_name, table_name, field.id, field.name])
-- BEGIN Custom Field Join: "%4$s"
LEFT OUTER JOIN (
SELECT
value AS %2$s,
customized_type,
custom_field_id,
customized_id
FROM
%1$s)
AS %2$s
ON %2$s.customized_type = 'Issue'
AND %2$s.custom_field_id = %3$d
AND %2$s.customized_id = entries.issue_id
-- END Custom Field Join: "%4$s"
SQL
self
end
def self.new(*)
fail "Only subclasses of #{self} should be instanciated." unless self < CustomField
super
end
def self.class_name_for(field)
"CustomField" << field.split(/[ \-_]/).map { |part| part.gsub(/\W/, '').capitalize }.join
end
extend CustomFieldMixin
on_prepare { group_fields table_name }
end
end

@ -28,7 +28,7 @@ module CostQuery::InheritedAttribute
alias singleton_class metaclass unless respond_to? :singleton_class
def define_singleton_method(name, &block)
attr_writer name
singleton_class.send :attr_writer, name
singleton_class.class_eval { define_method(name, &block) }
define_method(name) { instance_variable_get("@#{name}") or singleton_class.send(name) }
end

@ -154,7 +154,7 @@ class CostQuery::SqlStatement
sql = "\n-- BEGIN #{desc}\n" \
"SELECT\n#{select.map { |e| "\t#{e}" }.join ",\n"}" \
"\nFROM\n\t#{from.gsub("\n", "\n\t")}" \
"\n#{joins.map { |e| "\t#{e}" }.join "\n"}" \
"\n\t#{joins.map { |e| e.gsub("\n", "\n\t") }.join "\n\t"}" \
"\nWHERE #{where.join " AND "}\n"
sql << "GROUP BY #{group_by.join ', '}\nORDER BY #{group_by.join ', '}\n" if group_by?
sql << "-- END #{desc}\n"

Loading…
Cancel
Save