hairtrigger 0.2.21 → 0.2.25

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
- 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