tern 0.7.0 → 0.7.1

Sign up to get free protection for your applications and to get access to all the features.
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --colour
@@ -211,6 +211,14 @@ This will result in:
211
211
 
212
212
  DROP FUNCTION rendered_function();
213
213
 
214
+ Version History
215
+ ===============
216
+
217
+ * **0.7.1**
218
+ * Print friendly error message when database error occurs instead of stack trace.
219
+ * **0.7.0**
220
+ * Added ERB processing to SQL files
221
+
214
222
  License
215
223
  =======
216
224
 
@@ -2,6 +2,9 @@ require 'sequel'
2
2
  require 'yaml'
3
3
  require 'erb'
4
4
 
5
+ class TernError < StandardError
6
+ end
7
+
5
8
  class Parser
6
9
  def render_text(text)
7
10
  ERB.new(text).result(binding)
@@ -14,12 +17,25 @@ class Parser
14
17
  end
15
18
 
16
19
  class Change
20
+ class DatabaseError < TernError
21
+ end
22
+
17
23
  SPLIT_MARKER = '---- CREATE above / DROP below ----'
18
24
 
19
25
  def self.parse(string)
20
26
  create_sql, drop_sql = Parser.new.render_text(string).split(SPLIT_MARKER)
21
27
  [create_sql, drop_sql]
22
28
  end
29
+
30
+ def run(sql, context)
31
+ DB.run sql
32
+ rescue Sequel::DatabaseError
33
+ raise DatabaseError, "Error in #{context}\n#{$!.to_s}"
34
+ end
35
+
36
+ attr_reader :create_sql
37
+ attr_reader :drop_sql
38
+ attr_reader :name
23
39
  end
24
40
 
25
41
  class Definition < Change
@@ -41,7 +57,7 @@ class Definition < Change
41
57
 
42
58
  def load_existing
43
59
  table.order(:id).all.map do |row|
44
- new row[:id], row[:sequence], row[:create_sql], row[:drop_sql]
60
+ new "existing definition: #{row[:id]}", row[:id], row[:sequence], row[:create_sql], row[:drop_sql]
45
61
  end.group_by { |d| d.sequence }
46
62
  end
47
63
 
@@ -51,8 +67,9 @@ class Definition < Change
51
67
 
52
68
  definition_sequences.keys.each do |sequence|
53
69
  definition_sequences[sequence] = definition_sequences[sequence].map do |f|
54
- create_sql, drop_sql = parse File.read(File.join(sequence_dir, f))
55
- Definition.new nil, sequence, create_sql, drop_sql
70
+ path = File.join(sequence_dir, f)
71
+ create_sql, drop_sql = parse File.read(path)
72
+ Definition.new path, nil, sequence, create_sql, drop_sql
56
73
  end
57
74
  end
58
75
 
@@ -62,10 +79,9 @@ class Definition < Change
62
79
 
63
80
  attr_reader :id
64
81
  attr_reader :sequence
65
- attr_reader :create_sql
66
- attr_reader :drop_sql
67
-
68
- def initialize(id, sequence, create_sql, drop_sql)
82
+
83
+ def initialize(name, id, sequence, create_sql, drop_sql)
84
+ @name = name
69
85
  @id = id
70
86
  @sequence = sequence
71
87
  @create_sql = create_sql
@@ -73,12 +89,12 @@ class Definition < Change
73
89
  end
74
90
 
75
91
  def create
76
- DB.run create_sql
92
+ run create_sql, name
77
93
  table.insert :sequence => sequence, :create_sql => create_sql, :drop_sql => drop_sql
78
94
  end
79
95
 
80
96
  def drop
81
- DB.run drop_sql
97
+ run drop_sql, name
82
98
  table.filter(:id => id).delete
83
99
  end
84
100
 
@@ -88,13 +104,13 @@ class Definition < Change
88
104
  end
89
105
 
90
106
  class Alteration < Change
91
- class IrreversibleAlteration < StandardError
107
+ class IrreversibleAlteration < TernError
92
108
  end
93
109
 
94
- class MissingAlteration < StandardError
110
+ class MissingAlteration < TernError
95
111
  end
96
112
 
97
- class DuplicateAlteration < StandardError
113
+ class DuplicateAlteration < TernError
98
114
  end
99
115
 
100
116
  class << self
@@ -126,7 +142,7 @@ class Alteration < Change
126
142
  raise "This can't happen" unless File.basename(path) =~ /^(\d+)/
127
143
  version = $1.to_i
128
144
  create_sql, drop_sql = parse File.read(path)
129
- new version, create_sql, drop_sql
145
+ new path, version, create_sql, drop_sql
130
146
  end.sort_by(&:version)
