hairtrigger 0.2.21 → 0.2.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: f20c9f46678e0f212a8dddf861f0872609c4a519
4
- data.tar.gz: 3dd34ed254df8230ff6ffd32020be89d9b63c386
2
+ SHA256:
3
+ metadata.gz: 0537ad012af8bad34a62b81241c8517ac38fabeae279954e3e27ecc86e89cc9a
4
+ data.tar.gz: fe75190bc7fb5b8d2956929f5e72d2b48b0dbc81b5bdd27eac6fd48ccedf81cb
5
5
  SHA512:
6
- metadata.gz: a8db4cbe050c37d6aed248679e72770767e4b1b05812f8dc704ae2234e02ff5c7a8d38e3f4663ef23642b9c2aa3d39d18a813b73eb3f5ccc25cc24b5019170ca
7
- data.tar.gz: 827a7536fcee643bc4652a6cb7b073e13ab182b1b03f69bf80b63deb63f7618c6b564d3a91df5fa48acda4059f3e8c7eed03eb06510c79e4ed45d3aa7ffa6794
6
+ metadata.gz: f8df4419131442b648d2ed1a8315281e5d289638a228cf112882faacbcc27ebf5ca136474d1bf34d2b84e920187b23ec42365de67d1856112aa2449413571b52
7
+ data.tar.gz: 97193387286d4ed659612eca3d4d4a3266965f259a95c15494a627e494904d7a48c3b40a705455400aa5fb65bb90219a1485fd5494d8f006b472e8ac690eca6e
data/LICENSE.txt CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2011-2015 Jon Jensen
1
+ Copyright (c) 2011-2022 Jon Jensen
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
  # HairTrigger
