culturecode_stagehand 1.1.2 → 1.1.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fc5e551f7e747ad8fb67d445f787bd47df6059fbe939f65088901445e4ccc5db
4
- data.tar.gz: d7d1a28bdac8a210119431075d48fa5cfafaadf311958926e13e10ac5c5dda9c
3
+ metadata.gz: b9684506c931ca15ad9c467e5d96fb359ede46c3d41624331b72b7efe0b7b850
4
+ data.tar.gz: 43f4509740eb53ace3293ad6bdbd718562e165adf282e1ca2114c5daebd5ee15
5
5
  SHA512:
6
- metadata.gz: d73461a90dceed0855d2779925174f1ced0b4ba9a2a9b47c0948fa1faef6666eb5ee83af52481114033a99367747baf82b1161617ff73c30721c19dfedf5e28e
7
- data.tar.gz: 3a2443903c414b6f87ccb312d77b165428e036ae80bc04a103234a7efc373d5068f9f329d8c87c987a9e1605929237053e5b276de1dedd79860028e3fb9bc5a4
6
+ metadata.gz: 5cca6f14c6f8c9194d400a5c21bb49f90758e2160a9ebac99b72621f8b64410f91429a5b6f3ba62db4faf92d7d50caf1caee66a4d5631ccf4ac196206677130c
7
+ data.tar.gz: 28f4439a34ed046edff565df691fd4d1fada3e227a52a9fc3d60fec9b245db8d0a0c4e50629ab86febc7e5d0171c270b7257ee4121b0b5517296f6fb152b4eb6
@@ -6,7 +6,7 @@ module Stagehand
6
6
  def initialize(checklist, show_all_commits: false)
7
7
  entries = checklist.affected_entries.select(&:commit_id)
8
8
 
9
- @graph = GraphViz.new( :G, :type => :graph );
9
+ @graph = GraphViz.new( :G, :type => :graph )
10
10
  @commits = Hash.new {|hash, commit_id| hash[commit_id] = Stagehand::Staging::CommitEntry.find(commit_id) }
11
11
  nodes = Hash.new
12
12
  edges = []
@@ -24,16 +24,22 @@ module Stagehand
24
24
 
25
25
  # Create Subgraph nodes for commits with connections to other subjects
26
26
  entries = edges.flatten.uniq unless show_all_commits
27
- entries.group_by {|entry| commit_subject(entry) }.each do |subject, entries|
28
- subgraph = create_subgraph(subject, @graph)
27
+ entries.group_by {|entry| commit_subject(entry) || entry.commit_id }.each do |group, entries|
28
+ subject = commit_subject(entries.first)
29
+ subgraph = create_subgraph(subject, @graph, id: group)
29
30
  entries.each do |entry|
30
31
  nodes[entry] = create_node(entry, subgraph)
31
32
  end
32
33
  end
33
34
 
35
+ # Create deduplicate edge data in case multiple entries for the same record were part of a single commit
36
+ edges = edges.map do |entry_a, entry_b|
37
+ [[nodes[entry_a], nodes[entry_b]], label: edge_label(entry_a, entry_b)]
38
+ end
39
+
34
40
  # Create edges
35
- edges.each do |entry_a, entry_b|
36
- create_edge(nodes[entry_a], nodes[entry_b], :label => edge_label(entry_a, entry_b))
41
+ edges.uniq.each do |(node_a, node_b), options|
42
+ create_edge(node_a, node_b, options)
37
43
  end
38
44
  end
39
45
 
@@ -44,8 +50,8 @@ module Stagehand
44
50
 
45
51
  private
46
52
 
47
- def create_subgraph(subject, graph)
48
- graph.add_graph("cluster_#{subject}", :label => subject, :style => :filled, :color => :lightgrey)
53
+ def create_subgraph(subject, graph, id: subject)
54
+ graph.add_graph("cluster_#{id}", :label => subject, :style => :filled, :color => :lightgrey)
49
55
  end
50
56
 