131
147
 
132
148
  alterations.each_with_index do |a, i|
@@ -140,23 +156,22 @@ class Alteration < Change
140
156
  end
141
157
 
142
158
  attr_reader :version
143
- attr_reader :create_sql
144
- attr_reader :drop_sql
145
159
 
146
- def initialize(version, create_sql, drop_sql)
160
+ def initialize(name, version, create_sql, drop_sql)
161
+ @name = name
147
162
  @version = version
148
163
  @create_sql = create_sql
149
164
  @drop_sql = drop_sql
150
165
  end
151
166
 
152
167
  def create
153
- DB.run create_sql
168
+ run create_sql, name
154
169
  Alteration.version = version
155
170
  end
156
171
 
157
172
  def drop
158
173
  raise IrreversibleAlteration, "Alteration #{version.to_s.rjust(3, "0")} is irreversible" unless drop_sql
159
- DB.run drop_sql
174
+ run drop_sql, name
160
175
  Alteration.version = version - 1
161
176
  end
162
177
  end
@@ -33,7 +33,7 @@ class App < Thor
33
33
  begin
34
34
  tern = Tern.new(config['alterations']['table'], config['alterations']['column'], config['definitions']['table'])
35
35
  tern.migrate(:version => options["alteration_version"], :sequences => options["definition_sequences"])
36
- rescue Alteration::IrreversibleAlteration, Alteration::MissingAlteration, Alteration::DuplicateAlteration
36
+ rescue TernError
37
37
  say $!, :red
38
38
  end
39
39
  end
@@ -0,0 +1,8 @@
1
+ CREATE TABLE people(
2
+ id serial PRIMARY KEY,
3
+ name varchar NOT NULL
4
+ );
5
+
6
+ ---- CREATE above / DROP below ----
7
+
8
+ DROP TABLE people;
@@ -0,0 +1,8 @@
1
+ CREATE TABLE animals(
2
+ id serial PRIMARY KEY,
3
+ name varchar NOT NULL
4
+ );
5
+
6
+ ---- CREATE above / DROP below ----
7
+
8
+ DROP TABLE animals;
@@ -0,0 +1,10 @@
1
+ INVALID SQL;
2
+
3
+ CREATE TABLE plants(
4
+ id serial PRIMARY KEY,
5
+ name varchar NOT NULL
6
+ );
7
+
8
+ ---- CREATE above / DROP below ----
9
+
10
+ DROP TABLE plants;
@@ -0,0 +1,15 @@
1
+ alterations:
2
+ table: tern_alterations
3
+ column: version
4
+ definitions:
5
+ table: tern_definitions
6
+ environments:
7
+ development:
8
+ adapter: postgres
9
+ database: tern_test_development
10
+ test:
11
+ adapter: postgres
12
+ database: tern_test_test
13
+ production:
14
+ adapter: postgres
15
+ database: tern_test_production
@@ -0,0 +1,18 @@
1
+ # Put the relative path to your definition files in the sequence they should run.
2
+ #
3
+ # Most definitions should go in the default list. These will be dropped and
4
+ # recreated every migration.
5
+ #
6
+ # Definitions that should not automatically be dropped and created can be put in
7
+ # different lists. This is useful for definitions that make take prohibitively
8
+ # to drop and create every migration such as check constraints.
9
+ #
10
+ # Run alternative sequences by specifying sequences in order to migrate command.
11
+ # Example: rake migrate sequences=expensive,default
12
+ #
13
+ # default:
14
+ # - ultimate_answer.sql
15
+ # expensive:
16
+ # - super_slow_check_constraint.sql
17
+
18
+ default: []
@@ -0,0 +1,7 @@
1
+ CREATE FUNCTION ultimate_answer() RETURNS integer AS $$
2
+ SELECT 42;
3
+ $$ LANGUAGE SQL;
4
+
5
+ ---- CREATE above / DROP below ----
6
+
7
+ DROP FUNCTION ultimate_answer();
@@ -0,0 +1,16 @@
1
+ Sequel.migration do
2
+ up do
3
+ run <<-END_SQL
4
+ CREATE TABLE people(
5
+ id serial PRIMARY KEY,
6
+ name varchar NOT NULL
7
+ );
8
+ END_SQL
9
+ end
10
+
11
+ down do
12
+ run <<-END_SQL
13
+ DROP TABLE people;
14
+ END_SQL
15
+ end
16
+ end
@@ -0,0 +1,15 @@
1
+ alterations:
2
+ table: tern_alterations
3
+ column: version
4
+ definitions:
5
+ table: tern_definitions
6
+ environments:
7
+ development:
8
+ adapter: postgres
9
+ database: tern_test_development
10
+ test:
11
+ adapter: postgres
12
+ database: tern_test_test
13
+ production:
14
+ adapter: postgres
15
+ database: tern_test_production
@@ -0,0 +1,19 @@
1
+ # Put the relative path to your definition files in the sequence they should run.
2
+ #
3
+ # Most definitions should go in the default list. These will be dropped and
4
+ # recreated every migration.
5
+ #
6
+ # Definitions that should not automatically be dropped and created can be put in
7
+ # different lists. This is useful for definitions that make take prohibitively
8
+ # to drop and create every migration such as check constraints.
9
+ #
10
+ # Run alternative sequences by specifying sequences in order to migrate command.
11
+ # Example: rake migrate sequences=expensive,default
12
+ #
13
+ # default:
14
+ # - ultimate_answer.sql
15
+ # expensive:
16
+ # - super_slow_check_constraint.sql
17
+
18
+ default:
19
+ - ultimate_answer.sql
@@ -0,0 +1,9 @@
1
+ INVALID SQL;
2
+
3
+ CREATE FUNCTION ultimate_answer() RETURNS integer AS $$
4
+ SELECT 42;
5
+ $$ LANGUAGE SQL;
6
+
7
+ ---- CREATE above / DROP below ----
8
+
9
+ DROP FUNCTION ultimate_answer();
@@ -233,5 +233,19 @@ describe "tern" do
233
233
  expect { @dev_db[:a].all }.to raise_error(Sequel::DatabaseError)
