forked from paper-trail-gem/paper_trail
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix for issue paper-trail-gem#594, reifying sub-classed models that u…
…se STI
- Loading branch information
Showing
22 changed files
with
696 additions
and
91 deletions.
There are no files selected for viewing
This file contains 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
This file contains 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
2 changes: 1 addition & 1 deletion
2
lib/generators/paper_trail/USAGE → lib/generators/paper_trail/install/USAGE
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,2 @@ | ||
Description: | ||
Generates (but does not run) a migration to add a versions table. | ||
Generates (but does not run) a migration to add a versions table. See section 5.c. Generators in README.md for more information. |
This file contains 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
File renamed without changes.
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
# frozen_string_literal: true | ||
|
||
require "rails/generators" | ||
require "rails/generators/active_record" | ||
|
||
module PaperTrail | ||
# Basic structure to support a generator that builds a migration | ||
class MigrationGenerator < ::Rails::Generators::Base | ||
include ::Rails::Generators::Migration | ||
|
||
def self.next_migration_number(dirname) | ||
::ActiveRecord::Generators::Base.next_migration_number(dirname) | ||
end | ||
|
||
protected | ||
|
||
def add_paper_trail_migration(template, extra_options = {}) | ||
migration_dir = File.expand_path("db/migrate") | ||
if self.class.migration_exists?(migration_dir, template) | ||
::Kernel.warn "Migration already exists: #{template}" | ||
else | ||
migration_template( | ||
"#{template}.rb.erb", | ||
"db/migrate/#{template}.rb", | ||
{ migration_version: migration_version }.merge(extra_options) | ||
) | ||
end | ||
end | ||
|
||
def migration_version | ||
major = ActiveRecord::VERSION::MAJOR | ||
if major >= 5 | ||
"[#{major}.#{ActiveRecord::VERSION::MINOR}]" | ||
end | ||
end | ||
end | ||
end |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
Description: | ||
Generates (but does not run) a migration to update item_type for STI entries in an existing versions table. See section 5.c. Generators in README.md for more information. |
85 changes: 85 additions & 0 deletions
85
lib/generators/paper_trail/update_sti/templates/update_versions_for_sti.rb.erb
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
# This migration updates existing `versions` that have `item_type` that refers to | ||
# the base_class, and changes them to refer to the subclass instead. | ||
class UpdateVersionsForSti < ActiveRecord::Migration<%= migration_version %> | ||
include ActionView::Helpers::TextHelper | ||
def up | ||
<%= | ||
# Returns class, column, range | ||
def self.parse_custom_entry(text) | ||
parts = text.split("):") | ||
range = parts.last.split("..").map(&:to_i) | ||
range = Range.new(range.first, range.last) | ||
parts.first.split("(") + [range] | ||
end | ||
# Running: | ||
# rails g paper_trail:update_sti Animal(species):1..4 Plant(genus):42..1337 | ||
# results in: | ||
# # Versions of item_type "Animal" with IDs between 1 and 4 will be updated based on `species` | ||
# # Versions of item_type "Plant" with IDs between 42 and 1337 will be updated based on `genus` | ||
# hints = {"Animal"=>{1..4=>"species"}, "Plant"=>{42..1337=>"genus"}} | ||
hint_descriptions = "" | ||
hints = args.inject(Hash.new{|h, k| h[k] = {}}) do |s, v| | ||
klass, column, range = parse_custom_entry(v) | ||
hint_descriptions << " # Versions of item_type \"#{klass}\" with IDs between #{ | ||
range.first} and #{range.last} will be updated based on \`#{column}\`\n" | ||
s[klass][range] = column | ||
s | ||
end | ||
|
||
unless hints.empty? | ||
"#{hint_descriptions} hints = #{hints.inspect}\n" | ||
end | ||
%> | ||
# Find all ActiveRecord models mentioned in existing versions | ||
changes = Hash.new { |h, k| h[k] = [] } | ||
model_names = PaperTrail::Version.select(:item_type).distinct | ||
model_names.map(&:item_type).each do |model_name| | ||
hint = hints[model_name] if defined?(hints) | ||
begin | ||
klass = model_name.constantize | ||
# Actually implements an inheritance_column? (Usually "type") | ||
has_inheritance_column = klass.columns.map(&:name).include?(klass.inheritance_column) | ||
# Find domain of types stored in PaperTrail versions | ||
PaperTrail::Version.where(item_type: model_name).select(:id, :object, :object_changes).each do |obj| | ||
if (object_detail = PaperTrail.serializer.load(obj.object || obj.object_changes)) | ||
is_found = false | ||
type_name = nil | ||
hint&.each do |k, v| | ||
if k === obj.id && (type_name = object_detail[v]) | ||
break | ||
end | ||
end | ||
if type_name.nil? && has_inheritance_column | ||
type_name = object_detail[klass.inheritance_column] | ||
end | ||
if type_name | ||
type_name = type_name.last if type_name.is_a?(Array) | ||
if type_name != model_name | ||
changes[type_name] << obj.id | ||
end | ||
end | ||
end | ||
end | ||
rescue NameError => ex | ||
say "Skipping reference to #{model_name}", subitem: true | ||
end | ||
end | ||
changes.each do |k, v| | ||
# Update in blocks of up to 100 at a time | ||
block_of_ids = [] | ||
id_count = 0 | ||
num_updated = 0 | ||
v.sort.each do |id| | ||
block_of_ids << id | ||
if (id_count += 1) % 100 == 0 | ||
num_updated += PaperTrail::Version.where(id: block_of_ids).update_all(item_type: k) | ||
block_of_ids = [] | ||
end | ||
end | ||
num_updated += PaperTrail::Version.where(id: block_of_ids).update_all(item_type: k) | ||
if num_updated > 0 | ||
say "Associated #{pluralize(num_updated, 'record')} to #{k}", subitem: true | ||
end | ||
end | ||
end | ||
end |
17 changes: 17 additions & 0 deletions
17
lib/generators/paper_trail/update_sti/update_sti_generator.rb
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
# frozen_string_literal: true | ||
|
||
require_relative "../migration_generator" | ||
|
||
module PaperTrail | ||
# Updates STI entries for PaperTrail | ||
class UpdateStiGenerator < MigrationGenerator | ||
source_root File.expand_path("templates", __dir__) | ||
|
||
desc "Generates (but does not run) a migration to update item_type for STI entries in an "\ | ||
"existing versions table. See section 5.c. Generators in README.md for more information." | ||
|
||
def create_migration_file | ||
add_paper_trail_migration("update_versions_for_sti", sti_type_options: options) | ||
end | ||
end | ||
end |
This file contains 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
Oops, something went wrong.