triggerhappy 0.0.6
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/CHANGELOG +2 -0
- data/README +72 -0
- data/Rakefile +14 -0
- data/lib/triggerhappy.rb +55 -0
- data/lib/triggerhappy/connection_adapters/abstract/schema_definitions.rb +16 -0
- data/lib/triggerhappy/connection_adapters/abstract/schema_statements.rb +29 -0
- data/lib/triggerhappy/connection_adapters/abstract_adapter.rb +31 -0
- data/lib/triggerhappy/connection_adapters/mysql_adapter.rb +35 -0
- data/lib/triggerhappy/connection_adapters/sqlserver_adapter.rb +49 -0
- data/lib/triggerhappy/schema_dumper.rb +68 -0
- data/lib/triggerhappy/version.rb +9 -0
- data/triggerhappy-0.0.4.gem +0 -0
- data/triggerhappy-0.0.5.gem +0 -0
- data/triggerhappy.gemspec +14 -0
- metadata +82 -0
data/CHANGELOG
ADDED
data/README
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
== Rails SQL Triggers
|
|
2
|
+
|
|
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
|
+
|
|
5
|
+
== Installation
|
|
6
|
+
|
|
7
|
+
To install:
|
|
8
|
+
|
|
9
|
+
gem install triggerhappy
|
|
10
|
+
|
|
11
|
+
Then add the following to your Rails config/environment.rb:
|
|
12
|
+
|
|
13
|
+
require_gem 'triggerhappy'
|
|
14
|
+
require 'triggerhappy'
|
|
15
|
+
|
|
16
|
+
== Usage
|
|
17
|
+
|
|
18
|
+
You can then use create_trigger and drop_trigger in your migrations. For example:
|
|
19
|
+
|
|
20
|
+
class CreatePersonChangeTrigger < ActiveRecord::Migration
|
|
21
|
+
def self.up
|
|
22
|
+
create_table :person_changes do |t|
|
|
23
|
+
t.integer :person_id, :null => false
|
|
24
|
+
t.string :first_name, :null => false
|
|
25
|
+
t.string :last_name, :null => false
|
|
26
|
+
t.string :email, :null => false
|
|
27
|
+
t.datetime :effective_start
|
|
28
|
+
t.datetime :effective_end
|
|
29
|
+
t.integer :deleted_flag, :null => false, :default => 0
|
|
30
|
+
t.string :updated_by
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
create_trigger :person_change_trig, :people, [:insert, :update], <<EOSQL
|
|
34
|
+
DECLARE @person_id INT
|
|
35
|
+
DECLARE @first_name VARCHAR(255)
|
|
36
|
+
DECLARE @last_name VARCHAR(255)
|
|
37
|
+
DECLARE @email VARCHAR(255)
|
|
38
|
+
DECLARE @effective_start DATETIME
|
|
39
|
+
DECLARE @updated_by VARCHAR(255)
|
|
40
|
+
SELECT @person_id = (SELECT id FROM inserted)
|
|
41
|
+
SELECT @first_name = (SELECT first_name FROM inserted)
|
|
42
|
+
SELECT @last_name = (SELECT last_name FROM inserted)
|
|
43
|
+
SELECT @email = (SELECT email FROM inserted)
|
|
44
|
+
SELECT @effective_start = (SELECT updated_at FROM inserted)
|
|
45
|
+
SELECT @updated_by = (SELECT updated_by FROM inserted)
|
|
46
|
+
UPDATE person_changes SET effective_end = @effective_start
|
|
47
|
+
WHERE person_id = @person_id AND effective_end IS NULL
|
|
48
|
+
INSERT INTO person_changes (person_id, first_name, last_name, email, effective_start, updated_by)
|
|
49
|
+
VALUES (@person_id, @first_name, @last_name, @email, @effective_start, @updated_by)
|
|
50
|
+
EOSQL
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def self.down
|
|
54
|
+
drop_trigger :person_change_trig
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
This extension also adds support for triggers in the ActiveRecord::SchemaDumper class.
|
|
59
|
+
|
|
60
|
+
The following drivers are supported:
|
|
61
|
+
|
|
62
|
+
SQL Server
|
|
63
|
+
|
|
64
|
+
== Known Issues
|
|
65
|
+
|
|
66
|
+
* Drivers not mentioned above are not supported.
|
|
67
|
+
|
|
68
|
+
If you find any issues please send an email to stewbawka@gmail.com .
|
|
69
|
+
|
|
70
|
+
== Contributing
|
|
71
|
+
|
|
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. :-)
|
data/Rakefile
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
begin
|
|
2
|
+
require 'jeweler'
|
|
3
|
+
Jeweler::Tasks.new do |gemspec|
|
|
4
|
+
gemspec.name = "triggerhappy"
|
|
5
|
+
gemspec.summary = "sql triggers in migrations"
|
|
6
|
+
gemspec.description = "Provide create_trigger and drop_trigger in migrations. Also extends SchemaDumper to clue in about triggers"
|
|
7
|
+
gemspec.email = "stewbawka@gmail.com"
|
|
8
|
+
gemspec.homepage = "http://blog.stewbawka.com""
|
|
9
|
+
gemspec.authors = ["Stuart Wade"]
|
|
10
|
+
end
|
|
11
|
+
Jeweler::GemcutterTasks.new
|
|
12
|
+
rescue LoadError
|
|
13
|
+
puts "Jeweler not available. Install it with: sudo gem install jeweler -s http://gemcutter.org"
|
|
14
|
+
end
|
data/lib/triggerhappy.rb
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Triggerhappy is based the rails_sql_views gem developped by Anthony Eden
|
|
2
|
+
# I have included his original copyright notice since this gem is derivative of his work.
|
|
3
|
+
#
|
|
4
|
+
#--
|
|
5
|
+
# Copyright (c) 2006 Anthony Eden
|
|
6
|
+
#
|
|
7
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
|
8
|
+
# a copy of this software and associated documentation files (the
|
|
9
|
+
# "Software"), to deal in the Software without restriction, including
|
|
10
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
|
11
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
12
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
|
13
|
+
# the following conditions:
|
|
14
|
+
#
|
|
15
|
+
# The above copyright notice and this permission notice shall be
|
|
16
|
+
# included in all copies or substantial portions of the Software.
|
|
17
|
+
#
|
|
18
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
19
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
20
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
21
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
22
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
23
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
24
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
25
|
+
#++
|
|
26
|
+
|
|
27
|
+
$:.unshift(File.dirname(__FILE__)) unless
|
|
28
|
+
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
|
29
|
+
|
|
30
|
+
require 'rubygems'
|
|
31
|
+
|
|
32
|
+
#unless Kernel.respond_to?(:gem)
|
|
33
|
+
# Kernel.send :alias_method, :gem, :require_gem
|
|
34
|
+
#end
|
|
35
|
+
|
|
36
|
+
unless defined?(ActiveRecord)
|
|
37
|
+
begin
|
|
38
|
+
$:.unshift(File.dirname(__FILE__) + "/../../activerecord/lib")
|
|
39
|
+
require 'active_record'
|
|
40
|
+
rescue LoadError
|
|
41
|
+
gem 'activerecord'
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
#require 'core_ext/module'
|
|
46
|
+
|
|
47
|
+
require 'triggerhappy/connection_adapters/abstract/schema_definitions'
|
|
48
|
+
require 'triggerhappy/connection_adapters/abstract/schema_statements'
|
|
49
|
+
#require 'triggerhappy/connection_adapters/mysql_adapter'
|
|
50
|
+
require 'triggerhappy/connection_adapters/sqlserver_adapter'
|
|
51
|
+
require 'triggerhappy/schema_dumper'
|
|
52
|
+
|
|
53
|
+
class ActiveRecord::ConnectionAdapters::AbstractAdapter
|
|
54
|
+
include Triggerhappy::ConnectionAdapters::SchemaStatements
|
|
55
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
module Triggerhappy
|
|
2
|
+
module ConnectionAdapters #:nodoc:
|
|
3
|
+
# Abstract definition of a View
|
|
4
|
+
class TriggerDefinition
|
|
5
|
+
attr_accessor :name, :target, :events, :sql
|
|
6
|
+
|
|
7
|
+
def initialize(base, name, target, events, sql)
|
|
8
|
+
@base = base
|
|
9
|
+
@name = name
|
|
10
|
+
@target = target
|
|
11
|
+
@events = events
|
|
12
|
+
@sql = sql
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
module Triggerhappy
|
|
2
|
+
module ConnectionAdapters # :nodoc:
|
|
3
|
+
module SchemaStatements
|
|
4
|
+
# Create a trigger.
|
|
5
|
+
def create_trigger(name, target, events, sql, options={})
|
|
6
|
+
if supports_triggers?
|
|
7
|
+
trigger_definition = TriggerDefinition.new(self, name, target, events, sql)
|
|
8
|
+
|
|
9
|
+
if options[:force]
|
|
10
|
+
drop_trigger(name) rescue nil
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
create_sql = "CREATE TRIGGER "
|
|
14
|
+
create_sql << "#{name} ON #{target} AFTER #{(events*', ').upcase} AS"
|
|
15
|
+
create_sql << trigger_definition.sql
|
|
16
|
+
execute create_sql
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Drop a trigger.
|
|
21
|
+
def drop_trigger(name, options={})
|
|
22
|
+
if supports_triggers?
|
|
23
|
+
drop_sql = "DROP TRIGGER #{name}"
|
|
24
|
+
execute drop_sql
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
module ActiveRecord
|
|
2
|
+
module ConnectionAdapters
|
|
3
|
+
class AbstractAdapter
|
|
4
|
+
# Subclasses should override and return true if they support triggers.
|
|
5
|
+
def supports_triggers?
|
|
6
|
+
return false
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
# Get a list of all triggers for the current database
|
|
10
|
+
def triggers(name = nil)
|
|
11
|
+
raise NotImplementedError, "triggers is an abstract method"
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# Get the code for the specified trigger
|
|
15
|
+
def trigger_code(trigger, name=nil)
|
|
16
|
+
raise NotImplementedError, "trigger_code is an abstract method"
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Get the target for the specified trigger
|
|
20
|
+
def trigger_target(trigger, name=nil)
|
|
21
|
+
raise NotImplementedError, "trigger_target is an abstract method"
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Get the events for the specified trigger
|
|
25
|
+
def trigger_events(trigger, name=nil)
|
|
26
|
+
raise NotImplementedError, "trigger_events is an abstract method"
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
module ActiveRecord
|
|
2
|
+
module ConnectionAdapters
|
|
3
|
+
class MysqlAdapter
|
|
4
|
+
# Returns true as this adapter supports views.
|
|
5
|
+
def supports_views?
|
|
6
|
+
true
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def tables(name = nil) #:nodoc:
|
|
10
|
+
tables = []
|
|
11
|
+
execute("SHOW TABLE STATUS", name).each { |row| tables << row[0] if row[17] != 'VIEW' }
|
|
12
|
+
tables
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def views(name = nil) #:nodoc:
|
|
16
|
+
views = []
|
|
17
|
+
execute("SHOW TABLE STATUS", name).each { |row| views << row[0] if row[17] == 'VIEW' }
|
|
18
|
+
views
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Get the view select statement for the specified table.
|
|
22
|
+
def view_select_statement(view, name=nil)
|
|
23
|
+
row = execute("SHOW CREATE VIEW #{view}", name).each do |row|
|
|
24
|
+
return convert_statement(row[1]) if row[0] == view
|
|
25
|
+
end
|
|
26
|
+
raise "No view called #{view} found"
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
def convert_statement(s)
|
|
31
|
+
s.gsub!(/.* AS (select .*)/, '\1')
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
module ActiveRecord
|
|
2
|
+
module ConnectionAdapters
|
|
3
|
+
class SQLServerAdapter
|
|
4
|
+
# Returns true as this adapter supports views.
|
|
5
|
+
def supports_triggers?
|
|
6
|
+
true
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
# Returns all the trigger names from the currently connected schema.
|
|
10
|
+
def triggers(name = nil)
|
|
11
|
+
select_values("SELECT name FROM sys.triggers", name)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def trigger_sp_helptext(trigger, name=nil)
|
|
15
|
+
q =<<-ENDSQL
|
|
16
|
+
SELECT OBJECT_DEFINITION(OBJECT_ID('#{trigger}'));
|
|
17
|
+
ENDSQL
|
|
18
|
+
|
|
19
|
+
trigger_def = select_value(q, name)
|
|
20
|
+
|
|
21
|
+
if !trigger_def.blank?
|
|
22
|
+
return trigger_def
|
|
23
|
+
else
|
|
24
|
+
raise "No trigger called #{trigger} found"
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def trigger_target(trigger, name=nil)
|
|
30
|
+
trigger_def = trigger_sp_helptext(trigger, name)
|
|
31
|
+
trigger_def =~ /^CREATE.* ON (.*) AFTER /
|
|
32
|
+
$1
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def trigger_events(trigger, name=nil)
|
|
36
|
+
trigger_def = trigger_sp_helptext(trigger, name)
|
|
37
|
+
trigger_def =~ /^CREATE.* AFTER (.*) AS /
|
|
38
|
+
|
|
39
|
+
$1.split(', ').collect {|t| t.downcase.to_sym}
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def trigger_code(trigger, name=nil)
|
|
43
|
+
trigger_def = trigger_sp_helptext(trigger, name)
|
|
44
|
+
trigger_def.sub(/^CREATE.* AS /, '')
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
module ActiveRecord
|
|
2
|
+
class SchemaDumper
|
|
3
|
+
|
|
4
|
+
# A list of triggers which should not be dumped to the schema.
|
|
5
|
+
# Acceptable values are strings as well as regexp.
|
|
6
|
+
# This setting is only used if ActiveRecord::Base.schema_format == :ruby
|
|
7
|
+
cattr_accessor :ignore_triggers
|
|
8
|
+
@@ignore_triggers = []
|
|
9
|
+
|
|
10
|
+
def trailer_with_triggers(stream)
|
|
11
|
+
# do nothing...we'll call this later
|
|
12
|
+
end
|
|
13
|
+
alias_method_chain :trailer, :triggers
|
|
14
|
+
|
|
15
|
+
# Add triggers to the end of the dump stream
|
|
16
|
+
def dump_with_triggers(stream)
|
|
17
|
+
dump_without_triggers(stream)
|
|
18
|
+
begin
|
|
19
|
+
if @connection.supports_triggers?
|
|
20
|
+
triggers(stream)
|
|
21
|
+
end
|
|
22
|
+
rescue => e
|
|
23
|
+
ActiveRecord::Base.logger.error "Unable to dump triggers: #{e}"
|
|
24
|
+
end
|
|
25
|
+
trailer_without_triggers(stream)
|
|
26
|
+
stream
|
|
27
|
+
end
|
|
28
|
+
alias_method_chain :dump, :triggers
|
|
29
|
+
|
|
30
|
+
# Add triggers to the stream
|
|
31
|
+
def triggers(stream)
|
|
32
|
+
@connection.triggers.sort.each do |t|
|
|
33
|
+
next if ["schema_info", ignore_triggers].flatten.any? do |ignored|
|
|
34
|
+
case ignored
|
|
35
|
+
when String: t == ignored
|
|
36
|
+
when Regexp: t =~ ignored
|
|
37
|
+
else
|
|
38
|
+
raise StandardError, 'ActiveRecord::SchemaDumper.ignore_views accepts an array of String and / or Regexp values.'
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
trigger(t, stream)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Add the specified trigger to the stream
|
|
46
|
+
def trigger(trigger, stream)
|
|
47
|
+
begin
|
|
48
|
+
t = StringIO.new
|
|
49
|
+
t.print " trigger_code = <<EOSQL\n"
|
|
50
|
+
t.print @connection.trigger_code(trigger)
|
|
51
|
+
t.print "EOSQL\n"
|
|
52
|
+
t.print " create_trigger(#{trigger.to_sym.inspect}, "
|
|
53
|
+
t.print "#{@connection.trigger_target(trigger).to_sym.inspect}, "
|
|
54
|
+
t.print "#{@connection.trigger_events(trigger).inspect}, "
|
|
55
|
+
t.print "trigger_code, "
|
|
56
|
+
t.print ":force => true)\n"
|
|
57
|
+
t.rewind
|
|
58
|
+
stream.print t.read
|
|
59
|
+
rescue => e
|
|
60
|
+
stream.puts "# Could not dump trigger #{trigger.inspect} because of following #{e.class}"
|
|
61
|
+
stream.puts "# #{e.message}"
|
|
62
|
+
stream.puts "# #{e.trace}"
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
stream
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,14 @@
|
|
|
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
|
metadata
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: triggerhappy
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
hash: 19
|
|
5
|
+
prerelease:
|
|
6
|
+
segments:
|
|
7
|
+
- 0
|
|
8
|
+
- 0
|
|
9
|
+
- 6
|
|
10
|
+
version: 0.0.6
|
|
11
|
+
platform: ruby
|
|
12
|
+
authors:
|
|
13
|
+
- Stuart Wade
|
|
14
|
+
autorequire:
|
|
15
|
+
bindir: bin
|
|
16
|
+
cert_chain: []
|
|
17
|
+
|
|
18
|
+
date: 2011-05-13 00:00:00 -03:00
|
|
19
|
+
default_executable:
|
|
20
|
+
dependencies: []
|
|
21
|
+
|
|
22
|
+
description: Provide create_trigger and drop_trigger in migrations. Also extends SchemaDumper to clue in about triggers
|
|
23
|
+
email: stewbawka@gmail.com
|
|
24
|
+
executables: []
|
|
25
|
+
|
|
26
|
+
extensions: []
|
|
27
|
+
|
|
28
|
+
extra_rdoc_files: []
|
|
29
|
+
|
|
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
|
|
34
|
+
- lib/triggerhappy/connection_adapters/mysql_adapter.rb
|
|
35
|
+
- lib/triggerhappy/connection_adapters/sqlserver_adapter.rb
|
|
36
|
+
- lib/triggerhappy/schema_dumper.rb
|
|
37
|
+
- lib/triggerhappy/version.rb
|
|
38
|
+
- lib/triggerhappy.rb
|
|
39
|
+
- CHANGELOG
|
|
40
|
+
- Rakefile
|
|
41
|
+
- README
|
|
42
|
+
- triggerhappy-0.0.4.gem
|
|
43
|
+
- triggerhappy-0.0.5.gem
|
|
44
|
+
- triggerhappy.gemspec
|
|
45
|
+
has_rdoc: true
|
|
46
|
+
homepage: http://blog.stewbawka.com
|
|
47
|
+
licenses: []
|
|
48
|
+
|
|
49
|
+
post_install_message:
|
|
50
|
+
rdoc_options: []
|
|
51
|
+
|
|
52
|
+
require_paths:
|
|
53
|
+
- lib
|
|
54
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
55
|
+
none: false
|
|
56
|
+
requirements:
|
|
57
|
+
- - ">="
|
|
58
|
+
- !ruby/object:Gem::Version
|
|
59
|
+
hash: 3
|
|
60
|
+
segments:
|
|
61
|
+
- 0
|
|
62
|
+
version: "0"
|
|
63
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
64
|
+
none: false
|
|
65
|
+
requirements:
|
|
66
|
+
- - ">="
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
hash: 19
|
|
69
|
+
segments:
|
|
70
|
+
- 1
|
|
71
|
+
- 3
|
|
72
|
+
- 4
|
|
73
|
+
version: 1.3.4
|
|
74
|
+
requirements: []
|
|
75
|
+
|
|
76
|
+
rubyforge_project: triggerhappy
|
|
77
|
+
rubygems_version: 1.5.2
|
|
78
|
+
signing_key:
|
|
79
|
+
specification_version: 3
|
|
80
|
+
summary: sql triggers in migrations
|
|
81
|
+
test_files: []
|
|
82
|
+
|