pg_gnostic 0.0.1
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/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
|
+
|