rails_db_views 0.0.3 → 0.0.4

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
2
  SHA1:
3
- metadata.gz: 6edc610e6b4cbd12093917e89a779067b9b78608
4
- data.tar.gz: 7ecebff3dbe8ff7c5d95161f65f543b69135ea64
3
+ metadata.gz: ff2f855836b239c4af2dae529189588761c22ff3
4
+ data.tar.gz: 027d2f0e0f45ddb654d5ba70f4613219aa581eba
5
5
  SHA512:
6
- metadata.gz: 0a986ce2241177d8f7f1757c88da836ed636bb9393bd2c04e64f02ca85a6217a4aed40799dae0bc40a29403910154e6d4d153a160c9e602b5d60bd3fee96b470
7
- data.tar.gz: 3083faeccd65ab15521d93ef971d3b48dfceaf0a4b82522f023dc2ce7fea2ebad721cd76e7a9abb68ae9678fbc907b65e2951175e48fdb9a8d1e91ac4c4a9441
6
+ metadata.gz: c1289482ced1e66da617ad275fd184e68fd2050aaa1ed0f53288066931e35418a6424ab4e7b09fc2bef98e598a90c382bb3d7311ff5107344061ed80b31d7bcd
7
+ data.tar.gz: 871085dcaac1dc9663bdc6c4b4ce983f9e9d9be8363c41f0cfeced6ca70023334598d09c9481efbca3aaa722411d7412fe6cefe23653e225a7d388e3b4e76f7e
@@ -0,0 +1,16 @@
1
+ class RailsDbViews::Configuration
2
+ attr_accessor :views_paths, :views_extension
3
+ attr_accessor :functions_paths, :functions_extension
4
+
5
+ def initialize
6
+ @views_paths = %w(db/views)
7
+ @views_extension = "*.sql"
8
+
9
+ @functions_paths = %w(db/functions)
10
+ @functions_extension = "*.sql"
11
+ end
12
+
13
+ def [] *args
14
+ raise "rails_db_view has changed! Please use the methods views_paths/views_extension instead of hash notation"
15
+ end
16
+ end
@@ -0,0 +1,138 @@
1
+ class RailsDbViews::DatabaseSymbol
2
+ class CircularReferenceError < RuntimeError; end
3
+ class SymbolNotFound < RuntimeError; end
4
+
5
+ attr_accessor :path, :sql_content, :status, :required, :inverse_of_required, :marked_as_deleted, :name
6
+ alias :marked_as_deleted? :marked_as_deleted
7
+
8
+ module Status
9
+ LOADED = :loaded
10
+ IN_PROGRESS = :in_progress
11
+ UNLOADED = :unloaded
12
+ end
13
+
14
+ def initialize file_path
15
+ @path = file_path
16
+ @name = File.basename(file_path, ".*")
17
+
18
+ @status = :none
19
+ @required = []
20
+ @marked_as_deleted = false
21
+ @sql_content = File.read(@path)
22
+ @inverse_of_required = []
23
+
24
+ load_directives
25
+ end
26
+
27
+ def process_inverse_of_required!
28
+ @required.each do |name|
29
+ required = RailsDbViews::Factory.get(self.class, name)
30
+ not_found_error if required.nil?
31
+ required.inverse_of_required << self.name
32
+ end
33
+ end
34
+
35
+ def mark_as_delete!
36
+ @marked_as_deleted = true
37
+ end
38
+
39
+ def loaded?
40
+ status == Status::LOADED
41
+ end
42
+
43
+ def in_progress?
44
+ status == Status::IN_PROGRESS
45
+ end
46
+
47
+ def unloaded?
48
+ status == Status::UNLOADED
49
+ end
50
+
51
+ def create!
52
+ return if marked_as_deleted? || loaded?
53
+
54
+ circular_reference_error if in_progress?
55
+
56
+ self.status = Status::IN_PROGRESS
57
+
58
+ required.each do |symbol_name|
59
+ symbol = RailsDbViews::Factory.get(self.class, symbol_name)
60
+ not_found_error(symbol_name) if symbol.nil?
61
+ symbol.create!
62
+ end
63
+
64
+ ActiveRecord::Base.connection.execute(create_sql)
65
+
66
+ self.status = Status::LOADED
67
+ end
68
+
69
+ def drop!
70
+ return if loaded?
71
+
72
+ circular_reference_error if in_progress?
73
+
74
+ self.status = Status::IN_PROGRESS
75
+
76
+ # We start by the required one to delete first.
77
+ inverse_of_required.each do |symbol_name|
78
+ symbol = RailsDbViews::Factory.get(self.class, symbol_name)
79
+ not_found_error(symbol_name) if symbol.nil?
80
+ symbol.drop!
81
+ end
82
+
83
+ begin
84
+ ActiveRecord::Base.connection.execute(drop_sql)
85
+ #rescue ActiveRecord::ActiveRecordError => e #Probably because the symbol doesn't exists yet.
86
+ # handle_error_on_drop
87
+ end
88
+
89
+ self.status = Status::LOADED
90
+ end
91
+
92
+ # Theses methods should be implemented in children objects.
93
+ def drop_sql
94
+ raise NotImplementedError, "DatabaseSymbol should not be instanciated"
95
+ end
96
+
97
+ def create_sql
98
+ raise NotImplementedError, "DatabaseSymbol should not be instanciated"
99
+ end
100
+
101
+ def handle_error_on_drop
102
+ raise NotImplementedError, "DatabaseSymbol should not be instanciated"
103
+ end
104
+
105
+ protected
106
+ TWO_DASH_DIRECTIVE_START = /^--[ \t]*!/
107
+ SHARP_CHAR_DIRECTIVE_START = /^#[ \t]*!/
108
+ DIRECTIVE_START = /#{TWO_DASH_DIRECTIVE_START}|#{SHARP_CHAR_DIRECTIVE_START}/
109
+
110
+ def circular_reference_error
111
+ raise CircularReferenceError, "Circular file reference! (file: #{path})"
112
+ end
113
+
114
+ def not_found_error(symbol_name)
115
+ raise SymbolNotFound, "#{self.class.name} `#{symbol_name}` referenced in file #{path} cannot be found..."
116
+ end
117
+
118
+ def load_directives
119
+ content_lines = sql_content.split("\n")
120
+
121
+ directives = content_lines.map(&:strip).select{ |x| x =~ DIRECTIVE_START }.map{ |x|
122
+ x.gsub(DIRECTIVE_START, "")
123
+ }
124
+
125
+ directives.each do |d|
126
+ case d
127
+ when /^require /
128
+ self.required += d.split(/[ \t]+/)[1..-1]
129
+ when /^delete(d?) /
130
+ self.mark_as_delete!
131
+ else
132
+ raise IllegalDirective, "I don't know what to do with `#{d}` (in #{path})"
133
+ end
134
+ end
135
+
136
+ end
137
+
138
+ end
@@ -0,0 +1,46 @@
1
+
2
+ class RailsDbViews::Factory
3
+ class AmbigousNameError < RuntimeError; end
4
+
5
+ @symbols = {}
6
+
7
+ class << self
8
+ attr_reader :symbols
9
+
10
+ def register_files symbol_class, files
11
+ @symbols[symbol_class.to_s] ||= {}
12
+
13
+ files.each do |file|
14
+ symbol = symbol_class.new(file)
15
+
16
+ if s=@symbols[symbol_class.to_s][symbol.name]
17
+ raise AmbigousNameError, "between #{file} and #{s.path}"
18
+ end
19
+
20
+ @symbols[symbol_class.to_s][symbol.name] = symbol
21
+ end
22
+
23
+ @symbols.values.map(&:values).flatten.each(&:process_inverse_of_required!)
24
+ end
25
+
26
+ def drop(symbol_class)
27
+ symbol_list = @symbols[symbol_class.to_s]
28
+
29
+ symbol_list.values.each(&:drop!) if symbol_list
30
+ end
31
+
32
+ def create(symbol_class)
33
+ symbol_list = @symbols[symbol_class.to_s]
34
+
35
+ symbol_list.values.each(&:create!) if symbol_list
36
+ end
37
+
38
+ def get(symbol_class, name)
39
+ (@symbols[symbol_class.to_s]||{})[name]
40
+ end
41
+
42
+ def clear!
43
+ @symbols = {}
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,15 @@
1
+ class RailsDbViews::Function < RailsDbViews::DatabaseSymbol
2
+ def create_sql
3
+ puts "CREATE OR REPLACE FUNCTION #{name}..."
4
+ "CREATE OR REPLACE FUNCTION #{name} #{sql_content}"
5
+ end
6
+
7
+ def drop_sql
8
+ puts "DROP FUNCTION #{name}..."
9
+ "DROP FUNCTION #{name}"
10
+ end
11
+
12
+ def handle_error_on_drop
13
+ puts "WARNING: DROP FUNCTION #{name}... ERROR"
14
+ end
15
+ end
@@ -1,11 +1,11 @@
1
- class Railtie < Rails::Railtie
1
+ require 'rails_db_views/configuration'
2
+
3
+ class RailsDbViews::Railtie < Rails::Railtie
2
4
  railtie_name :rails_db_views
3
5
 
4
- config.rails_db_views = ActiveSupport::OrderedHash.new
6
+ config.rails_db_views = RailsDbViews::Configuration.new
5
7
 
6
8
  initializer "rails_db_views.initialize" do |app|
7
- app.config.rails_db_views[:views_path] = %w( db/views )
8
- app.config.rails_db_views[:views_ext] = "*.sql"
9
9
  end
10
10
 
11
11
  rake_tasks do
@@ -1,3 +1,3 @@
1
1
  module RailsDbViews
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.4"
3
3
  end
@@ -0,0 +1,15 @@
1
+ class RailsDbViews::View < RailsDbViews::DatabaseSymbol
2
+ def create_sql
3
+ puts "CREATE VIEW #{name}..."
4
+ "CREATE VIEW #{name} AS #{sql_content}"
5
+ end
6
+
7
+ def drop_sql
8
+ puts "DROP VIEW #{name}..."
9
+ "DROP VIEW #{name}"
10
+ end
11
+
12
+ def handle_error_on_drop
13
+ puts "WARNING: DROP VIEW #{name}... ERROR"
14
+ end
15
+ end
@@ -1,4 +1,11 @@
1
1
  module RailsDbViews
2
- require 'rails_db_views/railtie' if defined?(Rails)
3
- require 'rails_db_views/db_views_creator'
2
+ unless defined?(Rails)
3
+ raise "This gem is made for Ruby on Rails!"
4
+ end
4
5
  end
6
+
7
+ require 'rails_db_views/railtie'
8
+ require 'rails_db_views/database_symbol'
9
+ require 'rails_db_views/view'
10
+ require 'rails_db_views/function'
11
+ require 'rails_db_views/factory'
@@ -1,44 +1,55 @@
1
- namespace :db do
1
+ def apply_to paths, extension, method, klazz
2
+ RailsDbViews::Factory.clear!
2
3
 
3
- desc "Generate all the database views of the current project"
4
- task :create_views => :environment do
5
- creator = RailsDbViews::DbViewsCreator.new
4
+ paths.each do |path|
5
+ RailsDbViews::Factory.register_files klazz,
6
+ Dir[File.join(path, extension)].map{|x| File.expand_path(x)}
7
+ end
6
8
 
7
- views_path, views_ext = Rails.configuration.rails_db_views[:views_path], Rails.configuration.rails_db_views[:views_ext]
9
+ RailsDbViews::Factory.send(method, klazz)
10
+ end
8
11
 
9
- views_path.each do |path|
10
- creator.register_files Dir[File.join(path, views_ext)].map{|x| File.expand_path(x)}
11
- end
12
+ namespace :db do
12
13
 
13
- creator.create_views
14
+ desc "Create all the database views of the current project. Views are usually located in db/views"
15
+ task :create_views => :environment do
16
+ config = Rails.configuration.rails_db_views
17
+ apply_to config.views_paths, config.views_extension, :create, RailsDbViews::View
14
18
  end
15
19
 
16
20
  desc "Drop all the database views of the current project"
17
21
  task :drop_views => :environment do
18
- creator = RailsDbViews::DbViewsCreator.new
19
-
20
- views_path, views_ext = Rails.configuration.rails_db_views[:views_path], Rails.configuration.rails_db_views[:views_ext]
22
+ config = Rails.configuration.rails_db_views
23
+ apply_to config.views_paths, config.views_extension, :drop, RailsDbViews::View
24
+ end
21
25
 
22
- views_path.each do |path|
23
- creator.register_files Dir[File.join(path, views_ext)].map{|x| File.expand_path(x)}
26
+ desc "Create or replace all the functions"
27
+ task :create_functions => :environment do
28
+ adapter_type = ActiveRecord::Base.connection.adapter_name.downcase.to_sym
29
+ config = Rails.configuration.rails_db_views
30
+
31
+ if adapter_type != :sqlite
32
+ apply_to config.functions_paths, config.functions_extension, :create, RailsDbViews::Function
33
+ else
34
+ if config.functions_paths.length>=1 || File.is_directory?(config.functions_paths.try(:first))
35
+ puts "Notice: db:create_functions will not trigger for sqlite."
36
+ end
24
37
  end
38
+ end
25
39
 
26
- creator.drop_views
40
+ desc "Remove all the functions (to use manually only)"
41
+ task :drop_functions => :environment do
42
+ config = Rails.configuration.rails_db_views
43
+ apply_to config.functions_paths, config.functions_extension, :drop, RailsDbViews::Function
27
44
  end
28
45
  end
29
46
 
30
47
  require 'rake/hooks'
31
48
 
32
- before "db:migrate" do
33
- Rake::Task['db:drop_views'].invoke
34
- end
35
- before "db:rollback" do
36
- Rake::Task['db:drop_views'].invoke
37
- end
49
+ before("db:migrate"){ Rake::Task['db:drop_views'].invoke }
50
+ before("db:migrate"){ Rake::Task['db:create_functions'].invoke }
51
+ after("db:migrate"){ Rake::Task['db:create_views'].invoke }
38
52
 
39
- after "db:migrate" do
40
- Rake::Task['db:create_views'].invoke
41
- end
42
- after "db:rollback" do
43
- Rake::Task['db:create_views'].invoke
44
- end
53
+ before("db:rollback"){ Rake::Task['db:drop_views'].invoke }
54
+ before("db:rollback"){ Rake::Task['db:create_functions'].invoke }
55
+ after("db:rollback"){ Rake::Task['db:create_views'].invoke }
@@ -4,8 +4,8 @@
4
4
  # Ensure the SQLite 3 gem is defined in your Gemfile
5
5
  # gem 'sqlite3'
6
6
  development:
7
- adapter: sqlite3
8
- database: db/development.sqlite3
7
+ adapter: postgresql
8
+ database: rails_db_views
9
9
  pool: 5
10
10
  timeout: 5000
11
11
 
Binary file
@@ -0,0 +1,5 @@
1
+ (x integer, y integer) RETURNS integer AS $$
2
+ BEGIN
3
+ RETURN x + y;
4
+ END;
5
+ $$ LANGUAGE plpgsql;
@@ -13,4 +13,7 @@
13
13
 
14
14
  ActiveRecord::Schema.define(version: 0) do
15
15
 
16
+ # These are extensions that must be enabled in order to support this database
17
+ enable_extension "plpgsql"
18
+
16
19
  end
File without changes
@@ -1,2 +1,2 @@
1
- --!require required
1
+ --!require required
2
2
  SELECT 'HelloWorld' WHERE ( SELECT id FROM required ) IN (1)
@@ -166,3 +166,319 @@ SQLite3::SQLException: table required already exists: CREATE VIEW required AS SE
166
166
  ActiveRecord::SchemaMigration Load (0.1ms) SELECT "schema_migrations".* FROM "schema_migrations"
167
167
   (0.9ms) CREATE VIEW required AS SELECT 1 as id
168
168
   (1.1ms) CREATE VIEW hello_world AS SELECT 'HelloWorld' WHERE ( SELECT id FROM required ) IN (1)