51
57
  def create_edge(node_a, node_b, options = {})
@@ -65,7 +71,7 @@ module Stagehand
65
71
  end
66
72
 
67
73
  def same_subject?(entry_a, entry_b)
68
- commit_subject(entry_a) == commit_subject(entry_b)
74
+ commit_subject(entry_a) == commit_subject(entry_b) && commit_subject(entry_a)
69
75
  end
70
76
 
71
77
  def commit_subject(entry)
@@ -77,7 +83,7 @@ module Stagehand
77
83
  end
78
84
 
79
85
  def pretty_key(entry)
80
- "#{entry.table_name.classify} #{entry.record_id}"
86
+ "#{entry.table_name.classify} #{entry.record_id}" if entry.record_id && entry.table_name
81
87
  end
82
88
  end
83
89
  end
@@ -9,7 +9,8 @@ module Stagehand
9
9
  module Configuration
10
10
  extend self
11
11
 
12
- mattr_accessor :checklist_confirmation_filter, :checklist_association_filter, :checklist_relation_filter
12
+ mattr_accessor :checklist_confirmation_filter, :checklist_association_filter, :checklist_relation_filter, :ignored_columns
13
+ self.ignored_columns = HashWithIndifferentAccess.new
13
14
 
14
15
  def staging_connection_name
15
16
  Rails.env.to_sym
@@ -33,5 +34,11 @@ module Stagehand
33
34
  def single_connection?
34
35
  staging_connection_name == production_connection_name
35
36
  end
37
+
38
+ # Columns not to copy to the production database
39
+ # e.g. table_name => [column, column, ...]
40
+ def self.ignored_columns=(hash)
41
+ super HashWithIndifferentAccess.new(hash)
42
+ end
36
43
  end
37
44
  end
@@ -1,15 +1,22 @@
1
1
  module Stagehand
2
2
  module Connection
3
- def self.with_production_writes(model, &block)
4
- model.connection.allow_writes(&block)
3
+ def self.with_production_writes(&block)
4
+ state = allow_unsynced_production_writes?
5
+ allow_unsynced_production_writes!(true)
6
+ return block.call
7
+ ensure
8
+ allow_unsynced_production_writes!(state)
5
9
  end
6
10
 
7
- module AdapterExtensions
8
- def self.prepended(base)
9
- base.set_callback :checkout, :after, :update_readonly_state
10
- base.set_callback :checkin, :before, :clear_readonly_state
11
- end
11
+ def self.allow_unsynced_production_writes!(state = true)
12
+ Thread.current[:stagehand_allow_unsynced_production_writes] = state
13
+ end
12
14
 
15
+ def self.allow_unsynced_production_writes?
16
+ !!Thread.current[:stagehand_allow_unsynced_production_writes]
17
+ end
18
+
19
+ module AdapterExtensions
13
20
  def exec_insert(*)
14
21
  handle_readonly_writes!
15
22
  super
@@ -25,34 +32,14 @@ module Stagehand
25
32
  super
26
33
  end
27
34
 
28
- def allow_writes(&block)
29
- state = readonly?
30
- readonly!(false)
31
- return block.call
32
- ensure
33
- readonly!(state)
34
- end
35
-
36
- def readonly!(state = true)
37
- @readonly = state
38
- end
39
-
40
- def readonly?
41
- !!@readonly
42
- end
43
-
44
35
  private
45
36
 
46
- def update_readonly_state
47
- readonly! unless Configuration.single_connection? || @config[:database] == Database.staging_database_name
48
- end
49
-
50
- def clear_readonly_state
51
- readonly!(false)
37
+ def write_access?
38
+ Configuration.single_connection? || @config[:database] == Database.staging_database_name || Connection.allow_unsynced_production_writes?
52
39
  end
53
40
 
54
41
  def handle_readonly_writes!
55
- if !readonly?
42
+ if write_access?
56
43
  return
57
44
  elsif Configuration.allow_unsynced_production_writes?
