triggerhappy 0.0.6 → 0.1.0

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.
data/README CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  Library which adds SQL Triggers to Rails. Adds create_trigger and drop_trigger to the ActiveRecord::ConnectionAdapters::AbstractAdapter (which makes them available to migrations) and adds support for dumping triggers in the ActiveRecord::SchemaDumper.
4
4
 
5
+ Now supports creation / removal of stored procedures in migrations!
6
+
5
7
  == Installation
6
8
 
7
9
  To install:
@@ -69,4 +71,4 @@ If you find any issues please send an email to stewbawka@gmail.com .
69
71
 
70
72
  == Contributing
71
73
 
72
- If you would like to implement trigger support for other adapters then please drop me an email. Better yet, write up the adapter modifications and send them to me. :-)
74
+ If you would like to implement trigger support for other adapters then please drop me an email. Better yet, write up the adapter modifications and send them to me. :-)
@@ -0,0 +1,11 @@
1
+ # This is required for 1.1.6 support
2
+ class Module
3
+ def alias_method_chain(target, feature)
4
+ # Strip out punctuation on predicates or bang methods since
5
+ # e.g. target?_without_feature is not a valid method name.
6
+ aliased_target, punctuation = target.to_s.sub(/([?!=])$/, ''), $1
7
+ yield(aliased_target, punctuation) if block_given?
8
+ alias_method "#{aliased_target}_without_#{feature}#{punctuation}", target
9
+ alias_method target, "#{aliased_target}_with_#{feature}#{punctuation}"
10
+ end
11
+ end
@@ -12,5 +12,16 @@ module Triggerhappy
12
12
  @sql = sql
13
13
  end
14
14
  end
15
+
16
+ class ProcDefinition
17
+ attr_accessor :name, :sql
18
+
19
+ def initialize(base, name, sql)
20
+ @base = base
21
+ @name = name
22
+ @sql = sql
23
+ end
24
+ end
25
+
15
26
  end
16
- end
27
+ end
@@ -24,6 +24,31 @@ module Triggerhappy
24
24
  execute drop_sql
25
25
  end
26
26
  end
27
+
28
+ # Create a proc.
29
+ def create_proc(name, sql, options={})
30
+ if supports_procs?
31
+ proc_definition = ProcDefinition.new(self, name, sql)
32
+
33
+ if options[:force]
34
+ drop_proc(name) rescue nil
35
+ end
36
+
37
+ create_sql = "CREATE PROCEDURE "
38
+ create_sql << "#{name}"
39
+ create_sql << proc_definition.sql
40
+ execute create_sql
41
+ end
42
+ end
43
+
44
+ # Drop a proc.
45
+ def drop_proc(name, options={})
46
+ if supports_procs?
47
+ drop_sql = "DROP PROCEDURE #{name}"
48
+ execute drop_sql
49
+ end
50
+ end
51
+
27
52
  end
28
53
  end
29
- end
54
+ end
@@ -26,6 +26,21 @@ module ActiveRecord
26
26
  raise NotImplementedError, "trigger_events is an abstract method"
27
27
  end
28
28
 
29
+ # Subclasses should override and return true if they support procs.
30
+ def supports_procs?
31
+ return false
32
+ end
33
+
34
+ # Get a list of all procs for the current database
35
+ def procs(name = nil)
36
+ raise NotImplementedError, "procs is an abstract method"
37
+ end
38
+
39
+ # Get the code for the specified proc
40
+ def proc_code(proc, name=nil)
41
+ raise NotImplementedError, "proc_code is an abstract method"
42
+ end
43
+
29
44
  end
30
45
  end
31
- end
46
+ end
@@ -1,16 +1,26 @@
1
1
  module ActiveRecord
2
2
  module ConnectionAdapters
3
3
  class SQLServerAdapter
4
- # Returns true as this adapter supports views.
5
4
  def supports_triggers?
6
5
  true
7
6
  end
7
+
8
+ def supports_procs?
9
+ true
10
+ end
11
+
8
12
 
9
13
  # Returns all the trigger names from the currently connected schema.