169
+  (0.2ms) CREATE OR REPLACE FUNCTION (x integer, y integer) RETURNS integer AS $$
170
+ BEGIN
171
+ RETURN x + y;
172
+ END;
173
+ $$ LANGUAGE plpgsql; add.sql
174
+ SQLite3::SQLException: near "OR": syntax error: CREATE OR REPLACE FUNCTION (x integer, y integer) RETURNS integer AS $$
175
+ BEGIN
176
+ RETURN x + y;
177
+ END;
178
+ $$ LANGUAGE plpgsql; add.sql
179
+  (0.2ms) DROP FUNCTION add.sql
180
+ SQLite3::SQLException: near "FUNCTION": syntax error: DROP FUNCTION add.sql
181
+  (0.1ms) DROP FUNCTION add.sql
182
+ SQLite3::SQLException: near "FUNCTION": syntax error: DROP FUNCTION add.sql
183
+  (0.2ms) DROP FUNCTION add.sql
184
+ SQLite3::SQLException: near "FUNCTION": syntax error: DROP FUNCTION add.sql
185
+  (0.1ms) DROP FUNCTION add.sql
186
+ SQLite3::SQLException: near "FUNCTION": syntax error: DROP FUNCTION add.sql
187
+  (0.2ms) DROP FUNCTION add.sql
188
+ SQLite3::SQLException: near "FUNCTION": syntax error: DROP FUNCTION add.sql
189
+  (0.2ms) DROP FUNCTION add.sql
190
+ SQLite3::SQLException: near "FUNCTION": syntax error: DROP FUNCTION add.sql
191
+  (0.2ms) DROP FUNCTION add.sql
192
+ SQLite3::SQLException: near "FUNCTION": syntax error: DROP FUNCTION add.sql
193
+  (0.2ms) DROP FUNCTION add.sql
194
+ SQLite3::SQLException: near "FUNCTION": syntax error: DROP FUNCTION add.sql
195
+  (0.2ms) DROP FUNCTION add.sql
196
+ SQLite3::SQLException: near "FUNCTION": syntax error: DROP FUNCTION add.sql
197
+  (0.2ms) DROP FUNCTION add.sql
198
+ SQLite3::SQLException: near "FUNCTION": syntax error: DROP FUNCTION add.sql
199
+  (0.1ms) DROP FUNCTION add.sql
200
+ SQLite3::SQLException: near "FUNCTION": syntax error: DROP FUNCTION add.sql
201
+  (0.2ms) DROP FUNCTION add.sql
202
+ SQLite3::SQLException: near "FUNCTION": syntax error: DROP FUNCTION add.sql
203
+  (0.2ms) DROP FUNCTION add
204
+ SQLite3::SQLException: near "FUNCTION": syntax error: DROP FUNCTION add
205
+  (0.2ms) CREATE VIEW required
206
+ SQLite3::SQLException: near "required": syntax error: CREATE VIEW required
207
+  (0.1ms) CREATE VIEW hello_world
208
+ SQLite3::SQLException: near "hello_world": syntax error: CREATE VIEW hello_world
209
+  (1.0ms) CREATE TABLE "schema_migrations" ("version" varchar NOT NULL)
210
+  (0.1ms) select sqlite_version(*)
211
+  (0.8ms) CREATE UNIQUE INDEX "unique_schema_migrations" ON "schema_migrations" ("version")
212
+ ActiveRecord::SchemaMigration Load (0.1ms) SELECT "schema_migrations".* FROM "schema_migrations"
213
+  (0.1ms) CREATE VIEW SELECT 1 as id
214
+ SQLite3::SQLException: near "SELECT": syntax error: CREATE VIEW SELECT 1 as id
215
+  (0.2ms) DROP FUNCTION add
216
+ SQLite3::SQLException: near "FUNCTION": syntax error: DROP FUNCTION add
217
+  (0.2ms) CREATE VIEW required
218
+ SQLite3::SQLException: near "required": syntax error: CREATE VIEW required
219
+  (0.2ms) CREATE VIEW hello_world
220
+ SQLite3::SQLException: near "hello_world": syntax error: CREATE VIEW hello_world
221
+  (1.2ms) CREATE TABLE "schema_migrations" ("version" varchar NOT NULL)
222
+  (0.1ms) select sqlite_version(*)
223
+  (0.9ms) CREATE UNIQUE INDEX "unique_schema_migrations" ON "schema_migrations" ("version")
224
+ ActiveRecord::SchemaMigration Load (0.1ms) SELECT "schema_migrations".* FROM "schema_migrations"
225
+  (0.1ms) CREATE VIEW SELECT 1 as id
226
+ SQLite3::SQLException: near "SELECT": syntax error: CREATE VIEW SELECT 1 as id
227
+  (0.2ms) DROP FUNCTION add
228
+ SQLite3::SQLException: near "FUNCTION": syntax error: DROP FUNCTION add
229
+  (0.1ms) CREATE VIEW required
230
+ SQLite3::SQLException: near "required": syntax error: CREATE VIEW required
231
+  (0.1ms) CREATE VIEW hello_world
232
+ SQLite3::SQLException: near "hello_world": syntax error: CREATE VIEW hello_world
233
+  (1.9ms) CREATE TABLE "schema_migrations" ("version" varchar NOT NULL)
234
+  (0.1ms) select sqlite_version(*)
235
+  (1.2ms) CREATE UNIQUE INDEX "unique_schema_migrations" ON "schema_migrations" ("version")
236
+ ActiveRecord::SchemaMigration Load (0.1ms) SELECT "schema_migrations".* FROM "schema_migrations"
237
+  (1.0ms) CREATE VIEW required AS SELECT 1 as id
238
+  (0.2ms) DROP FUNCTION add
239
+ SQLite3::SQLException: near "FUNCTION": syntax error: DROP FUNCTION add
240
+  (0.1ms) CREATE VIEW required
241
+ SQLite3::SQLException: near "required": syntax error: CREATE VIEW required
242
+  (0.1ms) CREATE VIEW hello_world
243
+ SQLite3::SQLException: near "hello_world": syntax error: CREATE VIEW hello_world
244
+  (1.4ms) CREATE TABLE "schema_migrations" ("version" varchar NOT NULL)
245
+  (0.1ms) select sqlite_version(*)
246
+  (0.8ms) CREATE UNIQUE INDEX "unique_schema_migrations" ON "schema_migrations" ("version")
247
+ ActiveRecord::SchemaMigration Load (0.1ms) SELECT "schema_migrations".* FROM "schema_migrations"
248
+  (0.7ms) CREATE VIEW required AS SELECT 1 as id
249
+  (0.9ms) CREATE VIEW hello_world AS --!require required
250
+ SELECT 'HelloWorld' WHERE ( SELECT id FROM required ) IN (1)
251
+  (0.2ms) DROP FUNCTION add
252
+ SQLite3::SQLException: near "FUNCTION": syntax error: DROP FUNCTION add
253
+  (0.1ms) CREATE VIEW required
254
+ SQLite3::SQLException: near "required": syntax error: CREATE VIEW required
255
+  (0.1ms) CREATE VIEW hello_world
256
+ SQLite3::SQLException: near "hello_world": syntax error: CREATE VIEW hello_world
257
+  (1.4ms) CREATE TABLE "schema_migrations" ("version" varchar NOT NULL)
258
+  (0.1ms) select sqlite_version(*)
259
+  (0.9ms) CREATE UNIQUE INDEX "unique_schema_migrations" ON "schema_migrations" ("version")
260
+ ActiveRecord::SchemaMigration Load (0.1ms) SELECT "schema_migrations".* FROM "schema_migrations"
261
+  (0.8ms) CREATE VIEW required AS SELECT 1 as id
262
+  (0.9ms) CREATE VIEW hello_world AS --!require required
263
+ SELECT 'HelloWorld' WHERE ( SELECT id FROM required ) IN (1)
264
+  (0.2ms) DROP FUNCTION add
265
+ SQLite3::SQLException: near "FUNCTION": syntax error: DROP FUNCTION add
266
+  (0.1ms) CREATE VIEW required
267
+ SQLite3::SQLException: near "required": syntax error: CREATE VIEW required
268
+  (0.1ms) CREATE VIEW hello_world
269
+ SQLite3::SQLException: near "hello_world": syntax error: CREATE VIEW hello_world
270
+  (1.0ms) CREATE TABLE "schema_migrations" ("version" varchar NOT NULL)
271
+  (0.1ms) select sqlite_version(*)
272
+  (1.0ms) CREATE UNIQUE INDEX "unique_schema_migrations" ON "schema_migrations" ("version")
273
+ ActiveRecord::SchemaMigration Load (0.1ms) SELECT "schema_migrations".* FROM "schema_migrations"
274
+  (0.9ms) CREATE VIEW required AS SELECT 1 as id
275
+  (0.8ms) CREATE VIEW hello_world AS --!require required
276
+ SELECT 'HelloWorld' WHERE ( SELECT id FROM required ) IN (1)
277
+  (0.2ms) DROP FUNCTION add
278
+ SQLite3::SQLException: near "FUNCTION": syntax error: DROP FUNCTION add
279
+  (0.1ms) CREATE VIEW required
280
+ SQLite3::SQLException: near "required": syntax error: CREATE VIEW required
281
+  (0.1ms) CREATE VIEW hello_world
282
+ SQLite3::SQLException: near "hello_world": syntax error: CREATE VIEW hello_world
283
+  (1.2ms) CREATE TABLE "schema_migrations" ("version" varchar NOT NULL)
284
+  (0.1ms) select sqlite_version(*)
285
+  (0.9ms) CREATE UNIQUE INDEX "unique_schema_migrations" ON "schema_migrations" ("version")
286
+ ActiveRecord::SchemaMigration Load (0.1ms) SELECT "schema_migrations".* FROM "schema_migrations"
287
+  (0.8ms) CREATE VIEW required AS SELECT 1 as id
288
+  (1.1ms) CREATE VIEW hello_world AS --!require required
289
+ SELECT 'HelloWorld' WHERE ( SELECT id FROM required ) IN (1)
290
+  (0.2ms) CREATE VIEW required
291
+ SQLite3::SQLException: near "required": syntax error: CREATE VIEW required
292
+  (0.1ms) CREATE VIEW hello_world
293
+ SQLite3::SQLException: near "hello_world": syntax error: CREATE VIEW hello_world
294
+  (1.1ms) CREATE TABLE "schema_migrations" ("version" varchar NOT NULL) 
295
+  (0.1ms) select sqlite_version(*)
296
+  (0.9ms) CREATE UNIQUE INDEX "unique_schema_migrations" ON "schema_migrations" ("version")
297
+ ActiveRecord::SchemaMigration Load (0.1ms) SELECT "schema_migrations".* FROM "schema_migrations"
298
+  (3.9ms) CREATE VIEW required AS SELECT 1 as id
299
+  (0.9ms) CREATE VIEW hello_world AS --!require required
300
+ SELECT 'HelloWorld' WHERE ( SELECT id FROM required ) IN (1)
301
+  (0.2ms) DROP FUNCTION add
302
+ SQLite3::SQLException: near "FUNCTION": syntax error: DROP FUNCTION add
303
+  (0.2ms) CREATE VIEW required
304
+ SQLite3::SQLException: near "required": syntax error: CREATE VIEW required
305
+  (0.4ms) DROP VIEW required
306
+ SQLite3::SQLException: no such view: required: DROP VIEW required
307
+  (0.3ms) DROP VIEW required
308
+ SQLite3::SQLException: no such view: required: DROP VIEW required
309
+  (0.3ms) DROP VIEW required
310
+ SQLite3::SQLException: no such view: required: DROP VIEW required
311
+  (0.3ms) DROP VIEW required
312
+ SQLite3::SQLException: no such view: required: DROP VIEW required
313
+  (0.1ms) DROP VIEW hello_world
314
+ SQLite3::SQLException: no such view: hello_world: DROP VIEW hello_world
315
+  (1.2ms) CREATE TABLE "schema_migrations" ("version" varchar NOT NULL) 
316
+  (0.1ms) select sqlite_version(*)
317
+  (0.8ms) CREATE UNIQUE INDEX "unique_schema_migrations" ON "schema_migrations" ("version")
318
+ ActiveRecord::SchemaMigration Load (0.1ms) SELECT "schema_migrations".* FROM "schema_migrations"
319
+  (0.7ms) CREATE VIEW required AS SELECT 1 as id
320
+  (0.7ms) CREATE VIEW hello_world AS --!require required
321
+ SELECT 'HelloWorld' WHERE ( SELECT id FROM required ) IN (1)
322
+  (0.3ms) DROP VIEW required
323
+ SQLite3::SQLException: no such view: required: DROP VIEW required
324
+  (0.2ms) DROP VIEW hello_world
325
+ SQLite3::SQLException: no such view: hello_world: DROP VIEW hello_world
326
+  (1.0ms) CREATE TABLE "schema_migrations" ("version" varchar NOT NULL) 
327
+  (0.1ms) select sqlite_version(*)
328
+  (0.8ms) CREATE UNIQUE INDEX "unique_schema_migrations" ON "schema_migrations" ("version")
329
+ ActiveRecord::SchemaMigration Load (0.1ms) SELECT "schema_migrations".* FROM "schema_migrations"
330
+  (4.8ms) CREATE VIEW required AS SELECT 1 as id
331
+  (1.3ms) CREATE VIEW hello_world AS --!require required
332
+ SELECT 'HelloWorld' WHERE ( SELECT id FROM required ) IN (1)
333
+  (0.9ms) CREATE OR REPLACE FUNCTION (x integer, y integer) RETURNS integer AS $$
334
+ BEGIN
335
+ RETURN x + y;
336
+ END;
337
+ $$ LANGUAGE plpgsql; add
338
+ PG::SyntaxError: ERROR: syntax error at or near "("
339
+ LINE 1: CREATE OR REPLACE FUNCTION (x integer, y integer) RETURNS in...
340
+ ^
341
+ : CREATE OR REPLACE FUNCTION (x integer, y integer) RETURNS integer AS $$
342
+ BEGIN
343
+ RETURN x + y;
344
+ END;
345
+ $$ LANGUAGE plpgsql; add
346
+  (0.3ms) CREATE OR REPLACE FUNCTION add (x integer, y integer) RETURNS integer AS $$
347
+ BEGIN
348
+ RETURN x + y;
349
+ END;
350
+ $$ LANGUAGE plpgsql; add
351
+ PG::SyntaxError: ERROR: syntax error at or near "add"
352
+ LINE 5: $$ LANGUAGE plpgsql; add
353
+ ^
354
+ : CREATE OR REPLACE FUNCTION add (x integer, y integer) RETURNS integer AS $$
355
+ BEGIN
356
+ RETURN x + y;
357
+ END;
358
+ $$ LANGUAGE plpgsql; add
359
+  (8.7ms) CREATE OR REPLACE FUNCTION add (x integer, y integer) RETURNS integer AS $$
360
+ BEGIN
361
+ RETURN x + y;
362
+ END;
363
+ $$ LANGUAGE plpgsql;
364
+  (17.7ms) DROP VIEW required
365
+ PG::UndefinedTable: ERROR: view "required" does not exist
366
+ : DROP VIEW required
367
+  (0.3ms) DROP VIEW hello_world
368
+ PG::UndefinedTable: ERROR: view "hello_world" does not exist
369
+ : DROP VIEW hello_world
370
+  (24.1ms) CREATE TABLE "schema_migrations" ("version" character varying NOT NULL)
371
+  (1.0ms) CREATE UNIQUE INDEX "unique_schema_migrations" ON "schema_migrations" ("version")
372
+ ActiveRecord::SchemaMigration Load (0.3ms) SELECT "schema_migrations".* FROM "schema_migrations"
373
+  (23.3ms) CREATE VIEW required AS SELECT 1 as id
374
+  (5.5ms) CREATE VIEW hello_world AS --!require required
375
+ SELECT 'HelloWorld' WHERE ( SELECT id FROM required ) IN (1)
376
+  (12.3ms) CREATE OR REPLACE FUNCTION add (x integer, y integer) RETURNS integer AS $$
377
+ BEGIN
378
+ RETURN x + y;
379
+ END;
380
+ $$ LANGUAGE plpgsql;
381
+  (10.6ms) DROP VIEW required
382
+ PG::DependentObjectsStillExist: ERROR: cannot drop view required because other objects depend on it
383
+ DETAIL: view hello_world depends on view required
384
+ HINT: Use DROP ... CASCADE to drop the dependent objects too.
385
+ : DROP VIEW required
386
+  (18.0ms) DROP VIEW hello_world
387
+ ActiveRecord::SchemaMigration Load (0.2ms) SELECT "schema_migrations".* FROM "schema_migrations"
388
+  (0.2ms) CREATE VIEW required AS SELECT 1 as id
389
+ PG::DuplicateTable: ERROR: relation "required" already exists
390
+ : CREATE VIEW required AS SELECT 1 as id
391
+  (2.5ms) CREATE OR REPLACE FUNCTION add (x integer, y integer) RETURNS integer AS $$
392
+ BEGIN
393
+ RETURN x + y;
394
+ END;
395
+ $$ LANGUAGE plpgsql;
396
+  (1.0ms) DROP VIEW required
397
+  (0.4ms) DROP VIEW hello_world
398
+ PG::UndefinedTable: ERROR: view "hello_world" does not exist
399
+ : DROP VIEW hello_world
400
+ ActiveRecord::SchemaMigration Load (0.4ms) SELECT "schema_migrations".* FROM "schema_migrations"
401
+  (8.1ms) CREATE VIEW required AS SELECT 1 as id
402
+  (6.6ms) CREATE VIEW hello_world AS --!require required
403
+ SELECT 'HelloWorld' WHERE ( SELECT id FROM required ) IN (1)
404
+  (2.0ms) CREATE OR REPLACE FUNCTION add (x integer, y integer) RETURNS integer AS $$
405
+ BEGIN
406
+ RETURN x + y;
407
+ END;
408
+ $$ LANGUAGE plpgsql;
409
+  (0.6ms) DROP VIEW required
410
+ PG::DependentObjectsStillExist: ERROR: cannot drop view required because other objects depend on it
411
+ DETAIL: view hello_world depends on view required
412
+ HINT: Use DROP ... CASCADE to drop the dependent objects too.
413
+ : DROP VIEW required
414
+  (0.9ms) DROP VIEW hello_world
415
+ ActiveRecord::SchemaMigration Load (0.5ms) SELECT "schema_migrations".* FROM "schema_migrations"
416
+  (0.3ms) CREATE VIEW required AS SELECT 1 as id
417
+ PG::DuplicateTable: ERROR: relation "required" already exists
418
+ : CREATE VIEW required AS SELECT 1 as id
419
+  (2.1ms) CREATE OR REPLACE FUNCTION add (x integer, y integer) RETURNS integer AS $$
420
+ BEGIN
421
+ RETURN x + y;
422
+ END;
423
+ $$ LANGUAGE plpgsql;
424
+  (0.9ms) DROP VIEW required
425
+  (0.3ms) DROP VIEW hello_world
426
+ PG::UndefinedTable: ERROR: view "hello_world" does not exist
427
+ : DROP VIEW hello_world
428
+  (2.0ms) CREATE OR REPLACE FUNCTION add (x integer, y integer) RETURNS integer AS $$
429
+ BEGIN
430
+ RETURN x + y;
431
+ END;
432
+ $$ LANGUAGE plpgsql;
433
+  (0.3ms) DROP VIEW required
434
+ PG::UndefinedTable: ERROR: view "required" does not exist
435
+ : DROP VIEW required
436
+  (2.1ms) CREATE OR REPLACE FUNCTION add (x integer, y integer) RETURNS integer AS $$
437
+ BEGIN
438
+ RETURN x + y;
439
+ END;
440
+ $$ LANGUAGE plpgsql;
441
+  (0.3ms) DROP VIEW required
442
+ PG::UndefinedTable: ERROR: view "required" does not exist
443
+ : DROP VIEW required
444
+  (2.0ms) CREATE OR REPLACE FUNCTION add (x integer, y integer) RETURNS integer AS $$
445
+ BEGIN
446
+ RETURN x + y;
447
+ END;
448
+ $$ LANGUAGE plpgsql;
449
+  (0.3ms) DROP VIEW required
450
+ PG::UndefinedTable: ERROR: view "required" does not exist
451
+ : DROP VIEW required
452
+  (0.2ms) DROP VIEW hello_world
453
+ PG::UndefinedTable: ERROR: view "hello_world" does not exist
454
+ : DROP VIEW hello_world
455
+ ActiveRecord::SchemaMigration Load (0.3ms) SELECT "schema_migrations".* FROM "schema_migrations"
456
+  (6.7ms) CREATE VIEW required AS SELECT 1 as id
457
+  (6.6ms) CREATE VIEW hello_world AS --!require required
458
+ SELECT 'HelloWorld' WHERE ( SELECT id FROM required ) IN (1)
459
+  (2.3ms) CREATE OR REPLACE FUNCTION add (x integer, y integer) RETURNS integer AS $$
460
+ BEGIN
461
+ RETURN x + y;
462
+ END;
463
+ $$ LANGUAGE plpgsql;
464
+  (0.7ms) DROP VIEW required
465
+ PG::DependentObjectsStillExist: ERROR: cannot drop view required because other objects depend on it
466
+ DETAIL: view hello_world depends on view required
467
+ HINT: Use DROP ... CASCADE to drop the dependent objects too.
468
+ : DROP VIEW required
469
+  (3.0ms) CREATE OR REPLACE FUNCTION add (x integer, y integer) RETURNS integer AS $$
470
+ BEGIN
471
+ RETURN x + y;
472
+ END;
473
+ $$ LANGUAGE plpgsql;
474
+  (1.4ms) CREATE OR REPLACE FUNCTION add (x integer, y integer) RETURNS integer AS $$
475
+ BEGIN
476
+ RETURN x + y;
477
+ END;
478
+ $$ LANGUAGE plpgsql;
479
+  (1.2ms) DROP VIEW hello_world
480
+  (0.6ms) DROP VIEW required
481
+ ActiveRecord::SchemaMigration Load (0.3ms) SELECT "schema_migrations".* FROM "schema_migrations"
482
+  (12.4ms) CREATE VIEW required AS SELECT 1 as id
483
+  (12.6ms) CREATE VIEW hello_world AS --!require required
484
+ SELECT 'HelloWorld' WHERE ( SELECT id FROM required ) IN (1)
metadata CHANGED
@@ -1,19 +1,22 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails_db_views
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yacine Petitprez
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-06-05 00:00:00.000000000 Z
11
+ date: 2015-11-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '4'
17
20
  - - ">="
18
21
  - !ruby/object:Gem::Version
19
22
  version: '4.0'
@@ -21,6 +24,9 @@ dependencies:
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
23
26
  requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '4'
24
30
  - - ">="
25
31
  - !ruby/object:Gem::Version
26
32
  version: '4.0'
@@ -29,6 +35,9 @@ dependencies:
29
35
  requirement: !ruby/object:Gem::Requirement
30
36
  requirements:
31
37
  - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '1.2'
40
+ - - ">="
32
41
  - !ruby/object:Gem::Version
33
42
  version: 1.2.3
34
43
  type: :runtime
@@ -36,6 +45,9 @@ dependencies:
36
45
  version_requirements: !ruby/object:Gem::Requirement
37
46
  requirements:
38
47
  - - "~>"
48
+ - !ruby/object:Gem::Version
49
+ version: '1.2'
50
+ - - ">="
39
51
  - !ruby/object:Gem::Version
40
52
  version: 1.2.3
41
53
  - !ruby/object:Gem::Dependency
@@ -52,7 +64,21 @@ dependencies:
52
64
  - - ">="
53
65
  - !ruby/object:Gem::Version
54
66
  version: '0'
55
- description: ''
67
+ - !ruby/object:Gem::Dependency
68
+ name: pg
69
+ requirement: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: '0'
74
+ type: :development
75
+ prerelease: false
76
+ version_requirements: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ description: Provide tools to create and manage database view through Rails project.
56
82
  email:
57
83
  - anykeyh@gmail.com
58
84
  executables: []
@@ -62,9 +88,13 @@ files:
62
88
  - LICENSE
63
89
  - Rakefile
64
90
  - lib/rails_db_views.rb
65
- - lib/rails_db_views/db_views_creator.rb
91
+ - lib/rails_db_views/configuration.rb
92
+ - lib/rails_db_views/database_symbol.rb
93
+ - lib/rails_db_views/factory.rb
94
+ - lib/rails_db_views/function.rb
66
95
  - lib/rails_db_views/railtie.rb
67
96
  - lib/rails_db_views/version.rb
97
+ - lib/rails_db_views/view.rb
68
98
  - lib/tasks/rails_db_views_tasks.rake
69
99
  - test/dummy/README.rdoc
70
100
  - test/dummy/Rakefile
@@ -94,7 +124,9 @@ files:
94
124
  - test/dummy/config/locales/en.yml
95
125
  - test/dummy/config/routes.rb
96
126
  - test/dummy/db/development.sqlite3
127
+ - test/dummy/db/functions/add.sql
97
128
  - test/dummy/db/schema.rb
129
+ - test/dummy/db/test.sqlite3
98
130
  - test/dummy/db/views/hello_world.sql
99
131
  - test/dummy/db/views/required.sql