2
- [<img src="https://secure.travis-ci.org/jenseng/hair_trigger.svg?branch=master" />](http://travis-ci.org/jenseng/hair_trigger)
2
+ [<img src="https://github.com/jenseng/hair_trigger/workflows/CI/badge.svg" />](https://github.com/jenseng/hair_trigger/actions?query=workflow%3ACI)
3
3
 
4
4
  HairTrigger lets you create and manage database triggers in a concise,
5
5
  db-agnostic, Rails-y way. You declare triggers right in your models in Ruby,
@@ -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
 
@@ -94,10 +101,10 @@ Only fire the update trigger if at least one of the columns is specified in the
94
101
  Permissions/role to check when calling trigger. PostgreSQL supports `:invoker` (default) and `:definer`, MySQL supports `:definer` (default) and arbitrary users (syntax: `'user'@'host'`).
95
102
 
96
103
  #### timing(timing)
97
- Required (but may be satisified by `before`/`after`). Possible values are `:before`/`:after`.
104
+ Required (but may be satisfied by `before`/`after`). Possible values are `:before`/`:after`.
98
105
 
99
106
  #### events(*events)
100
- Required (but may be satisified by `before`/`after`). Possible values are `:insert`/`:update`/`:delete`/`:truncate`. MySQL/SQLite only support one action per trigger, and don't support `:truncate`.
107
+ Required (but may be satisfied by `before`/`after`). Possible values are `:insert`/`:update`/`:delete`/`:truncate`. MySQL/SQLite only support one action per trigger, and don't support `:truncate`.
101
108
 
102
109
  #### nowrap(flag = true)
103
110
  PostgreSQL-specific option to prevent the trigger action from being wrapped in a `CREATE FUNCTION`. This is useful for executing existing triggers/functions directly, but is not compatible with the `security` setting nor can it be used with pre-9.0 PostgreSQL when supplying a `where` condition.
@@ -233,6 +240,21 @@ As long as you don't delete old migrations and schema.rb prior to running
233
240
  If you have deleted all trigger migrations, you can regenerate a new
234
241
  baseline for model triggers via `rake db:generate_trigger_migration`.
235
242
 
243
+ ### Filtering
244
+
245
+ It is possible to filter which triggers are dumped by setting any of these
246
+ configuration values:
247
+
248
+ ```ruby
249
+ HairTrigger::SchemaDumper::Configuration.ignore_triggers = 'exact_trigger_name'
250
+ HairTrigger::SchemaDumper::Configuration.ignore_tables = [/partial_/, 'exact_table_name']
251
+ HairTrigger::SchemaDumper::Configuration.allow_triggers = [/partial_/, 'exact_trigger_name']
252
+ HairTrigger::SchemaDumper::Configuration.allow_tables = 'exact_table_name'
253
+ ```
254
+
255
+ Each option can accept a single String or Regexp, or a mixed array of both.
256
+
257
+
236
258
  ## Testing
237
259
 
238
260
  To stay on top of things, it's strongly recommended that you add a test or
@@ -248,7 +270,7 @@ create.
248
270
 
249
271
  ## Warnings and Errors
250
272
 
251
- There are a couple classes of errors: declaration errors and generation
273
+ There are a couple classes of errors: declaration errors and generation
252
274
  errors/warnings.
253
275
 
254
276
  Declaration errors happen if your trigger declaration is obviously wrong, and
@@ -313,10 +335,26 @@ existing trigger if you wish to redefine it.
313
335
  * Manual `create_trigger` statements have some gotchas. See the section
314
336
  "Manual triggers and :compatibility"
315
337
 
338
+ ## Contributing
339
+
340
+ Contributions welcome! I don't write much Ruby these days 😢 (and haven't used this
341
+ gem in years 😬) but am happy to take contributions. If I'm slow to respond, don't
342
+ hesitate to @ me repeatedly, sometimes those github notifications slip through
343
+ the cracks. 😆.
344
+
345
+ If you want to add a feature/bugfix, you can rely on Github Actions to run the
346
+ tests, but do also run them locally (especially if you are changing supported
347
+ railses/etc). HairTrigger uses [appraisal](https://github.com/thoughtbot/appraisal)
348
+ to manage all that w/ automagical gemfiles. So the tl;dr when testing locally is:
349
+
350
+ 1. make sure you have mysql and postgres installed (homebrew or whatever)
351
+ 2. `bundle exec appraisal install` -- get all the dependencies
352
+ 3. `bundle exec appraisal rake` -- run the specs every which way
353
+
316
354
  ## Compatibility
317
355
 
318
- * Ruby 1.8.7+
319
- * Rails 2.3+
356
+ * Ruby 2.3.0+
357
+ * Rails 5.0+
320
358
  * PostgreSQL 8.0+
321
359
  * MySQL 5.0.10+
322
360
  * SQLite 3.3.8+
@@ -325,4 +363,4 @@ existing trigger if you wish to redefine it.
325
363
 
326
364
  ## Copyright
327
365
 
328
- Copyright (c) 2011-2017 Jon Jensen. See LICENSE.txt for further details.
366
+ Copyright (c) 2011-2022 Jon Jensen. See LICENSE.txt for further details.
@@ -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] }
@@ -1,5 +1,12 @@
1
1
  module HairTrigger
2
2
  module SchemaDumper
3
+ module Configuration
4
+ mattr_accessor :allow_tables
5
+ mattr_accessor :allow_triggers
6
+ mattr_accessor :ignore_tables
7
+ mattr_accessor :ignore_triggers
8
+ end
9
+
3
10
  module TrailerWithTriggersSupport
4
11
  def trailer(stream)
5
12
  orig_show_warnings = Builder.show_warnings
@@ -55,7 +62,7 @@ module HairTrigger
55
62
  stream.puts " # no candidate create_trigger statement could be found, creating an adapter-specific one"
56
63
  end
57
64
  if definition =~ /\n/
58
- stream.print " execute(<<-TRIGGERSQL)\n#{definition.rstrip}\n TRIGGERSQL\n\n"
65
+ stream.print " execute(<<-SQL)\n#{definition.rstrip}\n SQL\n\n"
59
66
  else
60
67
  stream.print " execute(#{definition.inspect})\n\n"
61
68
  end
@@ -67,7 +74,7 @@ module HairTrigger
67
74
  def normalize_trigger(name, definition, type)
68
75
  @adapter_name = @connection.adapter_name.downcase.to_sym
69
76
 
