hairtrigger 0.1.14 → 0.2.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.rdoc +47 -41
- data/Rakefile +0 -34
- data/lib/hair_trigger.rb +134 -113
- data/lib/hair_trigger/builder.rb +3 -12
- data/lib/hair_trigger/migration_reader.rb +1 -1
- data/lib/hair_trigger/railtie.rb +11 -0
- data/lib/hair_trigger/version.rb +7 -0
- data/{init.rb → lib/hairtrigger.rb} +0 -0
- data/lib/tasks/hair_trigger.rake +1 -1
- data/spec/migrations-pre-3.1/20110331212003_initial_tables.rb +18 -0
- data/spec/migrations-pre-3.1/20110331212631_user_trigger.rb +18 -0
- data/spec/migrations-pre-3.1/20110417185102_manual_user_trigger.rb +10 -0
- data/spec/migrations/20110331212003_initial_tables.rb +2 -2
- data/spec/migrations/20110331212631_user_trigger.rb +2 -2
- data/spec/migrations/20110417185102_manual_user_trigger.rb +1 -1
- data/spec/schema_dumper_spec.rb +35 -34
- metadata +145 -248
- data/.document +0 -5
- data/.rspec +0 -1
- data/Gemfile +0 -16
- data/VERSION +0 -1
- data/rails/init.rb +0 -1
data/README.rdoc
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
= HairTrigger
|
2
|
+
{<img src="https://secure.travis-ci.org/jenseng/hair_trigger.png?branch=master" />}[http://travis-ci.org/jenseng/hair_trigger]
|
2
3
|
|
3
4
|
HairTrigger lets you create and manage database triggers in a concise,
|
4
5
|
db-agnostic, Rails-y way. You declare triggers right in your models in Ruby,
|
@@ -6,14 +7,18 @@ and a simple rake task does all the dirty work for you.
|
|
6
7
|
|
7
8
|
== Installation
|
8
9
|
|
9
|
-
===
|
10
|
+
=== Rails 3
|
10
11
|
|
11
|
-
If you are using
|
12
|
+
If you are using Rails 3, just put hairtrigger in your Gemfile.
|
12
13
|
|
13
|
-
|
14
|
-
hairtrigger in environment.rb
|
14
|
+
=== Rails 2
|
15
15
|
|
16
|
-
|
16
|
+
==== Step 1.
|
17
|
+
|
18
|
+
Put hairtrigger in your Gemfile, or if you're not using bundler, you can
|
19
|
+
"gem install hairtrigger" and then put hairtrigger in environment.rb
|
20
|
+
|
21
|
+
==== Step 2.
|
17
22
|
|
18
23
|
Create lib/tasks/hair_trigger.rake with the following:
|
19
24
|
|
@@ -60,38 +65,6 @@ removed or updated. It does this by diffing the current model trigger
|
|
60
65
|
declarations and any auto-generated triggers in schema.rb (and subsequent
|
61
66
|
migrations).
|
62
67
|
|
63
|
-
=== Manual Migrations
|
64
|
-
|
65
|
-
You can also manage triggers manually in your migrations via create_trigger and
|
66
|
-
drop_trigger. They are a little more verbose than model triggers, and they can
|
67
|
-
be more work since you need to figure out the up/down create/drop logic when
|
68
|
-
you change things. A sample trigger:
|
69
|
-
|
70
|
-
create_trigger(:compatibility => 1).on(:users).after(:insert) do
|
71
|
-
"UPDATE accounts SET user_count = user_count + 1 WHERE id = NEW.account_id;"
|
72
|
-
end
|
73
|
-
|
74
|
-
==== Manual triggers and :compatibility
|
75
|
-
|
76
|
-
As bugs are fixed and features are implemented in hairtrigger, it's possible
|
77
|
-
that the generated trigger SQL will change (this has only happened once so
|
78
|
-
far). If you upgrade to a newer version of hairtrigger, it needs a way of
|
79
|
-
knowing which previous version generated the original trigger. You only need
|
80
|
-
to worry about this for manual trigger migrations, as the model ones
|
81
|
-
automatically take care of this. For your manual triggers you can either:
|
82
|
-
|
83
|
-
* pass ":compatibility => x" to your create_trigger statement, where x is
|
84
|
-
whatever HairTrigger::Builder.compatiblity is (1 for this version).
|
85
|
-
* set "HairTrigger::Builder.base_compatibility = x" in an initializer, where
|
86
|
-
x is whatever HairTrigger::Builder.compatiblity is. This is like doing the
|
87
|
-
first option on every create_trigger. Note that once the compatibility
|
88
|
-
changes, you'll need to set :compatibility on new triggers (unless you
|
89
|
-
just redo all your triggers and bump the base_compatibility).
|
90
|
-
|
91
|
-
If you upgrade to a newer version of hairtrigger and see that the SQL
|
92
|
-
compatibility has changed, you'll need to set the appropriate compatibility
|
93
|
-
on any new triggers that you create.
|
94
|
-
|
95
68
|
=== Chainable Methods
|
96
69
|
|
97
70
|
Triggers are built by chaining several methods together, ending in a block
|
@@ -139,10 +112,10 @@ and timing. For example:
|
|
139
112
|
t.all do # every row
|
140
113
|
# some sql
|
141
114
|
end
|
142
|
-
t.where("OLD.foo
|
115
|
+
t.where("OLD.foo != NEW.foo") do
|
143
116
|
# some more sql
|
144
117
|
end
|
145
|
-
t.where("OLD.bar
|
118
|
+
t.where("OLD.bar != NEW.bar") do
|
146
119
|
# some other sql
|
147
120
|
end
|
148
121
|
end
|
@@ -175,6 +148,38 @@ you might do something like the following:
|
|
175
148
|
MYSQL
|
176
149
|
end
|
177
150
|
|
151
|
+
=== Manual Migrations
|
152
|
+
|
153
|
+
You can also manage triggers manually in your migrations via create_trigger and
|
154
|
+
drop_trigger. They are a little more verbose than model triggers, and they can
|
155
|
+
be more work since you need to figure out the up/down create/drop logic when
|
156
|
+
you change things. A sample trigger:
|
157
|
+
|
158
|
+
create_trigger(:compatibility => 1).on(:users).after(:insert) do
|
159
|
+
"UPDATE accounts SET user_count = user_count + 1 WHERE id = NEW.account_id;"
|
160
|
+
end
|
161
|
+
|
162
|
+
==== Manual triggers and :compatibility
|
163
|
+
|
164
|
+
As bugs are fixed and features are implemented in hairtrigger, it's possible
|
165
|
+
that the generated trigger SQL will change (this has only happened once so
|
166
|
+
far). If you upgrade to a newer version of hairtrigger, it needs a way of
|
167
|
+
knowing which previous version generated the original trigger. You only need
|
168
|
+
to worry about this for manual trigger migrations, as the model ones
|
169
|
+
automatically take care of this. For your manual triggers you can either:
|
170
|
+
|
171
|
+
* pass ":compatibility => x" to your create_trigger statement, where x is
|
172
|
+
whatever HairTrigger::Builder.compatiblity is (1 for this version).
|
173
|
+
* set "HairTrigger::Builder.base_compatibility = x" in an initializer, where
|
174
|
+
x is whatever HairTrigger::Builder.compatiblity is. This is like doing the
|
175
|
+
first option on every create_trigger. Note that once the compatibility
|
176
|
+
changes, you'll need to set :compatibility on new triggers (unless you
|
177
|
+
just redo all your triggers and bump the base_compatibility).
|
178
|
+
|
179
|
+
If you upgrade to a newer version of hairtrigger and see that the SQL
|
180
|
+
compatibility has changed, you'll need to set the appropriate compatibility
|
181
|
+
on any new triggers that you create.
|
182
|
+
|
178
183
|
== rake db:schema:dump
|
179
184
|
|
180
185
|
HairTrigger hooks into rake db:schema:dump (and rake tasks that call it) to
|
@@ -251,13 +256,14 @@ you want to support.
|
|
251
256
|
|
252
257
|
== Compatibility
|
253
258
|
|
254
|
-
* Rails 2.3
|
259
|
+
* Rails 2.3+
|
255
260
|
* Postgres 8.0+
|
256
261
|
* MySQL 5.0.10+
|
257
262
|
* SQLite 3.3.8+
|
258
263
|
|
259
264
|
== Version History
|
260
265
|
|
266
|
+
* 0.2.0 Rails 3.1+ support, easier installation, ruby 1.9 fix, travis-ci
|
261
267
|
* 0.1.14 sqlite + ruby1.9 bugfix
|
262
268
|
* 0.1.13 drop_trigger fix
|
263
269
|
* 0.1.12 DB-specific trigger body support, bugfixes
|
@@ -275,4 +281,4 @@ you want to support.
|
|
275
281
|
|
276
282
|
== Copyright
|
277
283
|
|
278
|
-
Copyright (c)
|
284
|
+
Copyright (c) 2012 Jon Jensen. See LICENSE.txt for further details.
|
data/Rakefile
CHANGED
@@ -1,29 +1,5 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require 'bundler'
|
3
|
-
begin
|
4
|
-
Bundler.setup(:default, :development)
|
5
|
-
rescue Bundler::BundlerError => e
|
6
|
-
$stderr.puts e.message
|
7
|
-
$stderr.puts "Run `bundle install` to install missing gems"
|
8
|
-
exit e.status_code
|
9
|
-
end
|
10
1
|
require 'rake'
|
11
2
|
|
12
|
-
require 'jeweler'
|
13
|
-
Jeweler::Tasks.new do |gem|
|
14
|
-
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
15
|
-
gem.name = "hairtrigger"
|
16
|
-
gem.homepage = "http://github.com/jenseng/hair_trigger"
|
17
|
-
gem.license = "MIT"
|
18
|
-
gem.summary = %Q{easy database triggers for active record}
|
19
|
-
gem.description = %Q{allows you to declare database triggers in ruby in your models, and then generate appropriate migrations as they change}
|
20
|
-
gem.email = "jenseng@gmail.com"
|
21
|
-
gem.authors = ["Jon Jensen"]
|
22
|
-
gem.add_dependency "activerecord", ">=2.3.0"
|
23
|
-
gem.add_development_dependency "rspec", "~> 2.3.0"
|
24
|
-
end
|
25
|
-
Jeweler::RubygemsDotOrgTasks.new
|
26
|
-
|
27
3
|
require 'rspec/core'
|
28
4
|
require 'rspec/core/rake_task'
|
29
5
|
RSpec::Core::RakeTask.new(:spec) do |spec|
|
@@ -36,13 +12,3 @@ RSpec::Core::RakeTask.new(:rcov) do |spec|
|
|
36
12
|
end
|
37
13
|
|
38
14
|
task :default => :spec
|
39
|
-
|
40
|
-
require 'rake/rdoctask'
|
41
|
-
Rake::RDocTask.new do |rdoc|
|
42
|
-
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
43
|
-
|
44
|
-
rdoc.rdoc_dir = 'rdoc'
|
45
|
-
rdoc.title = "hairtrigger #{version}"
|
46
|
-
rdoc.rdoc_files.include('README*')
|
47
|
-
rdoc.rdoc_files.include('lib/**/*.rb')
|
48
|
-
end
|
data/lib/hair_trigger.rb
CHANGED
@@ -5,154 +5,175 @@ require 'hair_trigger/migration_reader'
|
|
5
5
|
require 'hair_trigger/migrator'
|
6
6
|
require 'hair_trigger/adapter'
|
7
7
|
require 'hair_trigger/schema_dumper'
|
8
|
+
require 'hair_trigger/railtie' if defined?(Rails::Railtie)
|
8
9
|
|
9
10
|
module HairTrigger
|
10
|
-
|
11
|
-
|
12
|
-
canonical_triggers = []
|
13
|
-
Dir[model_path + '/*rb'].each do |model|
|
14
|
-
class_name = model.sub(/\A.*\/(.*?)\.rb\z/, '\1').camelize
|
15
|
-
next unless File.read(model) =~ /^\s*trigger[\.\(]/
|
16
|
-
begin
|
17
|
-
require model unless klass = Kernel.const_get(class_name) rescue nil
|
18
|
-
klass = Kernel.const_get(class_name)
|
19
|
-
rescue StandardError, LoadError
|
20
|
-
raise "unable to load #{class_name} and its trigger(s)" if File.read(model) =~ /^\s*trigger[\.\(]/
|
21
|
-
end
|
22
|
-
canonical_triggers += klass.triggers if klass < ActiveRecord::Base && klass.triggers
|
23
|
-
end
|
24
|
-
canonical_triggers.each(&:prepare!) # interpolates any vars so we match the migrations
|
25
|
-
end
|
11
|
+
class << self
|
12
|
+
attr_writer :model_path, :schema_rb_path, :migration_path
|
26
13
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
options[:skip_pending_migrations] = true
|
14
|
+
def current_triggers
|
15
|
+
# see what the models say there should be
|
16
|
+
canonical_triggers = models.map(&:triggers).flatten.compact
|
17
|
+
canonical_triggers.each(&:prepare!) # interpolates any vars so we match the migrations
|
32
18
|
end
|
33
19
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
20
|
+
def models
|
21
|
+
if defined?(Rails) && Rails::VERSION::MAJOR > 2
|
22
|
+
Rails.application.eager_load!
|
23
|
+
else
|
24
|
+
Dir[model_path + '/*rb'].each do |model|
|
25
|
+
class_name = model.sub(/\A.*\/(.*?)\.rb\z/, '\1').camelize
|
26
|
+
next unless File.read(model) =~ /^\s*trigger[\.\(]/
|
27
|
+
begin
|
28
|
+
require "./#{model}" unless Object.const_defined?(class_name)
|
29
|
+
rescue StandardError, LoadError
|
30
|
+
raise "unable to load #{class_name} and its trigger(s)"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
ActiveRecord::VERSION::STRING < "3.0." ?
|
35
|
+
ActiveRecord::Base.send(:subclasses) :
|
36
|
+
ActiveRecord::Base.descendants
|
49
37
|
end
|
50
38
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
39
|
+
def current_migrations(options = {})
|
40
|
+
if options[:in_rake_task]
|
41
|
+
options[:include_manual_triggers] = true
|
42
|
+
options[:schema_rb_first] = true
|
43
|
+
options[:skip_pending_migrations] = true
|
56
44
|
end
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
45
|
+
|
46
|
+
# if we're in a db:schema:dump task (explict or kicked off by db:migrate),
|
47
|
+
# we evaluate the previous schema.rb (if it exists), and then all applied
|
48
|
+
# migrations in order (even ones older than schema.rb). this ensures we
|
49
|
+
# handle db:migrate:down scenarios correctly
|
50
|
+
#
|
51
|
+
# if we're not in such a rake task (i.e. we just want to know what
|
52
|
+
# triggers are defined, whether or not they are applied in the db), we
|
53
|
+
# evaluate all migrations along with schema.rb, ordered by version
|
54
|
+
migrator = ActiveRecord::Migrator.new(:up, migration_path)
|
55
|
+
migrated = migrator.migrated rescue []
|
56
|
+
migrations = []
|
57
|
+
migrator.migrations.each do |migration|
|
58
|
+
next if options[:skip_pending_migrations] && !migrated.include?(migration.version)
|
59
|
+
triggers = MigrationReader.get_triggers(migration, options)
|
60
|
+
migrations << [migration, triggers] unless triggers.empty?
|
61
|
+
end
|
62
|
+
|
63
|
+
if previous_schema = (options.has_key?(:previous_schema) ? options[:previous_schema] : File.exist?(schema_rb_path) && File.read(schema_rb_path))
|
64
|
+
base_triggers = MigrationReader.get_triggers(previous_schema, options)
|
65
|
+
unless base_triggers.empty?
|
66
|
+
version = (previous_schema =~ /ActiveRecord::Schema\.define\(:version => (\d+)\)/) && $1.to_i
|
67
|
+
migrations.unshift [OpenStruct.new({:version => version}), base_triggers]
|
68
|
+
end
|
69
69
|
end
|
70
|
+
|
71
|
+
migrations = migrations.sort_by{|(migration, triggers)| migration.version} unless options[:schema_rb_first]
|
72
|
+
|
73
|
+
all_builders = []
|
74
|
+
migrations.each do |(migration, triggers)|
|
75
|
+
triggers.each do |new_trigger|
|
76
|
+
# if there is already a trigger with this name, delete it since we are
|
77
|
+
# either dropping it or replacing it
|
78
|
+
new_trigger.prepare!
|
79
|
+
all_builders.delete_if{ |(n, t)| t.prepared_name == new_trigger.prepared_name }
|
80
|
+
all_builders << [migration.name, new_trigger] unless new_trigger.options[:drop]
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
all_builders
|
70
85
|
end
|
71
86
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
def self.migrations_current?
|
76
|
-
current_migrations.map(&:last).sort.eql? current_triggers.sort
|
77
|
-
end
|
78
|
-
|
79
|
-
def self.generate_migration(silent = false)
|
80
|
-
begin
|
81
|
-
canonical_triggers = current_triggers
|
82
|
-
rescue
|
83
|
-
$stderr.puts $!
|
84
|
-
exit 1
|
87
|
+
def migrations_current?
|
88
|
+
current_migrations.map(&:last).sort.eql? current_triggers.sort
|
85
89
|
end
|
86
90
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
down_drop_triggers = []
|
94
|
-
down_create_triggers = []
|
95
|
-
|
96
|
-
existing_triggers.each do |existing|
|
97
|
-
unless canonical_triggers.any?{ |t| t.prepared_name == existing.prepared_name }
|
98
|
-
up_drop_triggers += existing.drop_triggers
|
99
|
-
down_create_triggers << existing
|
91
|
+
def generate_migration(silent = false)
|
92
|
+
begin
|
93
|
+
canonical_triggers = current_triggers
|
94
|
+
rescue
|
95
|
+
$stderr.puts $!
|
96
|
+
exit 1
|
100
97
|
end
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
98
|
+
|
99
|
+
migrations = current_migrations
|
100
|
+
migration_names = migrations.map(&:first)
|
101
|
+
existing_triggers = migrations.map(&:last)
|
102
|
+
|
103
|
+
up_drop_triggers = []
|
104
|
+
up_create_triggers = []
|
105
|
+
down_drop_triggers = []
|
106
|
+
down_create_triggers = []
|
107
|
+
|
108
|
+
# see which triggers need to be dropped
|
109
|
+
existing_triggers.each do |existing|
|
110
|
+
next if canonical_triggers.any?{ |t| t.prepared_name == existing.prepared_name }
|
111
|
+
up_drop_triggers.concat existing.drop_triggers
|
111
112
|
down_create_triggers << existing
|
112
113
|
end
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
114
|
+
|
115
|
+
# see which triggers need to be added/replaced
|
116
|
+
(canonical_triggers - existing_triggers).each do |new_trigger|
|
117
|
+
up_create_triggers << new_trigger
|
118
|
+
down_drop_triggers.concat new_trigger.drop_triggers
|
119
|
+
if existing = existing_triggers.detect{ |t| t.prepared_name == new_trigger.prepared_name }
|
120
|
+
# it's not sufficient to rely on the new trigger to replace the old
|
121
|
+
# one, since we could be dealing with trigger groups and the name
|
122
|
+
# alone isn't sufficient to know which component triggers to remove
|
123
|
+
up_drop_triggers.concat existing.drop_triggers
|
124
|
+
down_create_triggers << existing
|
125
|
+
end
|
124
126
|
end
|
127
|
+
|
128
|
+
return if up_drop_triggers.empty? && up_create_triggers.empty?
|
125
129
|
|
126
|
-
|
127
|
-
|
128
|
-
name_version = name_version.to_i + 1
|
129
|
-
end
|
130
|
-
migration_name = "#{migration_base_name}#{name_version}"
|
131
|
-
migration_version = ActiveRecord::Base.timestamped_migrations ?
|
132
|
-
Time.now.getutc.strftime("%Y%m%d%H%M%S") :
|
133
|
-
Dir.glob(migration_path + '/*rb').map{ |f| f.gsub(/.*\/(\d+)_.*/, '\1').to_i}.inject(0){ |curr, i| i > curr ? i : curr } + 1
|
130
|
+
migration_name = infer_migration_name(migration_names, up_create_triggers, up_drop_triggers)
|
131
|
+
migration_version = infer_migration_version(migration_name)
|
134
132
|
file_name = migration_path + '/' + migration_version + "_" + migration_name.underscore + ".rb"
|
133
|
+
prefix = ActiveRecord::VERSION::STRING < "3.1." ? "self." : ""
|
135
134
|
File.open(file_name, "w"){ |f| f.write <<-MIGRATION }
|
136
135
|
# This migration was auto-generated via `rake db:generate_trigger_migration'.
|
137
136
|
# While you can edit this file, any changes you make to the definitions here
|
138
137
|
# will be undone by the next auto-generated trigger migration.
|
139
138
|
|
140
139
|
class #{migration_name} < ActiveRecord::Migration
|
141
|
-
def
|
140
|
+
def #{prefix}up
|
142
141
|
#{(up_drop_triggers + up_create_triggers).map{ |t| t.to_ruby(' ') }.join("\n\n").lstrip}
|
143
142
|
end
|
144
143
|
|
145
|
-
def
|
144
|
+
def #{prefix}down
|
146
145
|
#{(down_drop_triggers + down_create_triggers).map{ |t| t.to_ruby(' ') }.join("\n\n").lstrip}
|
147
146
|
end
|
148
147
|
end
|
149
148
|
MIGRATION
|
150
149
|
file_name
|
151
150
|
end
|
152
|
-
end
|
153
151
|
|
154
|
-
|
155
|
-
|
152
|
+
def infer_migration_name(migration_names, create_triggers, drop_triggers)
|
153
|
+
migration_base_name = if create_triggers.size > 0
|
154
|
+
("create trigger#{create_triggers.size > 1 ? 's' : ''} " +
|
155
|
+
create_triggers.map{ |t| [t.options[:table], t.options[:events].join(" ")].join(" ") }.join(" and ")
|
156
|
+
).downcase.gsub(/[^a-z0-9_]/, '_').gsub(/_+/, '_').camelize
|
157
|
+
else
|
158
|
+
("drop trigger#{drop_triggers.size > 1 ? 's' : ''} " +
|
159
|
+
drop_triggers.map{ |t| t.options[:table] }.join(" and ")
|
160
|
+
).downcase.gsub(/[^a-z0-9_]/, '_').gsub(/_+/, '_').camelize
|
161
|
+
end
|
162
|
+
|
163
|
+
name_version = nil
|
164
|
+
while migration_names.include?("#{migration_base_name}#{name_version}")
|
165
|
+
name_version = name_version.to_i + 1
|
166
|
+
end
|
167
|
+
migration_name = "#{migration_base_name}#{name_version}"
|
168
|
+
end
|
169
|
+
|
170
|
+
def infer_migration_version(migration_name)
|
171
|
+
ActiveRecord::Base.timestamped_migrations ?
|
172
|
+
Time.now.getutc.strftime("%Y%m%d%H%M%S") :
|
173
|
+
Dir.glob(migration_path + '/*rb').
|
174
|
+
map{ |f| f.gsub(/.*\/(\d+)_.*/, '\1').to_i}.
|
175
|
+
inject(0){ |curr, i| i > curr ? i : curr } + 1
|
176
|
+
end
|
156
177
|
|
157
178
|
def model_path
|
158
179
|
@model_path ||= 'app/models'
|
data/lib/hair_trigger/builder.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'hair_trigger/version'
|
2
|
+
|
1
3
|
module HairTrigger
|
2
4
|
class Builder
|
3
5
|
class DeclarationError < StandardError; end
|
@@ -425,18 +427,7 @@ BEGIN
|
|
425
427
|
|
426
428
|
def compatibility
|
427
429
|
@compatibility ||= begin
|
428
|
-
|
429
|
-
gem_version.instance_eval(<<-METHODS)
|
430
|
-
def <=>(other)
|
431
|
-
[size, other.size].max.times do |i|
|
432
|
-
c = self[i].to_i <=> other[i].to_i
|
433
|
-
return c unless c == 0
|
434
|
-
end
|
435
|
-
0
|
436
|
-
end
|
437
|
-
extend Comparable
|
438
|
-
METHODS
|
439
|
-
if gem_version <= [0, 1, 3]
|
430
|
+
if HairTrigger::VERSION <= "0.1.3"
|
440
431
|
0 # initial releases
|
441
432
|
else
|
442
433
|
1 # postgres RETURN bugfix
|
@@ -22,7 +22,7 @@ module HairTrigger
|
|
22
22
|
sexps = sexps.detect{ |s| s.is_a?(Sexp) && s[0] == :class && s[1] == source.name.to_sym }.last
|
23
23
|
# find the block of the up method
|
24
24
|
sexps = sexps.last if sexps.last.is_a?(Sexp) && sexps.last[0] == :block
|
25
|
-
sexps = sexps.detect{ |s| s.is_a?(Sexp) && s[0] == :defs && s[1] && s[1][0] == :self && s[2] == :up }.last.last
|
25
|
+
sexps = sexps.detect{ |s| s.is_a?(Sexp) && (s[0] == :defs && s[1] && s[1][0] == :self && s[2] == :up || s[0] == :defn && s[1] == :up) }.last.last
|
26
26
|
sexps.each do |sexp|
|
27
27
|
next unless (method = extract_method_call(sexp)) && [:create_trigger, :drop_trigger].include?(method)
|
28
28
|
trigger = instance_eval("generate_" + generator.process(sexp))
|
File without changes
|
data/lib/tasks/hair_trigger.rake
CHANGED
@@ -12,7 +12,7 @@ namespace :db do
|
|
12
12
|
desc "Create a db/schema.rb file that can be portably used against any DB supported by AR"
|
13
13
|
task :dump => :environment do
|
14
14
|
require 'active_record/schema_dumper'
|
15
|
-
filename = ENV['SCHEMA'] || "#{
|
15
|
+
filename = ENV['SCHEMA'] || "#{Rails.root}/db/schema.rb"
|
16
16
|
ActiveRecord::SchemaDumper.previous_schema = File.exist?(filename) ? File.read(filename) : nil
|
17
17
|
File.open(filename, "w") do |file|
|
18
18
|
ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, file)
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class InitialTables < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table "users" do |t|
|
4
|
+
t.integer "group_id"
|
5
|
+
t.string "name"
|
6
|
+
end
|
7
|
+
|
8
|
+
create_table "groups" do |t|
|
9
|
+
t.integer "bob_count", :default => 0
|
10
|
+
t.integer "updated_joe_count", :default => 0
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.down
|
15
|
+
drop_table "users"
|
16
|
+
drop_table "groups"
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# This migration was auto-generated via `rake db:generate_trigger_migration'.
|
2
|
+
# While you can edit this file, any changes you make to the definitions here
|
3
|
+
# will be undone by the next auto-generated trigger migration.
|
4
|
+
|
5
|
+
class UserTrigger < ActiveRecord::Migration
|
6
|
+
def self.up
|
7
|
+
create_trigger("users_after_insert_row_when_new_name_bob__tr", :generated => true, :compatibility => 1).
|
8
|
+
on("users").
|
9
|
+
after(:insert).
|
10
|
+
where("NEW.name = 'bob'") do
|
11
|
+
"UPDATE groups SET bob_count = bob_count + 1"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.down
|
16
|
+
drop_trigger("users_after_insert_row_when_new_name_bob__tr", "users")
|
17
|
+
end
|
18
|
+
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
class InitialTables < ActiveRecord::Migration
|
2
|
-
def
|
2
|
+
def up
|
3
3
|
create_table "users" do |t|
|
4
4
|
t.integer "group_id"
|
5
5
|
t.string "name"
|
@@ -11,7 +11,7 @@ class InitialTables < ActiveRecord::Migration
|
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
14
|
-
def
|
14
|
+
def down
|
15
15
|
drop_table "users"
|
16
16
|
drop_table "groups"
|
17
17
|
end
|
@@ -3,7 +3,7 @@
|
|
3
3
|
# will be undone by the next auto-generated trigger migration.
|
4
4
|
|
5
5
|
class UserTrigger < ActiveRecord::Migration
|
6
|
-
def
|
6
|
+
def up
|
7
7
|
create_trigger("users_after_insert_row_when_new_name_bob__tr", :generated => true, :compatibility => 1).
|
8
8
|
on("users").
|
9
9
|
after(:insert).
|
@@ -12,7 +12,7 @@ class UserTrigger < ActiveRecord::Migration
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
-
def
|
15
|
+
def down
|
16
16
|
drop_trigger("users_after_insert_row_when_new_name_bob__tr", "users")
|
17
17
|
end
|
18
18
|
end
|
data/spec/schema_dumper_spec.rb
CHANGED
@@ -6,47 +6,48 @@ require 'active_record/connection_adapters/sqlite3_adapter'
|
|
6
6
|
require 'mysql2'
|
7
7
|
require 'rspec'
|
8
8
|
require 'hair_trigger'
|
9
|
+
require 'yaml'
|
9
10
|
|
10
11
|
# for this spec to work, you need to have postgres and mysql installed (in
|
11
12
|
# addition to the gems), and you should make sure that you have set up
|
12
|
-
#
|
13
|
-
# user (no password) having appropriate privileges (user needs to be able to
|
14
|
-
# drop/recreate this db)
|
13
|
+
# appropriate users and permissions. see database.yml for more info
|
15
14
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
15
|
+
describe "schema" do
|
16
|
+
def reset_tmp
|
17
|
+
HairTrigger.model_path = 'tmp/models'
|
18
|
+
HairTrigger.migration_path = 'tmp/migrations'
|
19
|
+
FileUtils.rm_rf('tmp') if File.directory?('tmp')
|
20
|
+
FileUtils.mkdir_p(HairTrigger.model_path)
|
21
|
+
FileUtils.mkdir_p(HairTrigger.migration_path)
|
22
|
+
FileUtils.cp_r('spec/models', 'tmp')
|
23
|
+
FileUtils.cp_r(Dir.glob("spec/migrations#{ActiveRecord::VERSION::STRING < "3.1." ? "-pre-3.1" : ""}/*"), HairTrigger.migration_path)
|
24
|
+
end
|
25
|
+
|
26
|
+
def initialize_db(adapter)
|
27
|
+
reset_tmp
|
28
|
+
config = @configs[adapter.to_s].merge({:adapter => adapter.to_s})
|
29
|
+
case adapter
|
30
|
+
when :mysql, :mysql2
|
31
|
+
ret = `echo "drop database if exists #{config['database']}; create database #{config['database']};" | mysql -u #{config['username']}`
|
32
|
+
raise "error creating database: #{ret}" unless $?.exitstatus == 0
|
33
|
+
when :postgresql
|
34
|
+
`dropdb -U #{config['username']} #{config['database']} &>/dev/null`
|
35
|
+
ret = `createdb -U #{config['username']} #{config['database']} 2>&1`
|
36
|
+
raise "error creating database: #{ret}" unless $?.exitstatus == 0
|
37
|
+
end
|
38
|
+
# Arel has an issue in that it keeps using original connection for quoting,
|
39
|
+
# etc. (which breaks stuff) unless you do this:
|
40
|
+
Arel::Visitors::ENGINE_VISITORS.delete(ActiveRecord::Base) if defined?(Arel)
|
41
|
+
ActiveRecord::Base.establish_connection(config)
|
42
|
+
ActiveRecord::Base.logger = Logger.new('/dev/null')
|
43
|
+
ActiveRecord::Migrator.migrate(HairTrigger.migration_path)
|
44
|
+
end
|
25
45
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
case adapter
|
30
|
-
when :mysql, :mysql2
|
31
|
-
ret = `echo "drop database if exists hairtrigger_schema_test; create database hairtrigger_schema_test;" | mysql hairtrigger_schema_test -u hairtrigger`
|
32
|
-
raise "error creating database: #{ret}" unless $?.exitstatus == 0
|
33
|
-
when :sqlite3
|
34
|
-
config[:database] = 'tmp/hairtrigger_schema_test.sqlite3'
|
35
|
-
when :postgresql
|
36
|
-
`dropdb -U hairtrigger hairtrigger_schema_test &>/dev/null`
|
37
|
-
ret = `createdb -U hairtrigger hairtrigger_schema_test 2>&1`
|
38
|
-
raise "error creating database: #{ret}" unless $?.exitstatus == 0
|
39
|
-
config[:min_messages] = :error
|
46
|
+
before :all do
|
47
|
+
@configs = YAML.load_file(File.expand_path(File.dirname(__FILE__) + '/../database.yml'))
|
48
|
+
@configs = @configs[ENV["DB_CONFIG"] || "test"]
|
40
49
|
end
|
41
|
-
# Arel has an issue in that it keeps using original connection for quoting,
|
42
|
-
# etc. (which breaks stuff) unless you do this:
|
43
|
-
Arel::Visitors::ENGINE_VISITORS.delete(ActiveRecord::Base) if defined?(Arel)
|
44
|
-
ActiveRecord::Base.establish_connection(config)
|
45
|
-
ActiveRecord::Base.logger = Logger.new('/dev/null')
|
46
|
-
ActiveRecord::Migrator.migrate(HairTrigger.migration_path)
|
47
|
-
end
|
48
50
|
|
49
|
-
describe "schema" do
|
50
51
|
[:mysql, :mysql2, :postgresql, :sqlite3].each do |adapter|
|
51
52
|
it "should correctly dump #{adapter}" do
|
52
53
|
ActiveRecord::Migration.verbose = false
|
metadata
CHANGED
@@ -1,319 +1,216 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: hairtrigger
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.0
|
5
5
|
prerelease:
|
6
|
-
segments:
|
7
|
-
- 0
|
8
|
-
- 1
|
9
|
-
- 14
|
10
|
-
version: 0.1.14
|
11
6
|
platform: ruby
|
12
|
-
authors:
|
7
|
+
authors:
|
13
8
|
- Jon Jensen
|
14
9
|
autorequire:
|
15
10
|
bindir: bin
|
16
11
|
cert_chain: []
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
dependencies:
|
21
|
-
- !ruby/object:Gem::Dependency
|
22
|
-
version_requirements: &id001 !ruby/object:Gem::Requirement
|
23
|
-
none: false
|
24
|
-
requirements:
|
25
|
-
- - ">="
|
26
|
-
- !ruby/object:Gem::Version
|
27
|
-
hash: 3
|
28
|
-
segments:
|
29
|
-
- 2
|
30
|
-
- 3
|
31
|
-
- 0
|
32
|
-
version: 2.3.0
|
33
|
-
prerelease: false
|
34
|
-
type: :runtime
|
35
|
-
requirement: *id001
|
12
|
+
date: 2012-12-04 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
36
15
|
name: activerecord
|
37
|
-
|
38
|
-
version_requirements: &id002 !ruby/object:Gem::Requirement
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
39
17
|
none: false
|
40
|
-
requirements:
|
41
|
-
- -
|
42
|
-
- !ruby/object:Gem::Version
|
43
|
-
|
44
|
-
segments:
|
45
|
-
- 2
|
46
|
-
- 0
|
47
|
-
- 6
|
48
|
-
version: 2.0.6
|
49
|
-
prerelease: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '2.3'
|
50
22
|
type: :runtime
|
51
|
-
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '2.3'
|
30
|
+
- !ruby/object:Gem::Dependency
|
52
31
|
name: ruby_parser
|
53
|
-
|
54
|
-
version_requirements: &id003 !ruby/object:Gem::Requirement
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
55
33
|
none: false
|
56
|
-
requirements:
|
57
|
-
- -
|
58
|
-
- !ruby/object:Gem::Version
|
59
|
-
|
60
|
-
segments:
|
61
|
-
- 1
|
62
|
-
- 2
|
63
|
-
- 5
|
64
|
-
version: 1.2.5
|
65
|
-
prerelease: false
|
34
|
+
requirements:
|
35
|
+
- - '='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: 2.0.6
|
66
38
|
type: :runtime
|
67
|
-
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - '='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 2.0.6
|
46
|
+
- !ruby/object:Gem::Dependency
|
68
47
|
name: ruby2ruby
|
69
|
-
|
70
|
-
version_requirements: &id004 !ruby/object:Gem::Requirement
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
71
49
|
none: false
|
72
|
-
requirements:
|
73
|
-
- -
|
74
|
-
- !ruby/object:Gem::Version
|
75
|
-
|
76
|
-
|
77
|
-
- 2
|
78
|
-
- 3
|
79
|
-
- 0
|
80
|
-
version: 2.3.0
|
50
|
+
requirements:
|
51
|
+
- - '='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 1.2.5
|
54
|
+
type: :runtime
|
81
55
|
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - '='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 1.2.5
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: rake
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
82
70
|
type: :development
|
83
|
-
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
84
79
|
name: rspec
|
85
|
-
|
86
|
-
version_requirements: &id005 !ruby/object:Gem::Requirement
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
87
81
|
none: false
|
88
|
-
requirements:
|
82
|
+
requirements:
|
89
83
|
- - ~>
|
90
|
-
- !ruby/object:Gem::Version
|
91
|
-
|
92
|
-
segments:
|
93
|
-
- 1
|
94
|
-
- 0
|
95
|
-
- 0
|
96
|
-
version: 1.0.0
|
97
|
-
prerelease: false
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: 2.12.0
|
98
86
|
type: :development
|
99
|
-
|
100
|
-
|
101
|
-
- !ruby/object:Gem::Dependency
|
102
|
-
version_requirements: &id006 !ruby/object:Gem::Requirement
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
103
89
|
none: false
|
104
|
-
requirements:
|
90
|
+
requirements:
|
105
91
|
- - ~>
|
106
|
-
- !ruby/object:Gem::Version
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
- 1
|
112
|
-
version: 1.6.1
|
113
|
-
prerelease: false
|
114
|
-
type: :development
|
115
|
-
requirement: *id006
|
116
|
-
name: jeweler
|
117
|
-
- !ruby/object:Gem::Dependency
|
118
|
-
version_requirements: &id007 !ruby/object:Gem::Requirement
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: 2.12.0
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: mysql
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
119
97
|
none: false
|
120
|
-
requirements:
|
121
|
-
- -
|
122
|
-
- !ruby/object:Gem::Version
|
123
|
-
|
124
|
-
segments:
|
125
|
-
- 0
|
126
|
-
version: "0"
|
127
|
-
prerelease: false
|
98
|
+
requirements:
|
99
|
+
- - ~>
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: 2.8.1
|
128
102
|
type: :development
|
129
|
-
|
130
|
-
|
131
|
-
- !ruby/object:Gem::Dependency
|
132
|
-
version_requirements: &id008 !ruby/object:Gem::Requirement
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
133
105
|
none: false
|
134
|
-
requirements:
|
135
|
-
- -
|
136
|
-
- !ruby/object:Gem::Version
|
137
|
-
hash: 45
|
138
|
-
segments:
|
139
|
-
- 2
|
140
|
-
- 8
|
141
|
-
- 1
|
106
|
+
requirements:
|
107
|
+
- - ~>
|
108
|
+
- !ruby/object:Gem::Version
|
142
109
|
version: 2.8.1
|
143
|
-
|
144
|
-
|
145
|
-
requirement:
|
146
|
-
name: mysql
|
147
|
-
- !ruby/object:Gem::Dependency
|
148
|
-
version_requirements: &id009 !ruby/object:Gem::Requirement
|
110
|
+
- !ruby/object:Gem::Dependency
|
111
|
+
name: mysql2
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
149
113
|
none: false
|
150
|
-
requirements:
|
151
|
-
- -
|
152
|
-
- !ruby/object:Gem::Version
|
153
|
-
hash: 13
|
154
|
-
segments:
|
155
|
-
- 0
|
156
|
-
- 3
|
157
|
-
version: "0.3"
|
158
|
-
- - ">="
|
159
|
-
- !ruby/object:Gem::Version
|
160
|
-
hash: 25
|
161
|
-
segments:
|
162
|
-
- 0
|
163
|
-
- 2
|
164
|
-
- 7
|
114
|
+
requirements:
|
115
|
+
- - ! '>='
|
116
|
+
- !ruby/object:Gem::Version
|
165
117
|
version: 0.2.7
|
166
|
-
prerelease: false
|
167
118
|
type: :development
|
168
|
-
requirement: *id009
|
169
|
-
name: mysql2
|
170
|
-
- !ruby/object:Gem::Dependency
|
171
|
-
version_requirements: &id010 !ruby/object:Gem::Requirement
|
172
|
-
none: false
|
173
|
-
requirements:
|
174
|
-
- - ">="
|
175
|
-
- !ruby/object:Gem::Version
|
176
|
-
hash: 53
|
177
|
-
segments:
|
178
|
-
- 0
|
179
|
-
- 10
|
180
|
-
- 1
|
181
|
-
version: 0.10.1
|
182
119
|
prerelease: false
|
183
|
-
|
184
|
-
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
122
|
+
requirements:
|
123
|
+
- - ! '>='
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: 0.2.7
|
126
|
+
- !ruby/object:Gem::Dependency
|
185
127
|
name: pg
|
186
|
-
|
187
|
-
version_requirements: &id011 !ruby/object:Gem::Requirement
|
128
|
+
requirement: !ruby/object:Gem::Requirement
|
188
129
|
none: false
|
189
|
-
requirements:
|
190
|
-
- -
|
191
|
-
- !ruby/object:Gem::Version
|
192
|
-
|
193
|
-
segments:
|
194
|
-
- 1
|
195
|
-
- 3
|
196
|
-
- 2
|
197
|
-
version: 1.3.2
|
198
|
-
prerelease: false
|
130
|
+
requirements:
|
131
|
+
- - ! '>='
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: 0.10.1
|
199
134
|
type: :development
|
200
|
-
requirement: *id011
|
201
|
-
name: sqlite3-ruby
|
202
|
-
- !ruby/object:Gem::Dependency
|
203
|
-
version_requirements: &id012 !ruby/object:Gem::Requirement
|
204
|
-
none: false
|
205
|
-
requirements:
|
206
|
-
- - "="
|
207
|
-
- !ruby/object:Gem::Version
|
208
|
-
hash: 63
|
209
|
-
segments:
|
210
|
-
- 0
|
211
|
-
- 10
|
212
|
-
- 4
|
213
|
-
version: 0.10.4
|
214
135
|
prerelease: false
|
215
|
-
|
216
|
-
requirement: *id012
|
217
|
-
name: ruby-debug
|
218
|
-
- !ruby/object:Gem::Dependency
|
219
|
-
version_requirements: &id013 !ruby/object:Gem::Requirement
|
136
|
+
version_requirements: !ruby/object:Gem::Requirement
|
220
137
|
none: false
|
221
|
-
requirements:
|
222
|
-
- -
|
223
|
-
- !ruby/object:Gem::Version
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
- 0
|
229
|
-
version: 2.3.0
|
230
|
-
prerelease: false
|
231
|
-
type: :runtime
|
232
|
-
requirement: *id013
|
233
|
-
name: activerecord
|
234
|
-
- !ruby/object:Gem::Dependency
|
235
|
-
version_requirements: &id014 !ruby/object:Gem::Requirement
|
138
|
+
requirements:
|
139
|
+
- - ! '>='
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
version: 0.10.1
|
142
|
+
- !ruby/object:Gem::Dependency
|
143
|
+
name: sqlite3
|
144
|
+
requirement: !ruby/object:Gem::Requirement
|
236
145
|
none: false
|
237
|
-
requirements:
|
238
|
-
- -
|
239
|
-
- !ruby/object:Gem::Version
|
240
|
-
|
241
|
-
segments:
|
242
|
-
- 2
|
243
|
-
- 3
|
244
|
-
- 0
|
245
|
-
version: 2.3.0
|
246
|
-
prerelease: false
|
146
|
+
requirements:
|
147
|
+
- - ! '>='
|
148
|
+
- !ruby/object:Gem::Version
|
149
|
+
version: 1.3.6
|
247
150
|
type: :development
|
248
|
-
|
249
|
-
|
250
|
-
|
151
|
+
prerelease: false
|
152
|
+
version_requirements: !ruby/object:Gem::Requirement
|
153
|
+
none: false
|
154
|
+
requirements:
|
155
|
+
- - ! '>='
|
156
|
+
- !ruby/object:Gem::Version
|
157
|
+
version: 1.3.6
|
158
|
+
description: allows you to declare database triggers in ruby in your models, and then
|
159
|
+
generate appropriate migrations as they change
|
251
160
|
email: jenseng@gmail.com
|
252
161
|
executables: []
|
253
|
-
|
254
162
|
extensions: []
|
255
|
-
|
256
|
-
extra_rdoc_files:
|
257
|
-
- LICENSE.txt
|
163
|
+
extra_rdoc_files:
|
258
164
|
- README.rdoc
|
259
|
-
files:
|
260
|
-
- .document
|
261
|
-
- .rspec
|
262
|
-
- Gemfile
|
165
|
+
files:
|
263
166
|
- LICENSE.txt
|
264
|
-
- README.rdoc
|
265
167
|
- Rakefile
|
266
|
-
-
|
267
|
-
- init.rb
|
268
|
-
- lib/hair_trigger.rb
|
168
|
+
- README.rdoc
|
269
169
|
- lib/hair_trigger/adapter.rb
|
270
170
|
- lib/hair_trigger/base.rb
|
271
171
|
- lib/hair_trigger/builder.rb
|
272
172
|
- lib/hair_trigger/migration_reader.rb
|
273
173
|
- lib/hair_trigger/migrator.rb
|
174
|
+
- lib/hair_trigger/railtie.rb
|
274
175
|
- lib/hair_trigger/schema_dumper.rb
|
176
|
+
- lib/hair_trigger/version.rb
|
177
|
+
- lib/hair_trigger.rb
|
178
|
+
- lib/hairtrigger.rb
|
275
179
|
- lib/tasks/hair_trigger.rake
|
276
|
-
- rails/init.rb
|
277
180
|
- spec/builder_spec.rb
|
278
181
|
- spec/migrations/20110331212003_initial_tables.rb
|
279
182
|
- spec/migrations/20110331212631_user_trigger.rb
|
280
183
|
- spec/migrations/20110417185102_manual_user_trigger.rb
|
184
|
+
- spec/migrations-pre-3.1/20110331212003_initial_tables.rb
|
185
|
+
- spec/migrations-pre-3.1/20110331212631_user_trigger.rb
|
186
|
+
- spec/migrations-pre-3.1/20110417185102_manual_user_trigger.rb
|
281
187
|
- spec/models/group.rb
|
282
188
|
- spec/models/user.rb
|
283
189
|
- spec/schema_dumper_spec.rb
|
284
|
-
has_rdoc: true
|
285
190
|
homepage: http://github.com/jenseng/hair_trigger
|
286
|
-
licenses:
|
191
|
+
licenses:
|
287
192
|
- MIT
|
288
193
|
post_install_message:
|
289
194
|
rdoc_options: []
|
290
|
-
|
291
|
-
require_paths:
|
195
|
+
require_paths:
|
292
196
|
- lib
|
293
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
197
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
294
198
|
none: false
|
295
|
-
requirements:
|
296
|
-
- -
|
297
|
-
- !ruby/object:Gem::Version
|
298
|
-
|
299
|
-
|
300
|
-
- 0
|
301
|
-
version: "0"
|
302
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
199
|
+
requirements:
|
200
|
+
- - ! '>='
|
201
|
+
- !ruby/object:Gem::Version
|
202
|
+
version: 1.8.7
|
203
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
303
204
|
none: false
|
304
|
-
requirements:
|
305
|
-
- -
|
306
|
-
- !ruby/object:Gem::Version
|
307
|
-
|
308
|
-
segments:
|
309
|
-
- 0
|
310
|
-
version: "0"
|
205
|
+
requirements:
|
206
|
+
- - ! '>='
|
207
|
+
- !ruby/object:Gem::Version
|
208
|
+
version: 1.3.5
|
311
209
|
requirements: []
|
312
|
-
|
313
210
|
rubyforge_project:
|
314
|
-
rubygems_version: 1.
|
211
|
+
rubygems_version: 1.8.24
|
315
212
|
signing_key:
|
316
213
|
specification_version: 3
|
317
214
|
summary: easy database triggers for active record
|
318
215
|
test_files: []
|
319
|
-
|
216
|
+
has_rdoc:
|
data/.document
DELETED
data/.rspec
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
--color
|
data/Gemfile
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
source "http://rubygems.org"
|
2
|
-
|
3
|
-
gem "activerecord", ">=2.3.0"
|
4
|
-
gem 'ruby_parser', '2.0.6'
|
5
|
-
gem 'ruby2ruby', '1.2.5'
|
6
|
-
group :development do
|
7
|
-
gem "rspec", "~> 2.3.0"
|
8
|
-
gem "bundler", "~> 1.0.0"
|
9
|
-
gem "jeweler", "~> 1.6.1"
|
10
|
-
gem "rcov", ">= 0"
|
11
|
-
gem 'mysql', '>= 2.8.1'
|
12
|
-
gem 'mysql2', '>= 0.2.7', '< 0.3'
|
13
|
-
gem 'pg', '>= 0.10.1'
|
14
|
-
gem 'sqlite3-ruby', '>= 1.3.2'
|
15
|
-
gem 'ruby-debug', '0.10.4'
|
16
|
-
end
|
data/VERSION
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
0.1.14
|
data/rails/init.rb
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
require 'hair_trigger'
|