58
45
  Rails.logger.warn "Writing directly to #{@config[:database]} database using readonly connection"
@@ -24,7 +24,7 @@ module Stagehand
24
24
  end
25
25
 
26
26
  def write(staging_record, attributes, table_name = nil)
27
- Connection.with_production_writes(Record) do
27
+ Connection.with_production_writes do
28
28
  is_new = matching(staging_record, table_name).update_all(attributes).zero?
29
29
 
30
30
  # Ensure we always return a record, even when updating instead of creating
@@ -37,7 +37,7 @@ module Stagehand
37
37
  end
38
38
 
39
39
  def delete(staging_record, table_name = nil)
40
- Connection.with_production_writes(Record) do
40
+ Connection.with_production_writes do
41
41
  matching(staging_record, table_name).delete_all
42
42
  end
43
43
  end
@@ -78,7 +78,12 @@ module Stagehand
78
78
 
79
79
  def staging_record_attributes(staging_record, table_name = nil)
80
80
  table_name, id = Stagehand::Key.generate(staging_record, :table_name => table_name)
81
- Stagehand::Staging::CommitEntry.connection.select_one("SELECT * FROM #{table_name} WHERE id = #{id}")
81
+ hash = Stagehand::Staging::CommitEntry.connection.select_one("SELECT * FROM #{table_name} WHERE id = #{id}")
82
+ hash&.except(*ignored_columns(table_name))
83
+ end
84
+
85
+ def ignored_columns(table_name)
86
+ Array.wrap(Configuration.ignored_columns[table_name]).map(&:to_s)
82
87
  end
83
88
 
84
89
  # CLASSES
@@ -2,7 +2,7 @@ module Stagehand
2
2
  module SchemaExtensions
3
3
  def define(*)
4
4
  # Allow production writes during Schema.define to allow Rails to write to ar_internal_metadata table
5
- Stagehand::Connection.with_production_writes(ActiveRecord::Base) { super }
5
+ Stagehand::Connection.with_production_writes { super }
6
6
  end
7
7
  end
8
8
  end
@@ -89,7 +89,20 @@ module Stagehand
89
89
  private
90
90
 
91
91
  def self.associated_associations(klass)
92
- cache("#{klass.name}_associated_associations") { klass.reflect_on_all_associations(:belongs_to).collect(&:name) }
92
+ cache("#{klass.name}_associated_associations") do
93
+ reflections = klass.reflect_on_all_associations(:belongs_to)
94
+
95
+ reflections.select! do |reflection|
96
+ begin
97
+ reflection.check_preloadable!
98
+ next true
99
+ rescue ArgumentError
100
+ next false
101
+ end
102
+ end
103
+
104
+ reflections.collect(&:name)
105
+ end
93
106
  end
94
107
 
95
108
  def self.stagehand_class?(klass)
@@ -1,3 +1,3 @@
1
1
  module Stagehand
2
- VERSION = "1.1.2"
2
+ VERSION = "1.1.5"
3
3
  end
@@ -20,7 +20,7 @@ namespace :stagehand do
20
20
  def rake_both_databases(task, stagehand_task = task.gsub(':','_'))
21
21
  task(stagehand_task => :environment) do
22
22
  Stagehand::Database.each do |connection_name|
23
- Stagehand::Connection.with_production_writes(ActiveRecord::Base) do
23
+ Stagehand::Connection.with_production_writes do
24
24
  puts "#{connection_name}"
25
25
  Rake::Task[task].reenable
26
26
  Rake::Task[task].invoke
@@ -35,4 +35,5 @@ namespace :stagehand do
35
35
 
36
36
  rake_both_databases('db:migrate')
37
37
  rake_both_databases('db:rollback')
38
+ rake_both_databases('db:test:load_structure')
38
39
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: culturecode_stagehand
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.2
4
+ version: 1.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nicholas Jakobsen
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2019-08-15 00:00:00.000000000 Z
12
+ date: 2020-06-29 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails