hairtrigger 0.2.19 → 0.2.24

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
  SHA1:
3
- metadata.gz: f42f7d04b773f6a0ce1f5acc86e90746f35322b1
4
- data.tar.gz: d05ccf70ece346e5e73ed4433e11dc678c0bd6e9
3
+ metadata.gz: b3a4b255f8184decc442a9c455f5b8a5a5c9bd48
4
+ data.tar.gz: b6c202c7328de121c67161cc4d31d83926076044
5
5
  SHA512:
6
- metadata.gz: 5d78e2251de79e05fdd17f1194b7f3ac7afd1711bd5cd5a40fd0205f39f4f884ca63839152e45d3a70bc60c50f2210fef4a9a6ff72e736ba05c69f0d78bda570
7
- data.tar.gz: 970c56031d52a6ad9f355e97dcad81f877ccf806a9bc4a7d6d1a659b5a5e0c04cc9505251be5982a126e625e227859c99217c3ef140678a889915a0a8f806ca2
6
+ metadata.gz: 5eb6f48db749f2841ee9a0b986dbaf9cf2d93f48f687822e8a6dda52c90e45165fba783510e7fb1e5ec8a490ce4a6dd58df5f2ebd04567e3d2839f87ef82815f
7
+ data.tar.gz: c8eebfc8a7a45d4987f1d6ea5281a06c333a4eee929830a73a78521c442983b1743f14a4f677fb31de9d4a7ce6b144f67000f84cd7c068d08160ef260bb815cf
data/README.md CHANGED
@@ -7,8 +7,15 @@ and a simple rake task does all the dirty work for you.
7
7
 
8
8
  ## Installation
9
9
 
10
- If you are using Rails 3 or beyond, just add `gem 'hairtrigger'` to your
11
- Gemfile. For Rails 2, it's [slightly more involved](RAILS2.md)
10
+ HairTrigger works with Rails 5.0 onwards. Add the following line to your Gemfile:
11
+
12
+ ```ruby
13
+ gem 'hairtrigger'
14
+ ```
15
+
16
+ Then run `bundle install`
17
+
18
+ For older versions of Rails check the last [0.2 release](https://github.com/jenseng/hair_trigger/tree/v0.2.21)
12
19
 
13
20
  ## Usage
14
21
 
@@ -248,7 +255,7 @@ create.
248
255
 
249
256
  ## Warnings and Errors
250
257
 
251
- There are a couple classes of errors: declaration errors and generation
258
+ There are a couple classes of errors: declaration errors and generation
252
259
  errors/warnings.
253
260
 
254
261
  Declaration errors happen if your trigger declaration is obviously wrong, and
@@ -313,10 +320,26 @@ existing trigger if you wish to redefine it.
313
320
  * Manual `create_trigger` statements have some gotchas. See the section
314
321
  "Manual triggers and :compatibility"
315
322
 
323
+ ## Contributing
324
+
325
+ Contributions welcome! I don't write much Ruby these days 😢 (and haven't used this
326
+ gem in years 😬) but am happy to take contributions. If I'm slow to respond, don't
327
+ hesitate to @ me repeatedly, sometimes those github notifications slip through
328
+ the cracks. 😆.
329
+
330
+ If you want to add a feature/bugfix, you can rely on Travis to run the tests, but
331
+ do also run them locally (especially if you are changing supported railses/etc).
332
+ HairTrigger uses [appraisal](https://github.com/thoughtbot/appraisal) to manage all
333
+ that w/ automagical gemfiles. So the tl;dr when testing locally is:
334
+
335
+ 1. make sure you have mysql and postgres installed (homebrew or whatever)
336
+ 2. `bundle exec appraisal install` -- get all the dependencies
337
+ 3. `bundle exec appraisal rake` -- run the specs every which way
338
+
316
339
  ## Compatibility
317
340
 
318
- * Ruby 1.8.7+
319
- * Rails 2.3+
341
+ * Ruby 2.3.0+
342
+ * Rails 5.0+
320
343
  * PostgreSQL 8.0+
321
344
  * MySQL 5.0.10+
322
345
  * SQLite 3.3.8+
@@ -325,4 +348,4 @@ existing trigger if you wish to redefine it.
325
348
 
326
349
  ## Copyright
327
350
 
328
- Copyright (c) 2011-2015 Jon Jensen. See LICENSE.txt for further details.
351
+ Copyright (c) 2011-2021 Jon Jensen. See LICENSE.txt for further details.
@@ -1,4 +1,5 @@
1
1
  require 'ostruct'
2
+ require 'fileutils'
2
3
  require 'active_record'
3
4
  require 'hair_trigger/base'
4
5
  require 'hair_trigger/migrator'
@@ -21,7 +22,7 @@ module HairTrigger
21
22
  end
22
23
 
23
24
  def models
24
- if defined?(Rails) && Rails::VERSION::MAJOR > 2
25
+ if defined?(Rails)
25
26
  Rails.application.eager_load!
26
27
  else
27
28
  Dir[model_path + '/*rb'].each do |model|
@@ -34,16 +35,24 @@ module HairTrigger
34
35
  end
35
36
  end
36
37
  end
37
- ActiveRecord::VERSION::STRING < "3.0." ?
38
- ActiveRecord::Base.send(:subclasses) :
39
- ActiveRecord::Base.descendants
38
+ ActiveRecord::Base.descendants
40
39
  end
41
40
 
42
41
  def migrator
43
- migrations = ActiveRecord::VERSION::STRING >= "4.0." ?
44
- ActiveRecord::Migrator.migrations(migration_path) :
45
- migration_path
46
- ActiveRecord::Migrator.new(:up, migrations)
42
+ version = ActiveRecord::VERSION::STRING
43
+ if version >= "6.0."
44
+ migrations = ActiveRecord::MigrationContext.new(migration_path, ActiveRecord::SchemaMigration).migrations
45
+ elsif version >= "5.2."
46
+ migrations = ActiveRecord::MigrationContext.new(migration_path).migrations
47
+ else # version >= "4.0."
48
+ migrations = ActiveRecord::Migrator.migrations(migration_path)
49
+ end
50
+
51
+ if version >= "6.0."
52
+ ActiveRecord::Migrator.new(:up, migrations, ActiveRecord::SchemaMigration)
53
+ else
54
+ ActiveRecord::Migrator.new(:up, migrations)
55
+ end
47
56
  end
48
57
 
49
58
  def current_migrations(options = {})
@@ -52,7 +61,7 @@ module HairTrigger
52
61
  options[:schema_rb_first] = true
53
62
  options[:skip_pending_migrations] = true
54
63
  end
55
-
64
+
56
65
  # if we're in a db:schema:dump task (explict or kicked off by db:migrate),
57
66
  # we evaluate the previous schema.rb (if it exists), and then all applied
58
67
  # migrations in order (even ones older than schema.rb). this ensures we
@@ -69,7 +78,7 @@ module HairTrigger
69
78
  triggers = MigrationReader.get_triggers(migration, options)
70
79
  migrations << [migration, triggers] unless triggers.empty?
71
80
  end
72
-
81
+
73
82
  if previous_schema = (options.has_key?(:previous_schema) ? options[:previous_schema] : File.exist?(schema_rb_path) && File.read(schema_rb_path))
74
83
  base_triggers = MigrationReader.get_triggers(previous_schema, options)
75
84
  unless base_triggers.empty?
@@ -77,9 +86,9 @@ module HairTrigger
77
86
  migrations.unshift [OpenStruct.new({:version => version}), base_triggers]
78
87
  end
79
88
  end
80
-
89
+
81
90
  migrations = migrations.sort_by{|(migration, triggers)| migration.version} unless options[:schema_rb_first]
82
-
91
+
83
92
  all_builders = []
84
93
  migrations.each do |(migration, triggers)|
85
94
  triggers.each do |new_trigger|
@@ -90,7 +99,7 @@ module HairTrigger
90
99
  all_builders << [migration.name, new_trigger] unless new_trigger.options[:drop]
91
100
  end
92
101
  end
93
-
102
+
94
103
  all_builders
95
104
  end
96
105
 
@@ -101,27 +110,27 @@ module HairTrigger
101
110
  def generate_migration(silent = false)
102
111
  begin
103
112
  canonical_triggers = current_triggers
104
- rescue
113
+ rescue
105
114
  $stderr.puts $!
106
115
  exit 1
107
116
  end
108
-
117
+
109
118
  migrations = current_migrations
110
119
  migration_names = migrations.map(&:first)
111
120
  existing_triggers = migrations.map(&:last)
112
-
121
+
113
122
  up_drop_triggers = []
114
123
  up_create_triggers = []
115
124
  down_drop_triggers = []
116
125
  down_create_triggers = []
117
-
126
+
118
127
  # see which triggers need to be dropped
119
128
  existing_triggers.each do |existing|
120
129
  next if canonical_triggers.any?{ |t| t.prepared_name == existing.prepared_name }
121
130
  up_drop_triggers.concat existing.drop_triggers
122
131
  down_create_triggers << existing
123
132
  end
124
-
133
+
125
134
  # see which triggers need to be added/replaced
126
135
  (canonical_triggers - existing_triggers).each do |new_trigger|
127
136
  up_create_triggers << new_trigger
@@ -134,28 +143,28 @@ module HairTrigger
134
143
  down_create_triggers << existing
135
144
  end
136
145
  end
137
-
146
+
138
147
  return if up_drop_triggers.empty? && up_create_triggers.empty?
139
148
 
140
149
  migration_name = infer_migration_name(migration_names, up_create_triggers, up_drop_triggers)
141
150
  migration_version = infer_migration_version(migration_name)
142
151
  file_name = migration_path + '/' + migration_version + "_" + migration_name.underscore + ".rb"
143
- prefix = ActiveRecord::VERSION::STRING < "3.1." ? "self." : ""
144
- File.open(file_name, "w"){ |f| f.write <<-MIGRATION }
152
+ FileUtils.mkdir_p migration_path
153
+ File.open(file_name, "w") { |f| f.write <<-RUBY }
145
154
  # This migration was auto-generated via `rake db:generate_trigger_migration'.
146
155
  # While you can edit this file, any changes you make to the definitions here
147
156
  # will be undone by the next auto-generated trigger migration.
148
157
 
149
- class #{migration_name} < ActiveRecord::Migration
150
- def #{prefix}up
158
+ class #{migration_name} < ActiveRecord::Migration[#{ActiveRecord::Migration.current_version}]
159
+ def up
151
160
  #{(up_drop_triggers + up_create_triggers).map{ |t| t.to_ruby(' ') }.join("\n\n").lstrip}
152
161
  end
153
162
 
154
- def #{prefix}down
163
+ def down
155
164
  #{(down_drop_triggers + down_create_triggers).map{ |t| t.to_ruby(' ') }.join("\n\n").lstrip}
156
165
  end
157
166
  end
158
- MIGRATION
167
+ RUBY
159
168
  file_name
160
169
  end
161
170
 
@@ -217,11 +226,9 @@ end
217
226
  end
218
227
  end
219
228
 
220
- ActiveRecord::Base.send :extend, HairTrigger::Base
221
- if ActiveRecord::VERSION::STRING < "4.1."
222
- ActiveRecord::Migrator.send :extend, HairTrigger::Migrator
223
- else
229
+ ActiveSupport.on_load(:active_record) do
230
+ ActiveRecord::Base.send :extend, HairTrigger::Base
224
231
  ActiveRecord::Migration.send :include, HairTrigger::Migrator
232
+ ActiveRecord::ConnectionAdapters::AbstractAdapter.class_eval { include HairTrigger::Adapter }
233
+ ActiveRecord::SchemaDumper.class_eval { include HairTrigger::SchemaDumper }
225
234
  end
226
- ActiveRecord::ConnectionAdapters::AbstractAdapter.class_eval { include HairTrigger::Adapter }
227
- ActiveRecord::SchemaDumper.class_eval { include HairTrigger::SchemaDumper }
@@ -137,22 +137,22 @@ module HairTrigger
137
137
  methods.each do |method|
138
138
  class_eval <<-METHOD, __FILE__, __LINE__ + 1
139
139
  alias #{method}_orig #{method}
140
- def #{method}(*args)
140
+ def #{method}(*args, &block)
141
141
  @chained_calls << :#{method}
142
142
  if @triggers || @trigger_group
143
143
  @errors << ["mysql doesn't support #{method} within a trigger group", :mysql] unless [:name, :where, :all, :of].include?(:#{method})
144
144
  end
145
- set_#{method}(*args, &(block_given? ? Proc.new : nil))
145
+ set_#{method}(*args, &(block_given? ? block : nil))
146
146
  end
147
- def set_#{method}(*args)
147
+ def set_#{method}(*args, &block)
148
148
  if @triggers # i.e. each time we say t.something within a trigger group block
149
149
  @chained_calls.pop # the subtrigger will get this, we don't need it
150
150
  @chained_calls = @chained_calls.uniq
151
151
  @triggers << trigger = clone
152
- trigger.#{method}(*args, &(block_given? ? Proc.new : nil))
152
+ trigger.#{method}(*args, &(block_given? ? block : nil))
153
153
  else
154
- #{method}_orig(*args)
155
- maybe_execute(&Proc.new) if block_given?
154
+ #{method}_orig(*args, &block)
155
+ maybe_execute(&block) if block_given?
156
156
  self
157
157
  end
158
158
  end
@@ -335,10 +335,11 @@ module HairTrigger
335
335
  block.call(self)
336
336
  raise DeclarationError, "trigger group did not define any triggers" if @triggers.empty?
337
337
  else
338
- @actions = block.call
339
- (@actions.is_a?(Hash) ? @actions.values : [@actions]).each do |actions|
340
- actions.sub!(/(\s*)\z/, ';\1') if actions && actions !~ /;\s*\z/
341
- end
338
+ @actions =
339
+ case (actions = block.call)
340
+ when Hash then actions.map { |key, action| [key, ensure_semicolon(action)] }.to_h
341
+ else ensure_semicolon(actions)
342
+ end
342
343
  end
343
344
  # only the top-most block actually executes
344
345
  if !@trigger_group
@@ -350,6 +351,10 @@ module HairTrigger
350
351
  self
351
352
  end
352
353
 
354
+ def ensure_semicolon(action)
355
+ action && action !~ /;\s*\z/ ? action.sub(/(\s*)\z/, ';\1') : action
356
+ end
357
+
353
358
  def validate_names!
354
359
  subtriggers = all_triggers(false)
355
360
  named_subtriggers = subtriggers.select{ |t| t.options[:name] }
@@ -427,7 +432,7 @@ END;
427
432
  raise GenerationError, "declare cannot be used in conjunction with nowrap" if options[:nowrap] && options[:declare]
428
433
  raise GenerationError, "security cannot be used in conjunction with nowrap" if options[:nowrap] && options[:security]
429
434
  raise GenerationError, "where can only be used in conjunction with nowrap on postgres 9.0 and greater" if options[:nowrap] && prepared_where && db_version < 90000
430
- raise GenerationError, "of can only be used in conjunction with nowrap on postgres 9.1 and greater" if options[:nowrap] && options[:of] && db_version < 91000
435
+ raise GenerationError, "of can only be used in conjunction with nowrap on postgres 9.1 and greater" if options[:nowrap] && options[:of] && db_version < 90100
431
436
 
432
437
  sql = ''
433
438
 
@@ -1,23 +1,25 @@
1
1
  module HairTrigger
2
2
  module Migrator
3
- def proper_table_name_with_hash_awareness(*args)
4
- name = args.first
5
- return name if name.is_a?(Hash)
6
- proper_table_name_without_hash_awareness(*args)
7
- end
8
-
9
3
  class << self
4
+ module ProperTableNameWithHashAwarenessSupport
5
+ def proper_table_name(*args)
6
+ name = args.first
7
+ return name if name.is_a?(Hash)
8
+ super
9
+ end
10
+ end
11
+
10
12
  def extended(base)
11
13
  base.class_eval do
12
14
  class << self
13
- alias_method_chain :proper_table_name, :hash_awareness
15
+ prepend ProperTableNameWithHashAwarenessSupport
14
16
  end
15
17
  end
16
18
  end
17
19
 
18
20
  def included(base)
19
21
  base.instance_eval do
20
- alias_method_chain :proper_table_name, :hash_awareness
22
+ prepend ProperTableNameWithHashAwarenessSupport
21
23
  end
22
24
  end
23
25
  end
@@ -1,13 +1,14 @@
1
1
  module HairTrigger
2
2
  module SchemaDumper
3
-
4
- def trailer_with_triggers(stream)
5
- orig_show_warnings = Builder.show_warnings
6
- Builder.show_warnings = false # we already show them when running the migration
7
- triggers(stream)
8
- trailer_without_triggers(stream)
9
- ensure
10
- Builder.show_warnings = orig_show_warnings
3
+ module TrailerWithTriggersSupport
4
+ def trailer(stream)
5
+ orig_show_warnings = Builder.show_warnings
6
+ Builder.show_warnings = false # we already show them when running the migration
7
+ triggers(stream)
8
+ super
9
+ ensure
10
+ Builder.show_warnings = orig_show_warnings
11
+ end
11
12
  end
12
13
 
13
14
  def triggers(stream)
@@ -54,7 +55,7 @@ module HairTrigger
54
55
  stream.puts " # no candidate create_trigger statement could be found, creating an adapter-specific one"
55
56
  end
56
57
  if definition =~ /\n/
57
- stream.print " execute(<<-TRIGGERSQL)\n#{definition.rstrip}\n TRIGGERSQL\n\n"
58
+ stream.print " execute(<<-SQL)\n#{definition.rstrip}\n SQL\n\n"
58
59
  else
59
60
  stream.print " execute(#{definition.inspect})\n\n"
60
61
  end
@@ -66,7 +67,7 @@ module HairTrigger
66
67
  def normalize_trigger(name, definition, type)
67
68
  @adapter_name = @connection.adapter_name.downcase.to_sym
68
69
 
69
- return definition unless @adapter_name == :postgresql
70
+ return definition unless @adapter_name == :postgresql || @adapter_name == :postgis
70
71
  # because postgres does not preserve the original CREATE TRIGGER/
71
72
  # FUNCTION statements, its decompiled reconstruction will not match
72
73
  # ours. we work around it by creating our generated trigger/function,
@@ -97,10 +98,9 @@ module HairTrigger
97
98
 
98
99
  def self.included(base)
99
100
  base.class_eval do
100
- alias_method_chain :trailer, :triggers
101
- class << self
102
- attr_accessor :previous_schema
103
- end
101
+ prepend TrailerWithTriggersSupport
102
+
103
+ class_attribute :previous_schema
104
104
  end
105
105
  end
106
106
  end
@@ -1,5 +1,5 @@
1
1
  module HairTrigger
2
- VERSION = "0.2.19"
2
+ VERSION = "0.2.24"
3
3
 
4
4
  def VERSION.<=>(other)
5
5
  split(/\./).map(&:to_i) <=> other.split(/\./).map(&:to_i)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hairtrigger
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.19
4
+ version: 0.2.24
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jon Jensen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-02-26 00:00:00.000000000 Z
11
+ date: 2021-02-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -16,42 +16,48 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '2.3'
19
+ version: '5.0'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '7'
20
23
  type: :runtime
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
23
26
  requirements:
24
27
  - - ">="
25
28
  - !ruby/object:Gem::Version
26
- version: '2.3'
29
+ version: '5.0'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '7'
27
33
  - !ruby/object:Gem::Dependency
28
34
  name: ruby_parser
29
35
  requirement: !ruby/object:Gem::Requirement
30
36
  requirements:
31
37
  - - "~>"
32
38
  - !ruby/object:Gem::Version
33
- version: '3.8'
39
+ version: '3.10'
34
40
  type: :runtime
35
41
  prerelease: false
36
42
  version_requirements: !ruby/object:Gem::Requirement
37
43
  requirements:
38
44
  - - "~>"
39
45
  - !ruby/object:Gem::Version
40
- version: '3.8'
46
+ version: '3.10'
41
47
  - !ruby/object:Gem::Dependency
42
48
  name: ruby2ruby
43
49
  requirement: !ruby/object:Gem::Requirement
44
50
  requirements:
45
51
  - - "~>"
46
52
  - !ruby/object:Gem::Version
47
- version: '2.3'
53
+ version: '2.4'
48
54
  type: :runtime
49
55
  prerelease: false
50
56
  version_requirements: !ruby/object:Gem::Requirement
51
57
  requirements:
52
58
  - - "~>"
53
59
  - !ruby/object:Gem::Version
54
- version: '2.3'
60
+ version: '2.4'
55
61
  description: allows you to declare database triggers in ruby in your models, and then
56
62
  generate appropriate migrations as they change
57
63
  email: jenseng@gmail.com
@@ -73,19 +79,6 @@ files:
73
79
  - lib/hair_trigger/version.rb
74
80
  - lib/hairtrigger.rb
75
81
  - lib/tasks/hair_trigger.rake
76
- - spec/adapter_spec.rb
77
- - spec/builder_spec.rb
78
- - spec/migrations-pre-3.1/20110331212003_initial_tables.rb
79
- - spec/migrations-pre-3.1/20110331212631_user_trigger.rb
80
- - spec/migrations-pre-3.1/20110417185102_manual_user_trigger.rb
81
- - spec/migrations/20110331212003_initial_tables.rb
82
- - spec/migrations/20110331212631_user_trigger.rb
83
- - spec/migrations/20110417185102_manual_user_trigger.rb
84
- - spec/migrations_spec.rb
85
- - spec/models/group.rb
86
- - spec/models/user.rb
87
- - spec/schema_dumper_spec.rb
88
- - spec/spec_helper.rb
89
82
  homepage: http://github.com/jenseng/hair_trigger
90
83
  licenses:
91
84
  - MIT
@@ -98,15 +91,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
98
91
  requirements:
99
92
  - - ">="
100
93
  - !ruby/object:Gem::Version
101
- version: 1.8.7
94
+ version: 2.3.0
102
95
  required_rubygems_version: !ruby/object:Gem::Requirement
103
96
  requirements:
104
97
  - - ">="
105
98
  - !ruby/object:Gem::Version
106
- version: 1.3.5
99
+ version: '0'
107
100
  requirements: []
108
101
  rubyforge_project:
109
- rubygems_version: 2.5.1
102
+ rubygems_version: 2.5.2.3
110
103
  signing_key:
111
104
  specification_version: 4
112
105
  summary: easy database triggers for active record