10
14
  def triggers(name = nil)
11
15
  select_values("SELECT name FROM sys.triggers", name)
12
16
  end
13
17
 
18
+ # Returns all the proc names from the currently connected schema.
19
+ def procs(name = nil)
20
+ select_values("SELECT name FROM sysobjects WHERE type = 'P'", name)
21
+ end
22
+
23
+
14
24
  def trigger_sp_helptext(trigger, name=nil)
15
25
  q =<<-ENDSQL
16
26
  SELECT OBJECT_DEFINITION(OBJECT_ID('#{trigger}'));
@@ -43,7 +53,27 @@ ENDSQL
43
53
  trigger_def = trigger_sp_helptext(trigger, name)
44
54
  trigger_def.sub(/^CREATE.* AS /, '')
45
55
  end
46
-
56
+
57
+ def proc_sp_helptext(proc, name=nil)
58
+ q =<<-ENDSQL
59
+ SELECT OBJECT_DEFINITION(OBJECT_ID('#{proc}'));
60
+ ENDSQL
61
+
62
+ proc_def = select_value(q, name)
63
+
64
+ if !proc_def.blank?
65
+ return proc_def
66
+ else
67
+ raise "No proc called #{proc} found"
68
+ end
69
+
70
+ end
71
+
72
+ def proc_code(proc, name=nil)
73
+ proc_def = proc_sp_helptext(proc, name)
74
+ proc_def.sub(/^CREATE PROCEDURE \w+\s+/, '')
75
+ end
76
+
47
77
  end
48
78
  end
49
- end
79
+ end
@@ -5,20 +5,25 @@ module ActiveRecord
5
5
  # Acceptable values are strings as well as regexp.
6
6
  # This setting is only used if ActiveRecord::Base.schema_format == :ruby
7
7
  cattr_accessor :ignore_triggers
8
+ cattr_accessor :ignore_procs
8
9
  @@ignore_triggers = []
10
+ @@ignore_procs = []
9
11
 
10
12
  def trailer_with_triggers(stream)
11
13
  # do nothing...we'll call this later
12
14
  end
13
15
  alias_method_chain :trailer, :triggers
14
16
 
15
- # Add triggers to the end of the dump stream
17
+ # Add triggers/procs to the end of the dump stream
16
18
  def dump_with_triggers(stream)
17
19
  dump_without_triggers(stream)
18
20
  begin
19
21
  if @connection.supports_triggers?
20
22
  triggers(stream)
21
23
  end
24
+ if @connection.supports_procs?
25
+ procs(stream)
26
+ end
22
27
  rescue => e
23
28
  ActiveRecord::Base.logger.error "Unable to dump triggers: #{e}"
24
29
  end
@@ -35,12 +40,28 @@ module ActiveRecord
35
40
  when String: t == ignored
36
41
  when Regexp: t =~ ignored
37
42
  else
38
- raise StandardError, 'ActiveRecord::SchemaDumper.ignore_views accepts an array of String and / or Regexp values.'
43
+ raise StandardError, 'ActiveRecord::SchemaDumper.ignore_triggers accepts an array of String and / or Regexp values.'
39
44
  end
40
45
  end
41
46
  trigger(t, stream)
42
47
  end
43
48
  end
49
+
50
+ # Add procs to the stream
51
+ def procs(stream)
52
+ @connection.procs.sort.each do |p|
53
+ next if [ignore_procs].flatten.any? do |ignored|
54
+ case ignored
55
+ when String: p == ignored
56
+ when Regexp: p =~ ignored
57
+ else
58
+ raise StandardError, 'ActiveRecord::SchemaDumper.ignore_procs accepts an array of String and / or Regexp values.'
59
+ end
60
+ end
61
+ proc(p, stream)
62
+ end
63
+ end
64
+
44
65
 
45
66
  # Add the specified trigger to the stream
46
67
  def trigger(trigger, stream)
@@ -64,5 +85,26 @@ module ActiveRecord
64
85
 
65
86
  stream
66
87
  end
