lib/active_bugzilla/bug/service_management.rb
require 'active_support/concern'
module ActiveBugzilla::Bug::ServiceManagement
extend ActiveSupport::Concern
ATTRIBUTES_XMLRPC_RENAMES_MAP = {
# Bug => XMLRPC
:created_by => :creator,
:created_on => :creation_time,
:duplicate_id => :dupe_of,
:updated_on => :last_change_time,
# Some are absent from what Bugzilla.fields() returns
:actual_time => :actual_time,
:flags => :flags,
}
module ClassMethods
def attributes_xmlrpc_map
@attributes_xmlrpc_map ||= begin
hash = generate_xmlrpc_map
define_attributes(hash.keys)
hash
end
end
def xmlrpc_timestamps
@xmlrpc_timestamps ||= fields.select(&:timestamp?).collect { |field| field.name.to_sym }
end
def default_service_attributes
attributes_xmlrpc_map.values - [:comments]
end
def normalize_attributes_to_service(hash)
attributes_xmlrpc_map.each do |bug_key, xmlrpc_key|
bug_key = bug_key.to_sym
xmlrpc_key = xmlrpc_key.to_sym
next if bug_key == xmlrpc_key
hash[xmlrpc_key] = hash.delete(bug_key)
end
hash[:include_fields] = normalize_include_fields_to_service(hash[:include_fields]) if hash.key?(:include_fields)
hash.delete_if { |k, v| v.nil? }
hash
end
def normalize_attributes_from_service(hash)
attributes_xmlrpc_map.each do |bug_key, xmlrpc_key|
next unless hash.key?(xmlrpc_key.to_s)
value = hash.delete(xmlrpc_key.to_s)
value = normalize_timestamp(value) if xmlrpc_timestamps.include?(xmlrpc_key)
hash[bug_key] = value
end
hash
end
def attribute_names
@attribute_names ||= attributes_xmlrpc_map.keys.sort_by { |sym| sym.to_s }
end
def search(options = {})
options = normalize_attributes_to_service(options)
service.search(options).collect do |bug_hash|
normalize_attributes_from_service(bug_hash)
end
end
private
def fetch_fields
service.fields
end
def generate_xmlrpc_map
hash = ATTRIBUTES_XMLRPC_RENAMES_MAP
fields.each do |field|
next if hash.values.include?(field.name)
next if field.name.include?(".")
attribute_name = field.name
attribute_name = attribute_name[3..-1] if attribute_name[0..2] == "cf_"
hash[attribute_name.to_sym] = field.name.to_sym
end
hash
end
def normalize_include_fields_to_service(include_fields)
include_fields.collect do |bug_key|
attributes_xmlrpc_map[bug_key]
end.uniq.compact
end
def define_attributes(names)
define_attribute_methods names
names.each do |name|
next if name.to_s == 'flags' # Flags is a special attribute
ivar_name = "@#{name}"
define_method(name) do
return instance_variable_get(ivar_name) if instance_variable_defined?(ivar_name)
instance_variable_set(ivar_name, raw_attribute(name))
end
define_method("#{name}=") do |val|
public_send("#{name}_will_change!") unless val == instance_variable_get(ivar_name)
instance_variable_set(ivar_name, val)
end
end
end
end
def attribute_names
self.class.attribute_names
end
private
def service
self.class.service
end
def raw_reset
@raw_data = nil
@raw_comments = nil
@raw_flags = nil
@raw_attributes = nil
end
def raw_update(attributes)
attributes = self.class.normalize_attributes_to_service(attributes)
result = service.update(@id, attributes).first
id = result['id']
raise "Error - Expected to update id <#{@id}>, but updated <#{id}>" unless id == @id
result
end
def raw_data
@raw_data ||= service.get(@id, :include_fields => self.class.default_service_attributes).first
end
def raw_flags
@raw_flags ||= raw_attribute('flags')
end
def raw_comments
@raw_comments ||= (raw_attributes['comments'] || fetch_comments)
end
def raw_attributes
@raw_attributes ||= self.class.normalize_attributes_from_service(raw_data)
end
def raw_attribute_set(key, value)
raw_attributes
@raw_attributes[key] = value
end
def raw_attribute(key)
raw_attribute_set(key, fetch_attribute(key)) unless raw_attributes.key?(key)
raw_attributes[key]
end
def fetch_comments
service.comments(:ids => @id)['bugs'][@id.to_s]['comments']
end
def fetch_attribute(key)
service.get(@id, :include_fields => [key]).first[key]
end
end