70
- return definition unless @adapter_name == :postgresql
77
+ return definition unless @adapter_name == :postgresql || @adapter_name == :postgis
71
78
  # because postgres does not preserve the original CREATE TRIGGER/
72
79
  # FUNCTION statements, its decompiled reconstruction will not match
73
80
  # ours. we work around it by creating our generated trigger/function,
@@ -91,17 +98,42 @@ module HairTrigger
91
98
  end
92
99
 
93
100
  def whitelist_triggers(triggers)
94
- triggers.reject do |name, source|
101
+ triggers = triggers.reject do |name, source|
95
102
  ActiveRecord::SchemaDumper.ignore_tables.any? { |ignored_table_name| source =~ /ON\s+#{@connection.quote_table_name(ignored_table_name)}\s/ }
96
103
  end
104
+
105
+ if Configuration.allow_tables.present?
106
+ triggers = triggers.select do |name, source|
107
+ Array(Configuration.allow_tables).any? { |allowed_table_name| source =~ /ON\s+#{@connection.quote_table_name(allowed_table_name)}\s/ }
108
+ end
109
+ end
110
+
111
+ if Configuration.allow_triggers.present?
112
+ triggers = triggers.select do |name, source|
113
+ Array(Configuration.allow_triggers).any? { |allowed_trigger_name| allowed_trigger_name === name } # Triple equals to allow regexps or strings as allowed_trigger_name
114
+ end
115
+ end
116
+
117
+ if Configuration.ignore_tables.present?
118
+ triggers = triggers.reject do |name, source|
119
+ Array(Configuration.ignore_tables).any? { |allowed_table_name| source =~ /ON\s+#{@connection.quote_table_name(allowed_table_name)}\s/ }
120
+ end
121
+ end
122
+
123
+ if Configuration.ignore_triggers.present?
124
+ triggers = triggers.reject do |name, source|
125
+ Array(Configuration.ignore_triggers).any? { |allowed_trigger_name| allowed_trigger_name === name } # Triple equals to allow regexps or strings as allowed_trigger_name
126
+ end
127
+ end
128
+
129
+ triggers
97
130
  end
98
131
 
99
132
  def self.included(base)
100
133
  base.class_eval do
101
134
  prepend TrailerWithTriggersSupport
102
- class << self
103
- attr_accessor :previous_schema
104
- end
135
+
136
+ class_attribute :previous_schema
105
137
  end
106
138
  end
107
139
  end
@@ -1,5 +1,5 @@
1
1
  module HairTrigger
2
- VERSION = "0.2.21"
2
+ VERSION = "0.2.25"
3
3
 
4
4
  def VERSION.<=>(other)
5
5
  split(/\./).map(&:to_i) <=> other.split(/\./).map(&:to_i)
data/lib/hair_trigger.rb CHANGED
@@ -22,7 +22,7 @@ module HairTrigger
22
22
  end
23
23
 
24
24
  def models
25
- if defined?(Rails) && Rails::VERSION::MAJOR > 2
25
+ if defined?(Rails)
26
26
  Rails.application.eager_load!
27
27
  else
28
28
  Dir[model_path + '/*rb'].each do |model|
@@ -35,22 +35,24 @@ module HairTrigger
35
35
  end
36
36
  end
37
37
  end
38
- ActiveRecord::VERSION::STRING < "3.0." ?
39
- ActiveRecord::Base.send(:subclasses) :
40
- ActiveRecord::Base.descendants
38
+ ActiveRecord::Base.descendants
41
39
  end
42
40
 
43
41
  def migrator
44
42
  version = ActiveRecord::VERSION::STRING
45
- if version >= "5.2."
43
+ if version >= "6.0."
44
+ migrations = ActiveRecord::MigrationContext.new(migration_path, ActiveRecord::SchemaMigration).migrations
45
+ elsif version >= "5.2."
46
46
  migrations = ActiveRecord::MigrationContext.new(migration_path).migrations
47
- elsif version < "4.0."
48
- migrations = migration_path
49
47
  else # version >= "4.0."
50
48
  migrations = ActiveRecord::Migrator.migrations(migration_path)
51
49
  end
52
50
 
53
- ActiveRecord::Migrator.new(:up, migrations)
51
+ if version >= "6.0."
52
+ ActiveRecord::Migrator.new(:up, migrations, ActiveRecord::SchemaMigration)
53
+ else
54
+ ActiveRecord::Migrator.new(:up, migrations)
55
+ end
54
56
  end
55
57
 
56
58
  def current_migrations(options = {})
@@ -59,8 +61,8 @@ module HairTrigger
59
61
  options[:schema_rb_first] = true
60
62
  options[:skip_pending_migrations] = true
61
63
  end
62
-
63
- # if we're in a db:schema:dump task (explict or kicked off by db:migrate),
64
+
65
+ # if we're in a db:schema:dump task (explicit or kicked off by db:migrate),
64
66
  # we evaluate the previous schema.rb (if it exists), and then all applied
65
67
  # migrations in order (even ones older than schema.rb). this ensures we
66
68
  # handle db:migrate:down scenarios correctly
@@ -76,7 +78,7 @@ module HairTrigger
76
78
  triggers = MigrationReader.get_triggers(migration, options)
77
79
  migrations << [migration, triggers] unless triggers.empty?
78
80
  end
79
-
81
+
80
82
  if previous_schema = (options.has_key?(:previous_schema) ? options[:previous_schema] : File.exist?(schema_rb_path) && File.read(schema_rb_path))
81
83
  base_triggers = MigrationReader.get_triggers(previous_schema, options)
82
84
  unless base_triggers.empty?
@@ -84,9 +86,9 @@ module HairTrigger
84
86
  migrations.unshift [OpenStruct.new({:version => version}), base_triggers]
85
87
  end
86
88
  end
87
-
89
+
88
90
  migrations = migrations.sort_by{|(migration, triggers)| migration.version} unless options[:schema_rb_first]
89
-
91
+
90
92
  all_builders = []
91
93
  migrations.each do |(migration, triggers)|
92
94
  triggers.each do |new_trigger|
@@ -97,7 +99,7 @@ module HairTrigger
97
99
  all_builders << [migration.name, new_trigger] unless new_trigger.options[:drop]
98
100
  end
99
101
  end
100
-
102
+
101
103
  all_builders
102
104
  end
103
105
 
@@ -108,27 +110,27 @@ module HairTrigger
108
110
  def generate_migration(silent = false)
109
111
  begin
110
112
  canonical_triggers = current_triggers
111
- rescue
113
+ rescue
112
114
  $stderr.puts $!
113
115
  exit 1
114
116
  end
115
-
117
+
116
118
  migrations = current_migrations
117
119
  migration_names = migrations.map(&:first)
118
120
  existing_triggers = migrations.map(&:last)
119
-
121
+
120
122
  up_drop_triggers = []
121
123
  up_create_triggers = []
122
124
  down_drop_triggers = []
123
125
  down_create_triggers = []
124
-
126
+
125
127
  # see which triggers need to be dropped
126
128
  existing_triggers.each do |existing|
127
129
  next if canonical_triggers.any?{ |t| t.prepared_name == existing.prepared_name }
128
130
  up_drop_triggers.concat existing.drop_triggers
129
131
  down_create_triggers << existing
130
132
  end
131
-
133
+
132
134
  # see which triggers need to be added/replaced
133
135
  (canonical_triggers - existing_triggers).each do |new_trigger|
134
136
  up_create_triggers << new_trigger
@@ -141,29 +143,28 @@ module HairTrigger
141
143
  down_create_triggers << existing
142
144
  end
143
145
  end
144
-
146
+
145
147
  return if up_drop_triggers.empty? && up_create_triggers.empty?
146
148
 
147
149
  migration_name = infer_migration_name(migration_names, up_create_triggers, up_drop_triggers)
148
150
  migration_version = infer_migration_version(migration_name)
149
151
  file_name = migration_path + '/' + migration_version + "_" + migration_name.underscore + ".rb"
150
152
  FileUtils.mkdir_p migration_path
151
- prefix = ActiveRecord::VERSION::STRING < "3.1." ? "self." : ""
152
- File.open(file_name, "w"){ |f| f.write <<-MIGRATION }
153
+ File.open(file_name, "w") { |f| f.write <<-RUBY }
153
154
  # This migration was auto-generated via `rake db:generate_trigger_migration'.
154
155
  # While you can edit this file, any changes you make to the definitions here
155
156
  # will be undone by the next auto-generated trigger migration.
156
157
 
157
- class #{migration_name} < ActiveRecord::Migration
158
- def #{prefix}up
158
+ class #{migration_name} < ActiveRecord::Migration[#{ActiveRecord::Migration.current_version}]
159
+ def up
159
160
  #{(up_drop_triggers + up_create_triggers).map{ |t| t.to_ruby(' ') }.join("\n\n").lstrip}
160
161
  end
161
162
 
162
- def #{prefix}down
163
+ def down
163
164
  #{(down_drop_triggers + down_create_triggers).map{ |t| t.to_ruby(' ') }.join("\n\n").lstrip}
164
165
  end
165
166
  end
166
- MIGRATION
167
+ RUBY
167
168
  file_name
168
169
  end
169
170
 
@@ -225,11 +226,9 @@ end
225
226
  end
226
227
  end
227
228
 
228
- ActiveRecord::Base.send :extend, HairTrigger::Base
229
- if ActiveRecord::VERSION::STRING < "4.1."
230
- ActiveRecord::Migrator.send :extend, HairTrigger::Migrator
231
- else
229
+ ActiveSupport.on_load(:active_record) do
230
+ ActiveRecord::Base.send :extend, HairTrigger::Base
232
231
  ActiveRecord::Migration.send :include, HairTrigger::Migrator
232
+ ActiveRecord::ConnectionAdapters::AbstractAdapter.class_eval { include HairTrigger::Adapter }
233
+ ActiveRecord::SchemaDumper.class_eval { include HairTrigger::SchemaDumper }
233
234
  end
234
- ActiveRecord::ConnectionAdapters::AbstractAdapter.class_eval { include HairTrigger::Adapter }
235
- ActiveRecord::SchemaDumper.class_eval { include HairTrigger::SchemaDumper }
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.21
4
+ version: 0.2.25
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jon Jensen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-08-08 00:00:00.000000000 Z
11
+ date: 2022-01-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -16,14 +16,20 @@ 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: '8'
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: '8'
27
33
  - !ruby/object:Gem::Dependency
28
34
  name: ruby_parser
29
35
  requirement: !ruby/object:Gem::Requirement
@@ -73,22 +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-3.2/20110331212003_initial_tables.rb
79
- - spec/migrations-3.2/20110331212631_user_trigger.rb
80
- - spec/migrations-3.2/20110417185102_manual_user_trigger.rb
81
- - spec/migrations-pre-3.1/20110331212003_initial_tables.rb
82
- - spec/migrations-pre-3.1/20110331212631_user_trigger.rb
83
- - spec/migrations-pre-3.1/20110417185102_manual_user_trigger.rb
84
- - spec/migrations/20110331212003_initial_tables.rb
85
- - spec/migrations/20110331212631_user_trigger.rb
86
- - spec/migrations/20110417185102_manual_user_trigger.rb
87
- - spec/migrations_spec.rb
88
- - spec/models/user.rb
89
- - spec/models/user_group.rb
90
- - spec/schema_dumper_spec.rb
91
- - spec/spec_helper.rb
92
82
  homepage: http://github.com/jenseng/hair_trigger
93
83
  licenses:
94
84
  - MIT
@@ -101,15 +91,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
101
91
  requirements:
102
92
  - - ">="
103
93
  - !ruby/object:Gem::Version
104
- version: 1.8.7
94
+ version: 2.3.0
105
95
  required_rubygems_version: !ruby/object:Gem::Requirement
106
96
  requirements:
107
97
  - - ">="
108
98
  - !ruby/object:Gem::Version
109
- version: 1.3.5
99
+ version: '0'
110
100
  requirements: []
111
- rubyforge_project:
112
- rubygems_version: 2.6.13
101
+ rubygems_version: 3.0.3
113
102
  signing_key:
114
103
  specification_version: 4
115
104
  summary: easy database triggers for active record
data/spec/adapter_spec.rb DELETED
@@ -1,94 +0,0 @@
1
- require 'spec_helper'
2
-
3
- # for this spec to work, you need to have postgres and mysql installed (in
4
- # addition to the gems), and you should make sure that you have set up
5
- # appropriate users and permissions. see database.yml for more info
6
-
7
- describe "adapter" do
8
- include_context "hairtrigger utils"
9
-
10
- describe ".triggers" do
11
- before do
12
- reset_tmp(:migration_glob => "*initial_tables*")
13
- initialize_db
14
- migrate_db
15
- end
16
-
17
- shared_examples_for "mysql" do
18
- # have to stub SHOW TRIGGERS to get back a '%' host, since GRANTs
19
- # and such get a little dicey for testing (local vs travis, etc.)
20
- it "matches the generated trigger with a '%' grant" do
21
- conn.instance_variable_get(:@config)[:host] = "somehost" # wheeeee!
22
- implicit_definer = "'root'@'somehost'"
23
- show_triggers_definer = "root@%"
24
-
25
- builder = trigger.on(:users).before(:insert){ "UPDATE foos SET bar = 1" }
26
- triggers = builder.generate.select{|t|t !~ /\ADROP/}
27
- expect(conn).to receive(:implicit_mysql_definer).and_return(implicit_definer)
28
- expect(conn).to receive(:select_rows).with("SHOW TRIGGERS").and_return([
29
- ['users_before_insert_row_tr', 'INSERT', 'users', "BEGIN\n UPDATE foos SET bar = 1;\nEND", 'BEFORE', 'NULL', 'STRICT_ALL_TABLES', show_triggers_definer]
30
- ])
31
-
32
- expect(db_triggers).to eq(triggers)
33
- end
34
-
35
- it "quotes table names" do
36
- conn.execute <<-SQL
37
- CREATE TRIGGER foos_tr AFTER DELETE ON users
38
- FOR EACH ROW
39
- BEGIN
40
- UPDATE user_groups SET bob_count = bob_count - 1;
41
- END
42
- SQL
43
-
44
- expect(conn.triggers["foos_tr"]).to match(/CREATE TRIGGER foos_tr AFTER DELETE ON `users`/)
45
- end
46
- end
47
-
48
- context "mysql" do
49
- let(:adapter) { :mysql }
50
- it_behaves_like "mysql"
51
- end if ADAPTERS.include? :mysql
52
-
53
- context "mysql2" do
54
- let(:adapter) { :mysql2 }
55
- it_behaves_like "mysql"
56
- end if ADAPTERS.include? :mysql2
57
-
58
- context "postgresql" do
59
- let(:adapter) { :postgresql }
60
-
61
- it "quotes table names" do
62
- conn.execute <<-SQL
63
- CREATE FUNCTION foos_tr()
64
- RETURNS TRIGGER AS $$
65
- BEGIN
66
- UPDATE user_groups SET bob_count = bob_count - 1;
67
- END;
68
- $$ LANGUAGE plpgsql;
69
-
70
- CREATE TRIGGER foos_tr AFTER DELETE ON users
71
- FOR EACH ROW EXECUTE PROCEDURE foos_tr();
72
- SQL
73
-
74
- expect(conn.triggers["foos_tr"]).to match(/CREATE TRIGGER foos_tr AFTER DELETE ON "users"/)
75
- end
76
- end
77
-
78
- context "sqlite3" do
79
- let(:adapter) { :sqlite3 }
80
-
81
- it "quotes table names" do
82
- conn.execute <<-SQL
83
- CREATE TRIGGER foos_tr AFTER DELETE ON users
84
- FOR EACH ROW
85
- BEGIN
86
- UPDATE user_groups SET bob_count = bob_count - 1;
87
- END;
88
- SQL
89
-
90
- expect(conn.triggers["foos_tr"]).to match(/CREATE TRIGGER foos_tr AFTER DELETE ON "users"/)
91
- end
92
- end
93
- end
94
- end