234
234
  end
235
235
  end
236
+
237
+ context "alteration with database error" do
238
+ it "prints an error message with file name" do
239
+ tern_migrate("spec/projects/alteration_with_error").should match /Error in alterations\/003_create_plants.sql/
240
+ end
241
+ end
242
+
243
+ context "definition with database error" do
244
+ it "prints an error message with file name" do
245
+ tern_migrate("spec/projects/definition_with_error").should match /Error in definitions\/ultimate_answer.sql/
246
+ end
247
+ end
248
+
249
+
236
250
  end
237
251
  end
@@ -3,7 +3,7 @@ $:.push File.expand_path("../lib", __FILE__)
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = "tern"
6
- s.version = '0.7.0'
6
+ s.version = '0.7.1'
7
7
  s.platform = Gem::Platform::RUBY
8
8
  s.authors = ["Jack Christensen"]
9
9
  s.email = ["jack@jackchristensen.com"]
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 7
8
- - 0
9
- version: 0.7.0
8
+ - 1
9
+ version: 0.7.1
10
10
  platform: ruby
11
11
  authors:
12
12
  - Jack Christensen
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2011-04-06 00:00:00 -05:00
17
+ date: 2011-06-25 00:00:00 -05:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -73,6 +73,7 @@ extra_rdoc_files: []
73
73
 
74
74
  files:
75
75
  - .gitignore
76
+ - .rspec
76
77
  - MIT-LICENSE
77
78
  - README.markdown
78
79
  - Rakefile
@@ -85,12 +86,22 @@ files:
85
86
  - lib/tern/generators/new/config.yml.tt
86
87
  - lib/tern/generators/new/definitions/sequence.yml
87
88
  - lib/tern/generators/new/definitions/ultimate_answer.sql.example
89
+ - spec/projects/alteration_with_error/alterations/001_create_people.sql
90
+ - spec/projects/alteration_with_error/alterations/002_create_animals.sql
91
+ - spec/projects/alteration_with_error/alterations/003_create_plants.sql
92
+ - spec/projects/alteration_with_error/config.yml
93
+ - spec/projects/alteration_with_error/definitions/sequence.yml
94
+ - spec/projects/alteration_with_error/definitions/ultimate_answer.sql.example
88
95
  - spec/projects/alterations/alterations/001_create_people.sql
89
96
  - spec/projects/alterations/alterations/002_create_animals.sql
90
97
  - spec/projects/alterations/alterations/003_create_plants.sql
91
98
  - spec/projects/alterations/config.yml
92
99
  - spec/projects/alterations/definitions/sequence.yml
93
100
  - spec/projects/alterations/definitions/ultimate_answer.sql.example
101
+ - spec/projects/definition_with_error/alterations/001_create_people.sql.example
102
+ - spec/projects/definition_with_error/config.yml
103
+ - spec/projects/definition_with_error/definitions/sequence.yml
104
+ - spec/projects/definition_with_error/definitions/ultimate_answer.sql
94
105
  - spec/projects/definitions/alterations/001_create_people.sql.example
95
106
  - spec/projects/definitions/config.yml
96
107
  - spec/projects/definitions/definitions/sequence.yml