sql_view 0.0.3 → 0.0.5
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.
- checksums.yaml +4 -4
- data/README.md +133 -8
- data/lib/generators/sql_view/view/view_generator.rb +1 -1
- data/lib/sql_view/schema_dumper.rb +14 -32
- data/lib/sql_view/version.rb +1 -1
- data/lib/sql_view.rb +1 -0
- metadata +6 -7
- data/lib/tasks/sql_view_tasks.rake +0 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 453bfcdc70b0ca2eba4be95d6eca062e840e9e3f4950f8fca7471421216d1de9
|
4
|
+
data.tar.gz: 14d65cba7bbcc28dc6741622abef7b91a8863ed8e738b35de373c1758e21f045
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 99a4e50942b3322d2a86e04b5c5b56e060718788beee10af35ca79de9331bf882d16f0311c9908d97bd8c5d88926e29fd1360fcaf30c90d5d3fd17b77813a238
|
7
|
+
data.tar.gz: d502bab08d5c44d183f6c741ed2d12c53cd5b27962c9a3eca384c66e213a0d1c5bdbce058184a13fdaf3495fca65f13f7e469a0a2fc59da861f4e8cffc18335d
|
data/README.md
CHANGED
@@ -1,11 +1,86 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# Rails + SQL View
|
2
|
+
|
3
|
+
[](https://opensource-heroes.com/r/igorkasyanchuk/sql_view)
|
4
|
+
|
5
|
+
## The easist way to add and work with SQL view in your app.
|
6
|
+
|
7
|
+
If you are lazy and don't like to write SQL to create SQL view but you know AR use your skills to create views.
|
8
|
+
|
9
|
+
Production-ready.
|
10
|
+
|
11
|
+

|
3
12
|
|
4
13
|
## Usage
|
5
|
-
|
14
|
+
|
15
|
+
The most simple way to add a view is to call a generator (examples below):
|
16
|
+
|
17
|
+
```bash
|
18
|
+
rails g sql_view:view DeletedProjects 'Project.only_deleted'
|
19
|
+
rails g sql_view:view ActiveUsers 'User.confirmed.where(active: true)' --materialized
|
20
|
+
```
|
21
|
+
|
22
|
+
Depending on whether you need a materialized view or not add `--materialized` flag (later you can change in "view" class). Materialized views works in Postgres.
|
23
|
+
|
24
|
+
Generator will create a file similar to:
|
25
|
+
|
26
|
+
```ruby
|
27
|
+
class ActiveUserView < SQLView::Model
|
28
|
+
materialized
|
29
|
+
|
30
|
+
schema -> { User.where(age: 18..60) }
|
31
|
+
|
32
|
+
extend_model_with do
|
33
|
+
# sample how you can extend it, similar to regular AR model
|
34
|
+
#
|
35
|
+
# include SomeConcern
|
36
|
+
#
|
37
|
+
# belongs_to :user
|
38
|
+
# has_many :posts
|
39
|
+
#
|
40
|
+
# scope :ordered, -> { order(:created_at) }
|
41
|
+
# scope :by_role, ->(role) { where(role: role) }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
```
|
45
|
+
|
46
|
+
or if you want to use SQL to create a regular view:
|
47
|
+
|
48
|
+
|
49
|
+
```ruby
|
50
|
+
class ActiveUserView < SQLView::Model
|
51
|
+
schema -> { "SELECT * FROM users WHERE active = TRUE" }
|
52
|
+
end
|
53
|
+
```
|
54
|
+
|
55
|
+
or the same but materialized:
|
56
|
+
|
57
|
+
```ruby
|
58
|
+
class ActiveUserView < SQLView::Model
|
59
|
+
materialized
|
60
|
+
schema -> { "SELECT * FROM users WHERE active = TRUE" }
|
61
|
+
end
|
62
|
+
```
|
63
|
+
|
64
|
+
Later with view you can work same way as with any model(ActiveRecord class). For example:
|
65
|
+
|
66
|
+
```ruby
|
67
|
+
ActiveUserView.model.count
|
68
|
+
# or
|
69
|
+
ActiveUserView.count
|
70
|
+
# ----
|
71
|
+
ActiveUserView.find(42)
|
72
|
+
# you can apply scopes, relations, methods, BUT add them in extend_model_with block
|
73
|
+
|
74
|
+
ActiveUserView.model.by_role("admin").count
|
75
|
+
ActiveUserView.where(role: "admin").exists?
|
76
|
+
ActiveUserView.model.includes(:profile)
|
77
|
+
```
|
78
|
+
|
79
|
+
If you need to refresh materialized view - `ActiveUserView.sql_view.refresh` (if you need to do it concerrently - `.refresh(concurrently: false)`.
|
80
|
+
|
81
|
+
More examples in this file: `./test/sql_view_test.rb`
|
6
82
|
|
7
83
|
## Installation
|
8
|
-
Add this line to your application's Gemfile:
|
9
84
|
|
10
85
|
```ruby
|
11
86
|
gem "sql_view"
|
@@ -16,17 +91,67 @@ And then execute:
|
|
16
91
|
$ bundle
|
17
92
|
```
|
18
93
|
|
19
|
-
Or
|
20
|
-
|
21
|
-
|
94
|
+
And use generator. Or you can connect it to existing view with `view_name=`:
|
95
|
+
|
96
|
+
```ruby
|
97
|
+
class OldUserView < SqlView::Model
|
98
|
+
self.view_name = "all_old_users"
|
99
|
+
|
100
|
+
materialized
|
101
|
+
|
102
|
+
schema -> { User.where("age > 18") }
|
103
|
+
|
104
|
+
extend_model_with do
|
105
|
+
scope :ordered, -> { order(:id) }
|
106
|
+
|
107
|
+
def test_instance_method
|
108
|
+
42
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
```
|
113
|
+
|
114
|
+
## Materialized view + concurrent update
|
115
|
+
|
116
|
+
1. add index
|
117
|
+
|
118
|
+
```ruby
|
119
|
+
add_index SomeView.view_name, :user_id, unique: true
|
22
120
|
```
|
23
121
|
|
122
|
+
2. refresh with parameter
|
123
|
+
|
124
|
+
```ruby
|
125
|
+
SomeView.sql_view.refresh(concurrently: true)
|
126
|
+
```
|
127
|
+
|
128
|
+
3. profit :)
|
129
|
+
|
130
|
+
## TODO
|
131
|
+
|
132
|
+
- CI with different versions of Rails/Ruby
|
133
|
+
- make unit tests works with `rake test`
|
134
|
+
- `cascade` option
|
135
|
+
- move classes to own files
|
136
|
+
- code coverage
|
137
|
+
- verify how it works with other DB's
|
138
|
+
- check if schema was changed on migrate or schema dump?
|
139
|
+
|
24
140
|
## Testing
|
25
141
|
|
26
142
|
`ruby ./test/sql_view_test.rb` (because somehow `rake test` not works, not critical for now)
|
27
143
|
|
28
144
|
## Contributing
|
29
|
-
|
145
|
+
|
146
|
+
You are welcome to contribute.
|
147
|
+
|
148
|
+
## Credits
|
149
|
+
|
150
|
+
I know about and actually using `gem scenic`, which is very nice and I tool some examples from it how to dump view into schema.rb but this gem was created to simplify life and reduce amount of time needed to write SQL to create a sql view.
|
30
151
|
|
31
152
|
## License
|
153
|
+
|
32
154
|
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
155
|
+
|
156
|
+
[<img src="https://github.com/igorkasyanchuk/rails_time_travel/blob/main/docs/more_gems.png?raw=true"
|
157
|
+
/>](https://www.railsjazz.com/?utm_source=github&utm_medium=bottom&utm_campaign=sql_view)
|
@@ -8,20 +8,21 @@ module SqlView
|
|
8
8
|
class DBView < OpenStruct
|
9
9
|
def to_schema
|
10
10
|
<<-DEFINITION
|
11
|
-
create_sql_view "#{
|
12
|
-
CREATE
|
11
|
+
create_sql_view "#{viewname}", sql: <<-\SQL
|
12
|
+
CREATE#{materialized_or_not}VIEW "#{viewname}" AS
|
13
13
|
#{escaped_definition.indent(2)}
|
14
14
|
SQL\n
|
15
15
|
DEFINITION
|
16
16
|
end
|
17
17
|
|
18
18
|
private
|
19
|
+
|
19
20
|
def materialized?
|
20
|
-
|
21
|
+
kind == "m"
|
21
22
|
end
|
22
23
|
|
23
24
|
def materialized_or_not
|
24
|
-
materialized? ? " MATERIALIZED " :
|
25
|
+
materialized? ? " MATERIALIZED " : " "
|
25
26
|
end
|
26
27
|
|
27
28
|
def escaped_definition
|
@@ -35,40 +36,18 @@ module SqlView
|
|
35
36
|
end
|
36
37
|
|
37
38
|
def views(stream)
|
38
|
-
if
|
39
|
-
stream.puts
|
40
|
-
end
|
39
|
+
stream.puts if sql_views.any?
|
41
40
|
|
42
|
-
|
43
|
-
next if already_indexed?(viewname)
|
44
|
-
view = DBView.new(get_view_info(viewname))
|
41
|
+
sql_views.each do |view|
|
45
42
|
stream.puts(view.to_schema)
|
46
|
-
indexes(viewname, stream)
|
43
|
+
indexes(view.viewname, stream)
|
47
44
|
end
|
48
45
|
end
|
49
46
|
|
50
47
|
private
|
51
48
|
|
52
|
-
|
53
|
-
|
54
|
-
@already_indexed ||= []
|
55
|
-
return true if @already_indexed.include?(viewname)
|
56
|
-
@already_indexed << viewname
|
57
|
-
false
|
58
|
-
end
|
59
|
-
|
60
|
-
def dumpable_views_in_database
|
61
|
-
@dumpable_views_in_database ||= ActiveRecord::Base.connection.views.reject do |viewname|
|
62
|
-
ignored?(viewname)
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
def get_view_info(viewname)
|
67
|
-
views_schema.detect{|e| e['viewname'] == viewname}
|
68
|
-
end
|
69
|
-
|
70
|
-
def views_schema
|
71
|
-
@views_schema ||= ActiveRecord::Base.connection.execute(<<-SQL)
|
49
|
+
def sql_views
|
50
|
+
@sql_views ||= ActiveRecord::Base.connection.execute(<<-SQL)
|
72
51
|
SELECT
|
73
52
|
c.relname as viewname,
|
74
53
|
pg_get_viewdef(c.oid) AS definition,
|
@@ -79,10 +58,11 @@ module SqlView
|
|
79
58
|
WHERE
|
80
59
|
c.relkind IN ('m', 'v')
|
81
60
|
AND c.relname NOT IN (SELECT extname FROM pg_extension)
|
61
|
+
AND c.relname != 'pg_stat_statements_info'
|
82
62
|
AND n.nspname = ANY (current_schemas(false))
|
83
63
|
ORDER BY c.oid
|
84
64
|
SQL
|
85
|
-
.to_a
|
65
|
+
.to_a.map(&DBView.method(:new)).reject { |view| ignored?(view.viewname) }
|
86
66
|
end
|
87
67
|
|
88
68
|
unless ActiveRecord::SchemaDumper.private_instance_methods(false).include?(:ignored?)
|
@@ -100,3 +80,5 @@ module SqlView
|
|
100
80
|
end
|
101
81
|
end
|
102
82
|
end
|
83
|
+
|
84
|
+
SQLView = SqlView
|
data/lib/sql_view/version.rb
CHANGED
data/lib/sql_view.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sql_view
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Igor Kasyanchuk
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-06-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -84,13 +84,12 @@ files:
|
|
84
84
|
- lib/sql_view/schema_dumper.rb
|
85
85
|
- lib/sql_view/statements.rb
|
86
86
|
- lib/sql_view/version.rb
|
87
|
-
- lib/tasks/sql_view_tasks.rake
|
88
87
|
homepage: https://github.com/igorkasyanchuk/sql_view
|
89
88
|
licenses:
|
90
89
|
- MIT
|
91
90
|
metadata:
|
92
91
|
homepage_uri: https://github.com/igorkasyanchuk/sql_view
|
93
|
-
post_install_message:
|
92
|
+
post_install_message:
|
94
93
|
rdoc_options: []
|
95
94
|
require_paths:
|
96
95
|
- lib
|
@@ -105,8 +104,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
105
104
|
- !ruby/object:Gem::Version
|
106
105
|
version: '0'
|
107
106
|
requirements: []
|
108
|
-
rubygems_version: 3.
|
109
|
-
signing_key:
|
107
|
+
rubygems_version: 3.4.13
|
108
|
+
signing_key:
|
110
109
|
specification_version: 4
|
111
110
|
summary: Simple way to create and interact with your SQL views using ActiveRecord.
|
112
111
|
test_files: []
|