2011-05-30 00:11:52 +04:00
|
|
|
#-- copyright
|
|
|
|
# ChiliProject is a project management system.
|
2011-05-30 22:52:25 +04:00
|
|
|
#
|
2011-05-30 00:11:52 +04:00
|
|
|
# Copyright (C) 2010-2011 the ChiliProject Team
|
2011-05-30 22:52:25 +04:00
|
|
|
#
|
2011-05-30 00:11:52 +04:00
|
|
|
# This program is free software; you can redistribute it and/or
|
|
|
|
# modify it under the terms of the GNU General Public License
|
|
|
|
# as published by the Free Software Foundation; either version 2
|
|
|
|
# of the License, or (at your option) any later version.
|
2011-05-30 22:52:25 +04:00
|
|
|
#
|
2011-05-30 00:11:52 +04:00
|
|
|
# See doc/COPYRIGHT.rdoc for more details.
|
|
|
|
#++
|
|
|
|
|
2011-05-13 20:55:55 +04:00
|
|
|
class GeneralizeJournals < ActiveRecord::Migration
|
|
|
|
def self.up
|
|
|
|
# This is provided here for migrating up after the JournalDetails has been removed
|
|
|
|
unless Object.const_defined?("JournalDetails")
|
|
|
|
Object.const_set("JournalDetails", Class.new(ActiveRecord::Base))
|
|
|
|
end
|
|
|
|
|
|
|
|
change_table :journals do |t|
|
|
|
|
t.rename :journalized_id, :journaled_id
|
|
|
|
t.rename :created_on, :created_at
|
|
|
|
|
|
|
|
t.integer :version, :default => 0, :null => false
|
|
|
|
t.string :activity_type
|
|
|
|
t.text :changes
|
|
|
|
t.string :type
|
|
|
|
|
|
|
|
t.index :journaled_id
|
|
|
|
t.index :activity_type
|
|
|
|
t.index :created_at
|
|
|
|
t.index :type
|
|
|
|
end
|
|
|
|
|
|
|
|
Journal.all.group_by(&:journaled_id).each_pair do |id, journals|
|
|
|
|
journals.sort_by(&:created_at).each_with_index do |j, idx|
|
|
|
|
j.update_attribute(:type, "#{j.journalized_type}Journal")
|
|
|
|
j.update_attribute(:version, idx + 1)
|
|
|
|
# FIXME: Find some way to choose the right activity here
|
|
|
|
j.update_attribute(:activity_type, j.journalized_type.constantize.activity_provider_options.keys.first)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
change_table :journals do |t|
|
|
|
|
t.remove :journalized_type
|
|
|
|
end
|
|
|
|
|
2011-06-04 00:01:56 +04:00
|
|
|
# Build initial journals for all activity providers
|
|
|
|
providers = Redmine::Activity.providers.collect {|k, v| v.collect(&:constantize) }.flatten.compact.uniq
|
|
|
|
providers.each do |p|
|
|
|
|
next unless p.table_exists? # Objects not in the DB yet need creation journal entries
|
|
|
|
p.find(:all).each do |o|
|
|
|
|
# Create initial journals
|
|
|
|
new_journal = o.journals.build
|
|
|
|
# Mock up a list of changes for the creation journal based on Class defaults
|
|
|
|
new_attributes = o.class.new.attributes.except(o.class.primary_key,
|
|
|
|
o.class.inheritance_column,
|
|
|
|
:updated_on,
|
|
|
|
:updated_at,
|
|
|
|
:lock_version,
|
|
|
|
:lft,
|
|
|
|
:rgt)
|
|
|
|
creation_changes = {}
|
|
|
|
new_attributes.each do |name, default_value|
|
|
|
|
# Set changes based on the initial value to current. Can't get creation value without
|
|
|
|
# rebuiling the object history
|
|
|
|
creation_changes[name] = [default_value, o.send(name)] # [initial_value, creation_value]
|
|
|
|
end
|
|
|
|
new_journal.changes = creation_changes
|
|
|
|
new_journal.version = 1
|
|
|
|
|
|
|
|
if o.respond_to?(:author)
|
|
|
|
new_journal.user = o.author
|
|
|
|
elsif o.respond_to?(:user)
|
|
|
|
new_journal.user = o.user
|
|
|
|
end
|
|
|
|
new_journal.save
|
|
|
|
|
|
|
|
# Backdate journal
|
|
|
|
if o.respond_to?(:created_at)
|
|
|
|
new_journal.update_attribute(:created_at, o.created_at)
|
|
|
|
elsif o.respond_to?(:created_on)
|
|
|
|
new_journal.update_attribute(:created_at, o.created_on)
|
|
|
|
end
|
|
|
|
p "Updating #{o}"
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
# Migrate journal changes now
|
2011-05-13 20:55:55 +04:00
|
|
|
JournalDetails.all.each do |detail|
|
|
|
|
journal = Journal.find(detail.journal_id)
|
|
|
|
changes = journal.changes || {}
|
|
|
|
if detail.property == 'attr' # Standard attributes
|
|
|
|
changes[detail.prop_key.to_s] = [detail.old_value, detail.value]
|
|
|
|
elsif detail.property == 'cf' # Custom fields
|
|
|
|
changes["custom_values_" + detail.prop_key.to_s] = [detail.old_value, detail.value]
|
|
|
|
elsif detail.property == 'attachment' # Attachment
|
|
|
|
changes["attachments_" + detail.prop_key.to_s] = [detail.old_value, detail.value]
|
|
|
|
end
|
|
|
|
journal.update_attribute(:changes, changes.to_yaml)
|
|
|
|
end
|
|
|
|
|
|
|
|
# drop_table :journal_details
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.down
|
|
|
|
# create_table "journal_details", :force => true do |t|
|
|
|
|
# t.integer "journal_id", :default => 0, :null => false
|
|
|
|
# t.string "property", :limit => 30, :default => "", :null => false
|
|
|
|
# t.string "prop_key", :limit => 30, :default => "", :null => false
|
|
|
|
# t.string "old_value"
|
|
|
|
# t.string "value"
|
|
|
|
# end
|
|
|
|
|
|
|
|
change_table "journals" do |t|
|
|
|
|
t.rename :journaled_id, :journalized_id
|
|
|
|
t.rename :created_at, :created_on
|
|
|
|
|
|
|
|
t.string :journalized_type, :limit => 30, :default => "", :null => false
|
|
|
|
end
|
|
|
|
|
|
|
|
custom_field_names = CustomField.all.group_by(&:type)[IssueCustomField].collect(&:name)
|
|
|
|
Journal.all.each do |j|
|
2011-05-13 21:20:34 +04:00
|
|
|
# Can't used j.journalized.class.name because the model changes make it nil
|
|
|
|
j.update_attribute(:journalized_type, j.type.to_s.sub("Journal","")) if j.type.present?
|
2011-05-13 20:55:55 +04:00
|
|
|
end
|
|
|
|
|
|
|
|
change_table "journals" do |t|
|
|
|
|
t.remove_index :journaled_id
|
|
|
|
t.remove_index :activity_type
|
|
|
|
t.remove_index :created_at
|
|
|
|
t.remove_index :type
|
|
|
|
|
|
|
|
t.remove :type
|
|
|
|
t.remove :version
|
|
|
|
t.remove :activity_type
|
|
|
|
t.remove :changes
|
|
|
|
end
|
|
|
|
|
|
|
|
# add_index "journal_details", ["journal_id"], :name => "journal_details_journal_id"
|
|
|
|
# add_index "journals", ["journalized_id", "journalized_type"], :name => "journals_journalized_id"
|
|
|
|
end
|
|
|
|
end
|