88
+
89
+ # Add the specified proc to the stream
90
+ def proc(proc, stream)
91
+ begin
92
+ t = StringIO.new
93
+ t.print " proc_code = <<EOSQL\n"
94
+ t.print @connection.proc_code(proc)
95
+ t.print "EOSQL\n"
96
+ t.print " create_proc(#{proc.to_sym.inspect}, "
97
+ t.print "proc_code, "
98
+ t.print ":force => true)\n"
99
+ t.rewind
100
+ stream.print t.read
101
+ rescue => e
102
+ stream.puts "# Could not dump proc #{proc.inspect} because of following #{e.class}"
103
+ stream.puts "# #{e.message}"
104
+ stream.puts "# #{e.trace}"
105
+ end
106
+
107
+ stream
108
+ end
67
109
  end
68
- end
110
+ end
@@ -1,8 +1,8 @@
1
1
  module TriggerHappy
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 0
4
- MINOR = 0
5
- TINY = 1
4
+ MINOR = 1
5
+ TINY = 0
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: triggerhappy
3
3
  version: !ruby/object:Gem::Version
4
- hash: 19
4
+ hash: 27
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
+ - 1
8
9
  - 0
9
- - 6
10
- version: 0.0.6
10
+ version: 0.1.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Stuart Wade
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-05-13 00:00:00 -03:00
18
+ date: 2011-08-11 00:00:00 -03:00
19
19
  default_executable:
20
20
  dependencies: []
21
21
 
@@ -28,20 +28,18 @@ extensions: []
28
28
  extra_rdoc_files: []
29
29
 
30
30
  files:
31
- - lib/triggerhappy/connection_adapters/abstract/schema_definitions.rb
32
- - lib/triggerhappy/connection_adapters/abstract/schema_statements.rb
33
- - lib/triggerhappy/connection_adapters/abstract_adapter.rb
31
+ - lib/core_ext/module.rb
32
+ - lib/triggerhappy.rb
33
+ - lib/triggerhappy/version.rb
34
+ - lib/triggerhappy/schema_dumper.rb
34
35
  - lib/triggerhappy/connection_adapters/mysql_adapter.rb
35
36
  - lib/triggerhappy/connection_adapters/sqlserver_adapter.rb
36
- - lib/triggerhappy/schema_dumper.rb
37
- - lib/triggerhappy/version.rb
38
- - lib/triggerhappy.rb
37
+ - lib/triggerhappy/connection_adapters/abstract_adapter.rb
38
+ - lib/triggerhappy/connection_adapters/abstract/schema_statements.rb
39
+ - lib/triggerhappy/connection_adapters/abstract/schema_definitions.rb
39
40
  - CHANGELOG
40
41
  - Rakefile
41
42
  - README
42
- - triggerhappy-0.0.4.gem
43
- - triggerhappy-0.0.5.gem
44
- - triggerhappy.gemspec
45
43
  has_rdoc: true
46
44
  homepage: http://blog.stewbawka.com
47
45
  licenses: []
@@ -74,7 +72,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
74
72
  requirements: []
75
73
 
76
74
  rubyforge_project: triggerhappy
77
- rubygems_version: 1.5.2
75
+ rubygems_version: 1.5.3
78
76
  signing_key:
79
77
  specification_version: 3
80
78
  summary: sql triggers in migrations
Binary file
Binary file
@@ -1,14 +0,0 @@
1
- Gem::Specification.new do |s|
2
- s.name = "triggerhappy"
3
- s.version = "0.0.6"
4
- s.author = "Stuart Wade"
5
- s.email = "stewbawka@gmail.com"
6
- s.homepage = "http://blog.stewbawka.com"
7
- s.summary = "sql triggers in migrations"
8
- s.description = "Provide create_trigger and drop_trigger in migrations. Also extends SchemaDumper to clue in about triggers"
9
- s.files = Dir["{lib,test}/**/*"] + Dir["[A-Z]*"]
10
- s.require_path = "lib"
11
-
12
- s.rubyforge_project = s.name
13
- s.required_rubygems_version = ">= 1.3.4"
14
- end