100
132
  - test/dummy/log/development.log
@@ -124,7 +156,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
124
156
  version: '0'
125
157
  requirements: []
126
158
  rubyforge_project:
127
- rubygems_version: 2.2.2
159
+ rubygems_version: 2.4.8
128
160
  signing_key:
129
161
  specification_version: 4
130
162
  summary: Provide tools to create and manage database view through Rails project.
@@ -155,7 +187,9 @@ test_files:
155
187
  - test/dummy/config/routes.rb
156
188
  - test/dummy/config.ru
157
189
  - test/dummy/db/development.sqlite3
190
+ - test/dummy/db/functions/add.sql
158
191
  - test/dummy/db/schema.rb
192
+ - test/dummy/db/test.sqlite3
159
193
  - test/dummy/db/views/hello_world.sql
160
194
  - test/dummy/db/views/required.sql
161
195
  - test/dummy/log/development.log
@@ -1,104 +0,0 @@
1
- class RailsDbViews::DbViewsCreator
2
- attr_reader :views
3
-
4
- def initialize
5
- @views = {}
6
- end
7
-
8
- def register_files files
9
- files.each do |file|
10
- view_name = File.basename(file, File.extname(file))
11
-
12
- content = File.read(file)
13
- content_lines = content.split("\n")
14
-
15
- # Reject the commented lines from the file
16
- sql_content = content_lines.reject{ |x| x.strip =~ /^--/ || x.strip =~ /^#/ }.join("\n")
17
-
18
- file_obj = { path: file, sql_content: sql_content, status: :none, requires: [] }
19
-
20
- # Detect directives in commentary
21
- directives = content_lines.select{ |x| x.strip =~ /^--/ || x.strip =~ /^#/ }.map(&:strip).map{ |x|
22
- x =~ /^--/ ? x[2..-1] : x[1..-1]
23
- }.select{|x| x =~ /^!/ }
24
-
25
- directives.each do |directive|
26
- if directive =~ /^!require / #Currently only the require directive exists.
27
- file_obj[:requires] += directive.split(" ")[1..-1]
28
- end
29
- end
30
-
31
- if @views[view_name]
32
- puts "WARNING: #{view_name} already defined in `#{@views[view_name][:path]}`. Will be ignored and we use `#{file_obj[:path]}`..."
33
- end
34
-
35
- @views[view_name] = file_obj
36
- end
37
- end
38
-
39
- def drop_views
40
- reset_views_status!
41
- @views.each{ |name, view|
42
- drop_view name, view
43
- }
44
- end
45
-
46
- def create_views
47
- reset_views_status!
48
- @views.each{ |name, view|
49
- create_view name, view
50
- }
51
- end
52
-
53
- private
54
- def reset_views_status!
55
- @views.each{ |name, view|
56
- view[:status] = :none
57
- }
58
- end
59
-
60
-
61
- def drop_view name, view
62
- return if view[:status] == :loaded
63
-
64
- if view[:status] == :inprogress
65
- raise "Error: Circular file reference! (view #{name})"
66
- end
67
-
68
- view[:requires].each do |other_view|
69
- drop_view other_view, @views[other_view]
70
- end
71
-
72
- sql = "DROP VIEW #{name}"
73
- begin
74
- ActiveRecord::Base.connection.execute(sql)
75
- puts "DROP VIEW #{name}... OK"
76
- rescue
77
- puts "WARNING: DROP VIEW #{name}... ERROR"
78
- end
79
-
80
- view[:status] = :loaded
81
- end
82
-
83
- def create_view name, view
84
- # View already loaded.
85
- return if view[:status] == :loaded
86
-
87
- if view[:status] == :inprogress
88
- raise "Error: Circular file reference! (view #{name})"
89
- end
90
-
91
- view[:status] = :inprogress
92
-
93
- view[:requires].each do |other_view|
94
- create_view other_view, @views[other_view]
95
- end
96
-
97
- sql = "CREATE VIEW #{name} AS #{view[:sql_content]}"
98
- ActiveRecord::Base.connection.execute(sql)
99
- puts "CREATE VIEW #{name} AS... OK"
100
-
101
- view[:status] = :loaded
102
- end
103
-
104
- end