pg_gnostic 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE +20 -0
- data/README.rdoc +58 -0
- data/Rakefile +48 -0
- data/generators/pg_view/USAGE +5 -0
- data/generators/pg_view/pg_view_generator.rb +50 -0
- data/generators/pg_view/templates/model.rb +11 -0
- data/generators/pg_view/templates/view.rb +11 -0
- data/generators/pg_view/templates/view.sql +3 -0
- data/lib/pg_gnostic/config.rb +11 -0
- data/lib/pg_gnostic/tasks.rb +1 -0
- data/lib/pg_gnostic/view_definition.rb +159 -0
- data/lib/pg_gnostic.rb +17 -0
- data/tasks/pg_gnostic_tasks.rake +30 -0
- data/test/config_test.rb +17 -0
- data/test/database.yml +6 -0
- data/test/db/schema.rb +15 -0
- data/test/db/views/other_users.sql +3 -0
- data/test/db/views/users.rb +8 -0
- data/test/pg_gnostic_test.rb +8 -0
- data/test/rails_root/app/model/views/role.rb +11 -0
- data/test/rails_root/app/model/views/user.rb +11 -0
- data/test/rails_root/db/views/roles.sql +3 -0
- data/test/rails_root/db/views/users.rb +11 -0
- data/test/test_helper.rb +95 -0
- data/test/view_definition_test.rb +45 -0
- data/test/view_generator_test.rb +43 -0
- metadata +89 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2010 [name of plugin creator]
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
== PgGnostic
|
2
|
+
|
3
|
+
Rails and postgres deeper integration
|
4
|
+
|
5
|
+
== Install
|
6
|
+
|
7
|
+
in config/environment.rb:
|
8
|
+
|
9
|
+
config.gem 'pg_gnostic'
|
10
|
+
|
11
|
+
and then
|
12
|
+
|
13
|
+
sudo rake gems:install
|
14
|
+
|
15
|
+
To install pg_gnostic rake tasks u need add this lines into RAILS_ROOT/Rakefile
|
16
|
+
|
17
|
+
require 'pg_gnostic'
|
18
|
+
require 'pg_gnostic/tasks'
|
19
|
+
|
20
|
+
== FEATURES
|
21
|
+
|
22
|
+
* add pg views generator
|
23
|
+
scripts/generate pg_view [--format= ruby|sql] view_name [dependency_view_names]
|
24
|
+
* rake pg: pg:drop_views, pg:functions, pg:views and all in one pg:update
|
25
|
+
|
26
|
+
|
27
|
+
== CHANGE LIST:
|
28
|
+
|
29
|
+
== TODO
|
30
|
+
|
31
|
+
* backup rake
|
32
|
+
* loganalize rake
|
33
|
+
* functions generator
|
34
|
+
|
35
|
+
== LICENSE:
|
36
|
+
|
37
|
+
(The MIT License)
|
38
|
+
|
39
|
+
Copyright (c) 2010 niquola
|
40
|
+
|
41
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
42
|
+
a copy of this software and associated documentation files (the
|
43
|
+
'Software'), to deal in the Software without restriction, including
|
44
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
45
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
46
|
+
permit persons to whom the Software is furnished to do so, subject to
|
47
|
+
the following conditions:
|
48
|
+
|
49
|
+
The above copyright notice and this permission notice shall be
|
50
|
+
included in all copies or substantial portions of the Software.
|
51
|
+
|
52
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
53
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
54
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
55
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
56
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
57
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
58
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rake/rdoctask'
|
4
|
+
require 'rake/gempackagetask'
|
5
|
+
|
6
|
+
desc 'Default: run unit tests.'
|
7
|
+
task :default => :test
|
8
|
+
|
9
|
+
desc 'Test the pg_gnostic plugin.'
|
10
|
+
Rake::TestTask.new(:test) do |t|
|
11
|
+
t.libs << 'lib'
|
12
|
+
t.libs << 'test'
|
13
|
+
t.pattern = 'test/**/*_test.rb'
|
14
|
+
t.verbose = true
|
15
|
+
end
|
16
|
+
|
17
|
+
desc 'Generate documentation for the pg_gnostic plugin.'
|
18
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
19
|
+
rdoc.rdoc_dir = 'rdoc'
|
20
|
+
rdoc.title = 'PgGnostic'
|
21
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
22
|
+
rdoc.rdoc_files.include('README.rdoc')
|
23
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
PKG_FILES = FileList[ '[a-zA-Z]*', 'generators/**/*', 'lib/**/*', 'rails/**/*', 'tasks/**/*', 'test/**/*' ]
|
28
|
+
|
29
|
+
spec = Gem::Specification.new do |s|
|
30
|
+
s.name = "pg_gnostic"
|
31
|
+
s.version = "0.0.1"
|
32
|
+
s.author = "niquola"
|
33
|
+
s.email = "niquola@gmail.com"
|
34
|
+
s.homepage = "http://github.com/niquola/pg_gnostic"
|
35
|
+
s.platform = Gem::Platform::RUBY
|
36
|
+
s.summary = "Rails plugin for postgres"
|
37
|
+
s.files = PKG_FILES.to_a
|
38
|
+
s.require_path = "lib"
|
39
|
+
s.has_rdoc = false
|
40
|
+
s.extra_rdoc_files = ["README.rdoc"]
|
41
|
+
s.add_dependency('kung_figure','0.0.2')
|
42
|
+
end
|
43
|
+
|
44
|
+
desc 'Turn this plugin into a gem.'
|
45
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
46
|
+
pkg.gem_spec = spec
|
47
|
+
end
|
48
|
+
|
@@ -0,0 +1,50 @@
|
|
1
|
+
$:.unshift(path('../lib'))
|
2
|
+
require 'pg_gnostic'
|
3
|
+
class PgViewGenerator < Rails::Generator::Base
|
4
|
+
default_options :format => 'ruby'
|
5
|
+
def manifest
|
6
|
+
record do |m|
|
7
|
+
unless args.size > 0
|
8
|
+
puts "require view name"
|
9
|
+
exit 1
|
10
|
+
end
|
11
|
+
parse_args
|
12
|
+
model_path = PgGnostic.config.view_model.model_path
|
13
|
+
m.directory File.join('db/views')
|
14
|
+
m.directory File.join(model_path)
|
15
|
+
case options[:format]
|
16
|
+
when 'sql':
|
17
|
+
m.template "view.sql", File.join('db/views',"#{@view_name}.sql"), :assigns=>@assigns
|
18
|
+
when 'ruby':
|
19
|
+
m.template "view.rb", File.join('db/views',"#{@view_name}.rb"), :assigns=>@assigns
|
20
|
+
end
|
21
|
+
m.template "model.rb", File.join(model_path,"#{@model_file_name}.rb"), :assigns=>@assigns
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def parse_args
|
26
|
+
@view_name = args.shift.pluralize
|
27
|
+
@model_name = @view_name.singularize
|
28
|
+
@model_file_name = @model_name.underscore
|
29
|
+
@class_name = @model_name.classify
|
30
|
+
@dependencies = args if args.length > 0
|
31
|
+
@assigns = {
|
32
|
+
:view_name=>@view_name,
|
33
|
+
:class_name=>@class_name,
|
34
|
+
:dependencies=>@dependencies,
|
35
|
+
:nest_in_module=>PgGnostic.config.view_model.nest_in_module,
|
36
|
+
:prefix_view_name=>PgGnostic.config.view_model.prefix_view_name
|
37
|
+
}
|
38
|
+
end
|
39
|
+
|
40
|
+
protected
|
41
|
+
def banner
|
42
|
+
"Usage: #{$0} #{spec.name} ViewName"
|
43
|
+
end
|
44
|
+
|
45
|
+
def add_options!(opt)
|
46
|
+
opt.separator ''
|
47
|
+
opt.separator 'Options:'
|
48
|
+
opt.on("-f","--format=ruby", String, "sql | ruby","Default ruby") { |v| options[:format] = v }
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<% unless nest_in_module.empty? %>
|
2
|
+
module <%= nest_in_module %>
|
3
|
+
<% end %>
|
4
|
+
class <%= class_name %> < ActiveRecord::Base
|
5
|
+
<% unless prefix_view_name.empty? %>
|
6
|
+
set_table_name "<%= prefix_view_name %>_#{table_name}"
|
7
|
+
<% end %>
|
8
|
+
end
|
9
|
+
<% unless nest_in_module.empty? %>
|
10
|
+
end
|
11
|
+
<% end %>
|
@@ -0,0 +1,11 @@
|
|
1
|
+
PgGnostic.define do |d|
|
2
|
+
d.create_view :view_<%= view_name %>,:depends_on=>[<%= dependencies.map{|d| ":view_#{d}"}.join(',') if dependencies %>], :sql=><<-SQL
|
3
|
+
SELECT
|
4
|
+
fld0
|
5
|
+
,fld1
|
6
|
+
,fld2
|
7
|
+
FROM <%= view_name %>
|
8
|
+
JOIN table2 ON conditions
|
9
|
+
SQL
|
10
|
+
end
|
11
|
+
# vim:ft=sql
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module PgGnostic
|
2
|
+
class Config < KungFigure::Base
|
3
|
+
class ViewModel < KungFigure::Base
|
4
|
+
define_prop :nest_in_module,'Views'
|
5
|
+
define_prop :prefix_view_name,'view_'
|
6
|
+
def model_path
|
7
|
+
nest_in_module ? "app/model/#{nest_in_module.underscore}" : "app/model"
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
load File.join(File.dirname(__FILE__),'../..','tasks','pg_gnostic_tasks.rake')
|
@@ -0,0 +1,159 @@
|
|
1
|
+
require 'erb'
|
2
|
+
require 'active_record'
|
3
|
+
|
4
|
+
module PgGnostic
|
5
|
+
class TableDesc
|
6
|
+
def column_names
|
7
|
+
@columns || @columns = ActiveRecord::Base.connection.columns(@name).map{|c| c.name}
|
8
|
+
@columns
|
9
|
+
end
|
10
|
+
def initialize(name)
|
11
|
+
@name = quote_table_name(name)
|
12
|
+
end
|
13
|
+
|
14
|
+
def quote_table_name(table)
|
15
|
+
ActiveRecord::Base.connection.quote_table_name(table)
|
16
|
+
end
|
17
|
+
|
18
|
+
def *(opts={})
|
19
|
+
table_name = opts[:table_name] || @name
|
20
|
+
aliases = opts[:aliases]
|
21
|
+
fields = column_names
|
22
|
+
fields = fields - opts[:exclude].flatten if opts[:exclude]
|
23
|
+
fields.map do |f|
|
24
|
+
line="#{table_name}.#{f}"
|
25
|
+
line<< " AS #{aliases[f]}" if aliases && aliases[f]
|
26
|
+
line
|
27
|
+
end.join("\n,")
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class Tables
|
32
|
+
attr :sql,true
|
33
|
+
def pname
|
34
|
+
%Q[format_name(patients.name)]
|
35
|
+
end
|
36
|
+
|
37
|
+
def timestamps
|
38
|
+
['created_at','updated_at']
|
39
|
+
end
|
40
|
+
|
41
|
+
def method_missing(name)
|
42
|
+
return ViewDefinition.predifined_fields[name] if ViewDefinition.predifined_fields[name]
|
43
|
+
return TableDesc.new(name)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
class ViewDefinition
|
48
|
+
class << self
|
49
|
+
attr :views
|
50
|
+
def views
|
51
|
+
@views||={}
|
52
|
+
end
|
53
|
+
|
54
|
+
def load_declarations(path)
|
55
|
+
Dir["#{path}/*.rb"].each do |f|
|
56
|
+
load f
|
57
|
+
end
|
58
|
+
Dir["#{path}/*.sql"].each do |f|
|
59
|
+
sql = IO.readlines(f,'').to_s
|
60
|
+
view_name = File.basename(f,".sql").to_sym
|
61
|
+
create_view(view_name,:sql=>sql)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def create_view(name,opts={})
|
66
|
+
raise "View with name #{name} already registered" if views.key? name
|
67
|
+
opts[:depends_on] = to_arr opts[:depends_on] if opts.key? :depends_on
|
68
|
+
|
69
|
+
views[name] = opts.merge(:name=>name,:sql=>opts[:sql])
|
70
|
+
end
|
71
|
+
|
72
|
+
def predifined_fields
|
73
|
+
@predifined_fields ||={}
|
74
|
+
end
|
75
|
+
|
76
|
+
def named_fields(*args)
|
77
|
+
key = args.shift
|
78
|
+
predifined_fields[key]=args.to_a
|
79
|
+
end
|
80
|
+
|
81
|
+
def to_arr(val)
|
82
|
+
if val && !val.is_a?(Array)
|
83
|
+
[ val ]
|
84
|
+
else
|
85
|
+
val
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def create_view_sql(vname,sql)
|
90
|
+
<<-SQL
|
91
|
+
CREATE VIEW #{vname} AS #{sql};
|
92
|
+
SQL
|
93
|
+
end
|
94
|
+
|
95
|
+
def reset_created_flag
|
96
|
+
views.values.each {|v| v[:created] = false}
|
97
|
+
end
|
98
|
+
|
99
|
+
def delete_all
|
100
|
+
views.each do |name,view|
|
101
|
+
delete name
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def delete(name)
|
106
|
+
puts " * Drop view #{name}"
|
107
|
+
ActiveRecord::Base.connection.execute "DROP VIEW IF EXISTS #{name} CASCADE;"
|
108
|
+
end
|
109
|
+
|
110
|
+
def update
|
111
|
+
delete_all
|
112
|
+
reset_created_flag
|
113
|
+
views.values.each do |view|
|
114
|
+
execute(view,[])
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def execute(view,stack)
|
119
|
+
if stack.include?(view)
|
120
|
+
stack<< view
|
121
|
+
raise "ERROR: Recursion in views dependencies \n #{stack.to_yaml}"
|
122
|
+
end
|
123
|
+
return if view[:created]
|
124
|
+
|
125
|
+
if view.key? :depends_on
|
126
|
+
view[:depends_on].each do |dep|
|
127
|
+
if views.key?(dep)
|
128
|
+
stack<< view
|
129
|
+
execute views[dep], stack
|
130
|
+
else
|
131
|
+
raise "ERROR: Could not find dependency #{dep}"
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
execute_sql(view)
|
136
|
+
view[:created] = true
|
137
|
+
end
|
138
|
+
|
139
|
+
def execute_sql(view)
|
140
|
+
name = view[:name]
|
141
|
+
ActiveRecord::Base.connection.reconnect!
|
142
|
+
template = ERB.new view[:sql]
|
143
|
+
t = Tables.new
|
144
|
+
t.instance_eval do
|
145
|
+
@sql = template.result(binding)
|
146
|
+
end
|
147
|
+
sql = create_view_sql(view[:name],t.sql)
|
148
|
+
puts " * Create view #{name}"
|
149
|
+
ActiveRecord::Base.transaction do
|
150
|
+
ActiveRecord::Base.connection().execute sql;
|
151
|
+
end
|
152
|
+
rescue Exception=>e
|
153
|
+
puts "ERROR: While creating #{name} #{e}"
|
154
|
+
raise e
|
155
|
+
end
|
156
|
+
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
data/lib/pg_gnostic.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__)) unless
|
2
|
+
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
3
|
+
require 'kung_figure'
|
4
|
+
# PgGnostic
|
5
|
+
module PgGnostic
|
6
|
+
include KungFigure
|
7
|
+
|
8
|
+
autoload :ViewDefinition, 'pg_gnostic/view_definition'
|
9
|
+
autoload :Config, 'pg_gnostic/config'
|
10
|
+
|
11
|
+
class << self
|
12
|
+
def define
|
13
|
+
yield ViewDefinition
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
@@ -0,0 +1,30 @@
|
|
1
|
+
puts "loading task"
|
2
|
+
namespace :pg do
|
3
|
+
desc "drop views"
|
4
|
+
task :drop_views=>:environment do
|
5
|
+
#ActiveRecord::Base.logger=Logger.new STDOUT
|
6
|
+
PgGnostic::ViewDefinition.load_declarations(File.join(RAILS_ROOT,'db','views'))
|
7
|
+
PgGnostic::ViewDefinition.delete_all
|
8
|
+
end
|
9
|
+
desc "update views"
|
10
|
+
task :views=>:environment do
|
11
|
+
#ActiveRecord::Base.logger=Logger.new STDOUT
|
12
|
+
PgGnostic::ViewDefinition.load_declarations File.join(RAILS_ROOT,'db','views')
|
13
|
+
PgGnostic::ViewDefinition.update
|
14
|
+
end
|
15
|
+
desc "updates functions"
|
16
|
+
task :functions => [:environment] do
|
17
|
+
Dir["#{File.join(RAILS_ROOT,'db','functions')}/*.sql"].sort.each do |f|
|
18
|
+
begin
|
19
|
+
puts "execute #{f}"
|
20
|
+
sql=open(f,'r').readlines.join("\n")
|
21
|
+
ActiveRecord::Base.connection().execute sql;
|
22
|
+
rescue Exception=>e
|
23
|
+
puts e
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
desc "updates functions and views"
|
28
|
+
task :update=>[:functions,:views] do
|
29
|
+
end
|
30
|
+
end
|
data/test/config_test.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper.rb'
|
2
|
+
|
3
|
+
class PgGnosticViewUtilsTest < ActiveSupport::TestCase
|
4
|
+
def test_default_config
|
5
|
+
assert_equal('Views',PgGnostic.config.view_model.nest_in_module)
|
6
|
+
|
7
|
+
PgGnostic.configure do
|
8
|
+
view_model do
|
9
|
+
nest_in_module 'OtherModule'
|
10
|
+
end
|
11
|
+
end
|
12
|
+
assert_equal('OtherModule',PgGnostic.config.view_model.nest_in_module)
|
13
|
+
assert_equal('view_',PgGnostic.config.view_model.prefix_view_name)
|
14
|
+
|
15
|
+
PgGnostic.clear_config!
|
16
|
+
end
|
17
|
+
end
|
data/test/database.yml
ADDED
data/test/db/schema.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
ActiveRecord::Schema.define(:version => 0) do
|
2
|
+
create_table :users do |t|
|
3
|
+
t.string :last_name, :limit => 25
|
4
|
+
t.string :first_name, :limit => 25
|
5
|
+
t.string :middle_name, :limit => 25
|
6
|
+
t.string :name, :limit => 25
|
7
|
+
t.string :login, :limit => 40
|
8
|
+
t.string :email, :limit => 100
|
9
|
+
t.string :crypted_password, :limit => 40
|
10
|
+
t.string :salt, :limit => 40
|
11
|
+
t.datetime :last_login_datetime
|
12
|
+
t.datetime :deleted_at
|
13
|
+
t.timestamps
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
PgGnostic.define do |d|
|
2
|
+
d.named_fields :my_exclude_fields,'crypted_password','salt','last_login_datetime','deleted_at'
|
3
|
+
d.create_view :view_users,:depends_on=>[:other_users], :sql=><<-SQL
|
4
|
+
SELECT
|
5
|
+
<%= users.* :exclude=>[timestamps,'id',my_exclude_fields] %>
|
6
|
+
FROM users
|
7
|
+
SQL
|
8
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'kung_figure'
|
3
|
+
def path(path)
|
4
|
+
File.join(File.dirname(__FILE__),path)
|
5
|
+
end
|
6
|
+
|
7
|
+
$:.unshift(path('../lib'))
|
8
|
+
require 'pg_gnostic'
|
9
|
+
require 'active_support'
|
10
|
+
require 'active_support/test_case'
|
11
|
+
require "rails_generator"
|
12
|
+
require "active_record"
|
13
|
+
require 'rails_generator/scripts/generate'
|
14
|
+
require "test/unit"
|
15
|
+
|
16
|
+
|
17
|
+
GEM_ROOT= path('..')
|
18
|
+
Rails::Generator::Base.default_options :collision => :ask, :quiet => false
|
19
|
+
Rails::Generator::Base.reset_sources
|
20
|
+
Rails::Generator::Base.append_sources(Rails::Generator::PathSource.new(:plugin, "#{GEM_ROOT}/generators/"))
|
21
|
+
|
22
|
+
class GeneratorTest < ActiveSupport::TestCase
|
23
|
+
def generate(*args)
|
24
|
+
Rails::Generator::Scripts::Generate.new.run(args, :destination=>fake_rails_root)
|
25
|
+
end
|
26
|
+
|
27
|
+
def read(path)
|
28
|
+
IO.readlines("#{fake_rails_root}/#{path}",'').to_s
|
29
|
+
end
|
30
|
+
|
31
|
+
def assert_file(file)
|
32
|
+
assert_block "File #{file} not exists, as not expected" do
|
33
|
+
File.exists? "#{fake_rails_root}/#{file}"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def setup
|
38
|
+
FileUtils.rm_r(fake_rails_root)
|
39
|
+
FileUtils.mkdir_p(fake_rails_root)
|
40
|
+
end
|
41
|
+
|
42
|
+
protected
|
43
|
+
def fake_rails_root
|
44
|
+
path('rails_root')
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
class TestDbUtils
|
49
|
+
class<< self
|
50
|
+
def config
|
51
|
+
@config ||= YAML::load(IO.read(path('/database.yml'))).symbolize_keys
|
52
|
+
end
|
53
|
+
|
54
|
+
#create test database
|
55
|
+
def ensure_test_database
|
56
|
+
connect_to_test_db
|
57
|
+
rescue
|
58
|
+
create_database
|
59
|
+
end
|
60
|
+
|
61
|
+
def load_schema
|
62
|
+
ensure_test_database
|
63
|
+
load(path('db/schema.rb'))
|
64
|
+
end
|
65
|
+
|
66
|
+
def ensure_schema
|
67
|
+
load_schema
|
68
|
+
rescue
|
69
|
+
puts "tests database exists: skip schema loading"
|
70
|
+
end
|
71
|
+
|
72
|
+
def create_database
|
73
|
+
connect_to_postgres_db
|
74
|
+
ActiveRecord::Base.connection.create_database(config[:database], config)
|
75
|
+
connect_to_test_db
|
76
|
+
rescue
|
77
|
+
$stderr.puts $!, *($!.backtrace)
|
78
|
+
$stderr.puts "Couldn't create database for #{config.inspect}"
|
79
|
+
end
|
80
|
+
|
81
|
+
def connect_to_test_db
|
82
|
+
ActiveRecord::Base.establish_connection(config)
|
83
|
+
ActiveRecord::Base.connection
|
84
|
+
end
|
85
|
+
|
86
|
+
def connect_to_postgres_db
|
87
|
+
ActiveRecord::Base.establish_connection(config.merge(:database => 'postgres', :schema_search_path => 'public'))
|
88
|
+
end
|
89
|
+
|
90
|
+
def drop_database
|
91
|
+
connect_to_postgres_db
|
92
|
+
ActiveRecord::Base.connection.drop_database config[:database]
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper.rb'
|
2
|
+
#ActiveRecord::Base.logger=Logger.new(STDOUT)
|
3
|
+
|
4
|
+
TestDbUtils.ensure_schema
|
5
|
+
PgGnostic::ViewDefinition.load_declarations path('db/views')
|
6
|
+
PgGnostic::ViewDefinition.update
|
7
|
+
|
8
|
+
class User < ActiveRecord::Base
|
9
|
+
set_table_name "view_#{table_name}"
|
10
|
+
end
|
11
|
+
|
12
|
+
class OtherUser < ActiveRecord::Base
|
13
|
+
end
|
14
|
+
|
15
|
+
class PgGnosticViewUtilsTest < ActiveSupport::TestCase
|
16
|
+
def assert_contain_field(model_class, field)
|
17
|
+
assert_block "Model #{model_class} not include #{field},but should do. [#{model_class.column_names}]" do
|
18
|
+
model_class.column_names.include?(field)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def assert_not_contain_field(model_class, field)
|
23
|
+
assert_block "Model #{model_class} include #{field}, but should not" do
|
24
|
+
! model_class.column_names.include?(field)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_view_creation
|
29
|
+
assert_equal 'view_users',User.table_name
|
30
|
+
assert_contain_field(User,'name')
|
31
|
+
assert_not_contain_field(User,'id')
|
32
|
+
assert_not_contain_field(User,'created_at')
|
33
|
+
assert_not_contain_field(User,'crypted_password')
|
34
|
+
assert_not_contain_field(User,'deleted_at')
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_sql_view
|
38
|
+
assert_equal 'other_users',OtherUser.table_name
|
39
|
+
assert_contain_field(OtherUser,'name')
|
40
|
+
assert_not_contain_field(OtherUser,'id')
|
41
|
+
assert_not_contain_field(OtherUser,'created_at')
|
42
|
+
assert_not_contain_field(OtherUser,'crypted_password')
|
43
|
+
assert_not_contain_field(OtherUser,'deleted_at')
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper.rb'
|
2
|
+
|
3
|
+
class PgGnosticViewsGeneratorTest < GeneratorTest
|
4
|
+
def test_generates_definition
|
5
|
+
PgGnostic.clear_config!
|
6
|
+
generate 'pg_view','users','roles'
|
7
|
+
assert_file 'db/views/users.rb'
|
8
|
+
result = read 'db/views/users.rb'
|
9
|
+
assert_match(/view_users/, result)
|
10
|
+
assert_match(/view_roles/, result)
|
11
|
+
assert_match(/PgGnostic.define/, result)
|
12
|
+
assert_match(/depends_on/, result)
|
13
|
+
assert_file 'app/model/views/user.rb'
|
14
|
+
result = read 'app/model/views/user.rb'
|
15
|
+
assert_match(/class User < ActiveRecord::Base/, result)
|
16
|
+
|
17
|
+
generate 'pg_view','roles','--format','sql'
|
18
|
+
assert_file 'db/views/roles.sql'
|
19
|
+
result = read 'db/views/roles.sql'
|
20
|
+
assert_file 'app/model/views/role.rb'
|
21
|
+
result = read 'app/model/views/role.rb'
|
22
|
+
assert_match(/class Role < ActiveRecord::Base/, result)
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_gen_with_changed_config
|
26
|
+
PgGnostic.clear_config!
|
27
|
+
PgGnostic.config.view_model.nest_in_module 'PgViews'
|
28
|
+
generate 'pg_view','users','roles'
|
29
|
+
assert_file 'app/model/pg_views/user.rb'
|
30
|
+
result = read 'app/model/pg_views/user.rb'
|
31
|
+
assert_match(/module PgViews/, result)
|
32
|
+
|
33
|
+
PgGnostic.configure do
|
34
|
+
view_model do
|
35
|
+
nest_in_module ''
|
36
|
+
end
|
37
|
+
end
|
38
|
+
generate 'pg_view','users','roles'
|
39
|
+
assert_file 'app/model/user.rb'
|
40
|
+
result = read 'app/model/user.rb'
|
41
|
+
assert_no_match(/module/, result)
|
42
|
+
end
|
43
|
+
end
|
metadata
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: pg_gnostic
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- niquola
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2010-03-10 00:00:00 +03:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: kung_figure
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - "="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.0.2
|
24
|
+
version:
|
25
|
+
description:
|
26
|
+
email: niquola@gmail.com
|
27
|
+
executables: []
|
28
|
+
|
29
|
+
extensions: []
|
30
|
+
|
31
|
+
extra_rdoc_files:
|
32
|
+
- README.rdoc
|
33
|
+
files:
|
34
|
+
- Rakefile
|
35
|
+
- README.rdoc
|
36
|
+
- MIT-LICENSE
|
37
|
+
- generators/pg_view/pg_view_generator.rb
|
38
|
+
- generators/pg_view/templates/view.rb
|
39
|
+
- generators/pg_view/templates/view.sql
|
40
|
+
- generators/pg_view/templates/model.rb
|
41
|
+
- generators/pg_view/USAGE
|
42
|
+
- lib/pg_gnostic.rb
|
43
|
+
- lib/pg_gnostic/config.rb
|
44
|
+
- lib/pg_gnostic/tasks.rb
|
45
|
+
- lib/pg_gnostic/view_definition.rb
|
46
|
+
- tasks/pg_gnostic_tasks.rake
|
47
|
+
- test/view_generator_test.rb
|
48
|
+
- test/pg_gnostic_test.rb
|
49
|
+
- test/database.yml
|
50
|
+
- test/db/views/users.rb
|
51
|
+
- test/db/views/other_users.sql
|
52
|
+
- test/db/schema.rb
|
53
|
+
- test/rails_root/app/model/views/role.rb
|
54
|
+
- test/rails_root/app/model/views/user.rb
|
55
|
+
- test/rails_root/db/views/users.rb
|
56
|
+
- test/rails_root/db/views/roles.sql
|
57
|
+
- test/config_test.rb
|
58
|
+
- test/view_definition_test.rb
|
59
|
+
- test/test_helper.rb
|
60
|
+
has_rdoc: true
|
61
|
+
homepage: http://github.com/niquola/pg_gnostic
|
62
|
+
licenses: []
|
63
|
+
|
64
|
+
post_install_message:
|
65
|
+
rdoc_options: []
|
66
|
+
|
67
|
+
require_paths:
|
68
|
+
- lib
|
69
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: "0"
|
74
|
+
version:
|
75
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
76
|
+
requirements:
|
77
|
+
- - ">="
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: "0"
|
80
|
+
version:
|
81
|
+
requirements: []
|
82
|
+
|
83
|
+
rubyforge_project:
|
84
|
+
rubygems_version: 1.3.5
|
85
|
+
signing_key:
|
86
|
+
specification_version: 3
|
87
|
+
summary: Rails plugin for postgres
|
88
|
+
test_files: []
|
89
|
+
|