rails_age 0.3.0 → 0.3.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -4
- data/README.md +40 -6
- data/db/schema.rb +1 -1
- data/lib/rails_age/version.rb +1 -1
- data/lib/tasks/copy_migrations.rake +33 -0
- data/lib/tasks/database_config.rake +99 -0
- data/lib/tasks/install.original.rake +257 -0
- data/lib/tasks/install.rake +8 -199
- data/lib/tasks/schema_config.rake +95 -0
- metadata +6 -3
- data/lib/tasks/rails_age_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: 272f8908dc8fb8a98adb443411e4b439eff914c8173b5eb64b53fa5362fa1572
|
4
|
+
data.tar.gz: bf1921611698ffc1b651787f2e1b1a5d1bc503cbe1300639b2f9dada8202cdde
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 51592c31e872a9b8dc6e96fe8fa42374241496e4da6a17ce70bf63f5f118ac078e81200259c048529e7e16b2147c8c5bbef00315cee8f26237295d04ffaea887
|
7
|
+
data.tar.gz: 0b24560f7703e4dc4f97d3d36de626906a47a2cda5f5137cc6c1840a5281bbcf2693743666fb6301b26723c9723244bd1854c9c8b21d5d657eb621d4caf0d864
|
data/CHANGELOG.md
CHANGED
@@ -2,8 +2,6 @@
|
|
2
2
|
|
3
3
|
## VERSION 0.4.0 - 2024-xx-xx
|
4
4
|
|
5
|
-
- **Edges**
|
6
|
-
* `find_edge` is deprecated - use `find_by` with :start_node, :end_node to find an edge with specific nodes
|
7
5
|
- **cypher**
|
8
6
|
* query support
|
9
7
|
* paths support
|
@@ -13,14 +11,19 @@
|
|
13
11
|
|
14
12
|
## VERSION 0.3.1 - 2024-xx-xx
|
15
13
|
|
16
|
-
- **
|
14
|
+
- **Generators**
|
17
15
|
* add `rails generate apache_age:node` to create a node model (with its type in initializer)
|
18
16
|
* add `rails generate apache_age:edge` to create an edge model (with its type in initializer)
|
19
17
|
- **Installer**
|
20
|
-
*
|
18
|
+
* refactor into multiple independent tasks with tests
|
19
|
+
- **Documentation**
|
20
|
+
* updated README with additional information
|
21
|
+
* added `db/structure.sql` config to README
|
21
22
|
|
22
23
|
## VERSION 0.3.0 - 2024-05-28
|
23
24
|
|
25
|
+
- **Edges**
|
26
|
+
* `find_by(start_node:, :end_node:, properties:)` to find an edge with specific nodes & properties (deprecated `find_edge`)
|
24
27
|
- **Installer** (`rails generate apache_age:install`)
|
25
28
|
* copy Age PG Extenstion migration to `db/migrate`
|
26
29
|
* run the AGE PG Migration
|
data/README.md
CHANGED
@@ -14,6 +14,8 @@ gem "rails_age"
|
|
14
14
|
|
15
15
|
### Quick Install
|
16
16
|
|
17
|
+
using the installer, creates the migration to install age, runs the migration, and adjusts the schema file, and updates the `config/database.yml` file.
|
18
|
+
|
17
19
|
```bash
|
18
20
|
$ bundle
|
19
21
|
$ bin/rails apache_age:install
|
@@ -21,7 +23,9 @@ $ git add .
|
|
21
23
|
$ git commit -m "Add Apache Age to Rails"
|
22
24
|
```
|
23
25
|
|
24
|
-
NOTE: it is important to
|
26
|
+
NOTE: it is important to commit the `db/schema.rb` to git because `rails db:migrate` inappropriately modifies the schema file (I haven't yet tested `db/structure.sql`). **You can run `bin/rails apache_age:install` at any time to repair the schema file as needed.**
|
27
|
+
|
28
|
+
For now, if you are using `db/structure.sql` you will need to manually configure Apache Age (RailsAge) as described below.
|
25
29
|
|
26
30
|
### Manual Install
|
27
31
|
|
@@ -76,6 +80,7 @@ $ bin/rails db:migrate
|
|
76
80
|
|
77
81
|
Rails migrate will mangle the schema `db/schema.rb` file. You need to remove the lines that look like:
|
78
82
|
```ruby
|
83
|
+
ActiveRecord::Schema[7.1].define(version: 2024_05_21_062349) do
|
79
84
|
create_schema "ag_catalog"
|
80
85
|
create_schema "age_schema"
|
81
86
|
|
@@ -99,12 +104,14 @@ Rails migrate will mangle the schema `db/schema.rb` file. You need to remove th
|
|
99
104
|
|
100
105
|
# other migrations
|
101
106
|
# ...
|
107
|
+
end
|
102
108
|
```
|
103
109
|
|
104
110
|
and replace them with the following lines:
|
105
111
|
```ruby
|
112
|
+
ActiveRecord::Schema[7.1].define(version: 2024_05_21_062349) do
|
106
113
|
# These are extensions that must be enabled in order to support this database
|
107
|
-
enable_extension
|
114
|
+
enable_extension 'plpgsql'
|
108
115
|
|
109
116
|
# Allow age extension
|
110
117
|
execute('CREATE EXTENSION IF NOT EXISTS age;')
|
@@ -120,14 +127,38 @@ and replace them with the following lines:
|
|
120
127
|
|
121
128
|
# other migrations
|
122
129
|
# ...
|
130
|
+
end
|
123
131
|
```
|
124
132
|
|
125
|
-
NOTE:
|
126
|
-
|
133
|
+
NOTE: if using `db/structure.sql` use:
|
134
|
+
```sql
|
135
|
+
-- These are extensions that must be enabled in order to support this database
|
136
|
+
CREATE EXTENSION IF NOT EXISTS plpgsql WITH SCHEMA public;
|
137
|
+
|
138
|
+
-- Allow age extension (if not already enabled), this builds the age_catalog schema
|
139
|
+
CREATE EXTENSION IF NOT EXISTS age;
|
140
|
+
|
141
|
+
-- Load the age module
|
142
|
+
LOAD 'age';
|
143
|
+
|
144
|
+
-- Load the ag_catalog into the search path
|
145
|
+
SET search_path = ag_catalog, "$user", public;
|
146
|
+
|
147
|
+
-- Create age_schema graph if it doesn't exist
|
148
|
+
SELECT create_graph('age_schema');
|
149
|
+
|
150
|
+
# other migrations
|
151
|
+
# ...
|
152
|
+
|
153
|
+
INSERT INTO "schema_migrations" (version) VALUES
|
154
|
+
('20110315075839'),
|
155
|
+
--- ...
|
156
|
+
('20240521062349');
|
157
|
+
```
|
127
158
|
|
128
159
|
## Contributing
|
129
160
|
|
130
|
-
Create an
|
161
|
+
Create an merge request (with tests) and I will review it/merge it when ready.
|
131
162
|
|
132
163
|
## License
|
133
164
|
|
@@ -135,9 +166,12 @@ The gem is available as open source under the terms of the [MIT License](https:/
|
|
135
166
|
|
136
167
|
## Usage
|
137
168
|
|
169
|
+
I suggest you creat a folder create a folder called `app/nodes` and `app/edges` to keep the code organized.
|
170
|
+
I frequently use the `app/graphs` folder to keep all the graph related code together in a Module (as is done in the [rails age demo app](https://github.com/marpori/rails_age_demo_app))
|
171
|
+
|
138
172
|
I suggest you creat a folder within app called `graphs` and under that create a folder called `nodes` and `edges`. This will help you keep your code organized.
|
139
173
|
|
140
|
-
A
|
174
|
+
A trival, but fully functional [rails age demo app](https://github.com/marpori/rails_age_demo_app), based on the Flintstones Commic, is available for reference.
|
141
175
|
|
142
176
|
### Nodes
|
143
177
|
|
data/db/schema.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
ActiveRecord::Schema[7.1].define(version: 2024_05_21_062349) do
|
2
2
|
# These are extensions that must be enabled in order to support this database
|
3
|
-
enable_extension
|
3
|
+
enable_extension 'plpgsql'
|
4
4
|
|
5
5
|
# Allow age extension
|
6
6
|
execute('CREATE EXTENSION IF NOT EXISTS age;')
|
data/lib/rails_age/version.rb
CHANGED
@@ -0,0 +1,33 @@
|
|
1
|
+
# lib/tasks/install.rake
|
2
|
+
# Usage:
|
3
|
+
# * `bin/rails apache_age:copy_migrations`
|
4
|
+
# * `bundle exec rails apache_age:copy_migrations[destination_path.to_s]`
|
5
|
+
# * `bundle exec rails apache_age:copy_migrations.invoke(destination_path.to_s)`
|
6
|
+
namespace :apache_age do
|
7
|
+
desc "Copy migrations from rails_age to application and update schema"
|
8
|
+
task :copy_migrations, [:destination_path] => :environment do |t, args|
|
9
|
+
source = File.expand_path('../../../db/migrate', __FILE__)
|
10
|
+
destination_path =
|
11
|
+
File.expand_path(args[:destination_path].presence || "#{Rails.root}/db/migrate", __FILE__)
|
12
|
+
|
13
|
+
FileUtils.mkdir_p(destination_path) unless File.exist?(destination_path)
|
14
|
+
existing_migrations =
|
15
|
+
Dir.glob("#{destination_path}/*.rb").map { |file| File.basename(file).sub(/^\d+/, '') }
|
16
|
+
|
17
|
+
Dir.glob("#{source}/*.rb").each do |file|
|
18
|
+
filename = File.basename(file)
|
19
|
+
test_name = filename.sub(/^\d+/, '')
|
20
|
+
|
21
|
+
if existing_migrations.include?(test_name)
|
22
|
+
puts "Skipping migration: '#{filename}', it already exists"
|
23
|
+
else
|
24
|
+
migration_version = Time.now.utc.strftime("%Y_%m_%d_%H%M%S")
|
25
|
+
file_version = migration_version.delete('_')
|
26
|
+
new_filename = filename.sub(/^\d+/, file_version)
|
27
|
+
destination_file = File.join(destination_path, new_filename)
|
28
|
+
FileUtils.cp(file, destination_file)
|
29
|
+
puts "Created migration: '#{new_filename}'"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
# lib/tasks/install.rake
|
2
|
+
# Usage: `rake apache_age:copy_migrations`
|
3
|
+
#
|
4
|
+
namespace :apache_age do
|
5
|
+
desc "Ensure the database.yml file is properly configured for Apache Age"
|
6
|
+
task :database_config => :environment do
|
7
|
+
|
8
|
+
db_config_file = File.expand_path("#{Rails.root}/config/database.yml", __FILE__)
|
9
|
+
|
10
|
+
# Read the file
|
11
|
+
lines = File.readlines(db_config_file)
|
12
|
+
|
13
|
+
# any uncommented "schema_search_path:" lines?
|
14
|
+
path_index = lines.find_index { |line| !line.include?('#') && line.include?('schema_search_path:') }
|
15
|
+
default_start_index = lines.index { |line| line.strip.start_with?('default:') }
|
16
|
+
|
17
|
+
# when it finds an existing schema_search_path, it updates it
|
18
|
+
if path_index && lines[path_index].include?('ag_catalog,age_schema')
|
19
|
+
puts "the schema_search_path in config/database.yml is already properly set, nothing to do."
|
20
|
+
else
|
21
|
+
if path_index
|
22
|
+
key, val = lines[path_index].split(': ')
|
23
|
+
# remove any unwanted characters
|
24
|
+
val = val.gsub(/[ "\s\"\"'\n]/, '')
|
25
|
+
lines[path_index] = "#{key}: ag_catalog,age_schema,#{val}\n"
|
26
|
+
puts "added ag_catalog,age_schema to schema_search_path in config/database.yml"
|
27
|
+
elsif default_start_index
|
28
|
+
puts "the schema_search_path in config/database.yml is now properly set."
|
29
|
+
sections_index = lines.map.with_index { |line, index| index if !line.start_with?(' ') }.compact.sort
|
30
|
+
|
31
|
+
# find the start of the default section
|
32
|
+
next_section_in_list = sections_index.index(default_start_index) + 1
|
33
|
+
|
34
|
+
# find the end of the default section (before the next section starts)
|
35
|
+
path_insert_index = sections_index[next_section_in_list]
|
36
|
+
|
37
|
+
lines.insert(path_insert_index, " schema_search_path: ag_catalog,age_schema,public\n")
|
38
|
+
else
|
39
|
+
puts "didn't find a default section in database.yml, please add the following line:"
|
40
|
+
puts " schema_search_path: ag_catalog,age_schema,public"
|
41
|
+
puts "to the apprpriate section of your database.yml"
|
42
|
+
end
|
43
|
+
|
44
|
+
# Write the modified lines back to the file
|
45
|
+
File.open(db_config_file, 'w') { |file| file.write(lines.join) }
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# # lib/tasks/install.rake
|
51
|
+
# # Usage: `rake apache_age:copy_migrations`
|
52
|
+
# #
|
53
|
+
# namespace :apache_age do
|
54
|
+
# desc "Ensure the database.yml file is properly configured for Apache Age"
|
55
|
+
# task :database_config, [:destination_path] => :environment do |t, args|
|
56
|
+
# destination_path =
|
57
|
+
# File.expand_path(args[:destination_path].presence || "#{Rails.root}/config", __FILE__)
|
58
|
+
|
59
|
+
# db_config_file = File.expand_path("#{destination_path.to_s}/database.yml", __FILE__)
|
60
|
+
|
61
|
+
# # Read the file
|
62
|
+
# lines = File.readlines(db_config_file)
|
63
|
+
|
64
|
+
# # any uncommented "schema_search_path:" lines?
|
65
|
+
# path_index = lines.find_index { |line| !line.include?('#') && line.include?('schema_search_path:') }
|
66
|
+
# default_start_index = lines.index { |line| line.strip.start_with?('default:') }
|
67
|
+
|
68
|
+
# # when it finds an existing schema_search_path, it updates it
|
69
|
+
# if path_index && lines[path_index].include?('ag_catalog,age_schema')
|
70
|
+
# puts "the schema_search_path in config/database.yml is already properly set, nothing to do."
|
71
|
+
# else
|
72
|
+
# if path_index
|
73
|
+
# key, val = lines[path_index].split(': ')
|
74
|
+
# # remove any unwanted characters
|
75
|
+
# val = val.gsub(/[ "\s\"\"'\n]/, '')
|
76
|
+
# lines[path_index] = "#{key}: ag_catalog,age_schema,#{val}\n"
|
77
|
+
# puts "added ag_catalog,age_schema to schema_search_path in config/database.yml"
|
78
|
+
# elsif default_start_index
|
79
|
+
# puts "the schema_search_path in config/database.yml is now properly set."
|
80
|
+
# sections_index = lines.map.with_index { |line, index| index if !line.start_with?(' ') }.compact.sort
|
81
|
+
|
82
|
+
# # find the start of the default section
|
83
|
+
# next_section_in_list = sections_index.index(default_start_index) + 1
|
84
|
+
|
85
|
+
# # find the end of the default section (before the next section starts)
|
86
|
+
# path_insert_index = sections_index[next_section_in_list]
|
87
|
+
|
88
|
+
# lines.insert(path_insert_index, " schema_search_path: ag_catalog,age_schema,public\n")
|
89
|
+
# else
|
90
|
+
# puts "didn't find a default section in database.yml, please add the following line:"
|
91
|
+
# puts " schema_search_path: ag_catalog,age_schema,public"
|
92
|
+
# puts "to the apprpriate section of your database.yml"
|
93
|
+
# end
|
94
|
+
|
95
|
+
# # Write the modified lines back to the file
|
96
|
+
# File.open(db_config_file, 'w') { |file| file.write(lines.join) }
|
97
|
+
# end
|
98
|
+
# end
|
99
|
+
# end
|
@@ -0,0 +1,257 @@
|
|
1
|
+
# lib/tasks/install.rake
|
2
|
+
# Usage: `rake apache_age:install`
|
3
|
+
#
|
4
|
+
namespace :apache_age do
|
5
|
+
desc "Install & configure Apache Age within Rails (updates migrations, schema & database.yml)"
|
6
|
+
task :install_old => :environment do
|
7
|
+
source_schema = File.expand_path('../../../db/schema.rb', __FILE__)
|
8
|
+
destination_schema = File.expand_path("#{Rails.root}/db/schema.rb", __FILE__)
|
9
|
+
source_migrations = File.expand_path('../../../db/migrate', __FILE__)
|
10
|
+
destination_migrations = File.expand_path("#{Rails.root}/db/migrate", __FILE__)
|
11
|
+
# create the migrations folder if needed
|
12
|
+
FileUtils.mkdir_p(destination_migrations) unless File.exist?(destination_migrations)
|
13
|
+
original_migrations =
|
14
|
+
Dir.glob("#{destination_migrations}/*.rb").map { |file| File.basename(file).sub(/^\d+/, '') }
|
15
|
+
|
16
|
+
# # check if the schema is non-existent or blank (NEW) we need to know how to handle schema
|
17
|
+
# is_schema_blank = !File.exist?(destination_schema) || blank_schema?(destination_schema)
|
18
|
+
# puts "Schema is blank: #{is_schema_blank}"
|
19
|
+
|
20
|
+
# ensure we have a schema file
|
21
|
+
unless File.exist?(destination_schema)
|
22
|
+
run_db_create
|
23
|
+
run_db_migrate
|
24
|
+
end
|
25
|
+
|
26
|
+
# copy our migrations to the application (last_migration_version is nil if no migration necessary)
|
27
|
+
# last_migration_version = copy_migrations
|
28
|
+
Rake::Task["apache_age:copy_migrations"].invoke
|
29
|
+
|
30
|
+
updated_migrations =
|
31
|
+
Dir.glob("#{destination_migrations}/*.rb").map { |file| File.basename(file).sub(/^\d+/, '') }
|
32
|
+
|
33
|
+
# # run our new migrations (unless we have not added any new migrations)
|
34
|
+
# if original_migrations == updated_migrations
|
35
|
+
# puts "no new migrations were copied, skipping migrations"
|
36
|
+
# else
|
37
|
+
# puts "added Apache Age migrations, running migrations"
|
38
|
+
# run_db_migrate
|
39
|
+
# end
|
40
|
+
run_db_migrate
|
41
|
+
|
42
|
+
# adjust the schema file (unfortunately rails mangles the schema file)
|
43
|
+
# if is_schema_blank
|
44
|
+
# puts "creating new schema..."
|
45
|
+
# create_new_schema(last_migration_version, destination_schema, source_schema)
|
46
|
+
# else
|
47
|
+
# puts "updating existing schema..."
|
48
|
+
# update_existing_schema(last_migration_version, destination_schema, source_schema)
|
49
|
+
# end
|
50
|
+
Rake::Task["apache_age:schema_config"].invoke
|
51
|
+
|
52
|
+
# ensure the config/database.yml file has the proper configurations
|
53
|
+
# update_database_yml
|
54
|
+
Rake::Task["apache_age:database_config"].invoke
|
55
|
+
end
|
56
|
+
|
57
|
+
def run_db_create
|
58
|
+
puts "Running db:create..."
|
59
|
+
Rake::Task["db:create"].invoke
|
60
|
+
end
|
61
|
+
|
62
|
+
def run_db_migrate
|
63
|
+
puts "Running db:migrate..."
|
64
|
+
Rake::Task["db:migrate"].invoke
|
65
|
+
end
|
66
|
+
|
67
|
+
def copy_migrations
|
68
|
+
migration_version = nil
|
69
|
+
|
70
|
+
source = File.expand_path('../../../db/migrate', __FILE__)
|
71
|
+
destination = File.expand_path("#{Rails.root}/db/migrate", __FILE__)
|
72
|
+
|
73
|
+
FileUtils.mkdir_p(destination) unless File.exist?(destination)
|
74
|
+
existing_migrations =
|
75
|
+
Dir.glob("#{destination}/*.rb").map { |file| File.basename(file).sub(/^\d+/, '') }
|
76
|
+
|
77
|
+
Dir.glob("#{source}/*.rb").each do |file|
|
78
|
+
filename = File.basename(file)
|
79
|
+
test_name = filename.sub(/^\d+/, '')
|
80
|
+
|
81
|
+
if existing_migrations.include?(test_name)
|
82
|
+
puts "Skipping #{filename}, it already exists"
|
83
|
+
else
|
84
|
+
migration_version = Time.now.utc.strftime("%Y_%m_%d_%H%M%S")
|
85
|
+
file_version = migration_version.delete('_')
|
86
|
+
new_filename = filename.sub(/^\d+/, file_version)
|
87
|
+
destination_file = File.join(destination, new_filename)
|
88
|
+
FileUtils.cp(file, destination_file)
|
89
|
+
puts "Copied #{filename} to #{destination} as #{new_filename}"
|
90
|
+
end
|
91
|
+
end
|
92
|
+
migration_version
|
93
|
+
end
|
94
|
+
|
95
|
+
def blank_schema?(destination_schema)
|
96
|
+
return false unless File.exist?(destination_schema)
|
97
|
+
|
98
|
+
content = File.read(destination_schema)
|
99
|
+
content.include?('define(version: 0)') &&
|
100
|
+
(content.include?("enable_extension 'plpgsql'") || content.include?('enable_extension "plpgsql"')) &&
|
101
|
+
content.scan(/enable_extension/).size == 1
|
102
|
+
end
|
103
|
+
|
104
|
+
def schema_rails_version(destination_schema)
|
105
|
+
if File.exist?(destination_schema)
|
106
|
+
content = File.read(destination_schema)
|
107
|
+
version_match = content.match(/ActiveRecord::Schema\[(.*?)\]/)
|
108
|
+
return version_match[1] if version_match
|
109
|
+
else
|
110
|
+
full_version = Rails.version
|
111
|
+
primary_secondary_version = full_version.split('.')[0..1].join('.')
|
112
|
+
primary_secondary_version
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def create_new_schema(last_migration_version, destination_schema, source_schema)
|
117
|
+
if File.exist?(source_schema) && File.exist?(destination_schema)
|
118
|
+
rails_version = schema_rails_version(destination_schema)
|
119
|
+
source_content = File.read(source_schema)
|
120
|
+
|
121
|
+
# ensure we use the Rails version from the destination schema
|
122
|
+
source_content.gsub!(
|
123
|
+
/ActiveRecord::Schema\[\d+\.\d+\]/,
|
124
|
+
"ActiveRecord::Schema[#{rails_version}]"
|
125
|
+
)
|
126
|
+
# ensure we use the last migration version (not the source schema version)
|
127
|
+
source_content.gsub!(
|
128
|
+
/define\(version: \d{4}(?:_\d{2}){2}(?:_\d{6})?\) do/,
|
129
|
+
"define(version: #{last_migration_version}) do"
|
130
|
+
)
|
131
|
+
|
132
|
+
File.write(destination_schema, source_content)
|
133
|
+
puts "Created new schema in #{destination_schema} with necessary extensions and configurations."
|
134
|
+
else
|
135
|
+
puts "local db/schema.rb file not found."
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def update_existing_schema(last_migration_version, destination_schema, source_schema)
|
140
|
+
if File.exist?(source_schema) && File.exist?(destination_schema)
|
141
|
+
rails_version = schema_rails_version(destination_schema)
|
142
|
+
source_content = File.read(source_schema)
|
143
|
+
new_content =
|
144
|
+
source_content.gsub(
|
145
|
+
/.*ActiveRecord::Schema\[\d+\.\d+\]\.define\(version: \d{4}(?:_\d{2}){2}(?:_\d{6})?\) do\n|\nend$/,
|
146
|
+
''
|
147
|
+
)
|
148
|
+
|
149
|
+
destination_content = File.read(destination_schema)
|
150
|
+
|
151
|
+
# Remove unwanted schema statements
|
152
|
+
destination_content.gsub!(%r{^.*?create_schema "ag_catalog".*?\n}, '')
|
153
|
+
destination_content.gsub!(%r{^.*?create_schema "age_schema".*?\n}, '')
|
154
|
+
destination_content.gsub!(%r{^.*?enable_extension "age".*?\n}, '')
|
155
|
+
destination_content.gsub!(%r{^.*?enable_extension "plpgsql".*?\n}, '')
|
156
|
+
destination_content.gsub!(%r{^.*?# Could not dump table "ag_graph" because of following StandardError.*?\n}, '')
|
157
|
+
destination_content.gsub!(%r{^.*?# Unknown type 'regnamespace' for column 'namespace'.*?\n}, '')
|
158
|
+
destination_content.gsub!(%r{^.*?# Could not dump table "ag_label" because of following StandardError.*?\n}, '')
|
159
|
+
destination_content.gsub!(%r{^.*?# Unknown type 'regclass' for column 'relation'.*?\n}, '')
|
160
|
+
destination_content.gsub!(%r{^.*?# Unknown type 'graphid' for column 'id'.*?\n}, '')
|
161
|
+
destination_content.gsub!(
|
162
|
+
%r{^.*?# Could not dump table "_ag_label_edge" because of following StandardError.*?\n}, ''
|
163
|
+
)
|
164
|
+
destination_content.gsub!(
|
165
|
+
%r{^.*?# Could not dump table "_ag_label_vertex" because of following StandardError.*?\n}, ''
|
166
|
+
)
|
167
|
+
destination_content.gsub!(%r{^.*?# Could not dump table "ag_graph" because of following StandardError.*?\n}, '')
|
168
|
+
destination_content.gsub!(%r{^.*?# Could not dump table "ag_label" because of following StandardError.*?\n}, '')
|
169
|
+
destination_content.gsub!(%r{^.*?add_foreign_key "ag_label", "ag_graph".*?\n}, '')
|
170
|
+
|
171
|
+
# add new wanted schema statements (at the top of the schema)
|
172
|
+
unless destination_content.include?(%{execute("LOAD 'age';")}) &&
|
173
|
+
destination_content.include?(%{enable_extension 'plpgsql'}) &&
|
174
|
+
destination_content.include?(%{execute("SELECT create_graph('age_schema');")}) &&
|
175
|
+
destination_content.include?(%{execute('CREATE EXTENSION IF NOT EXISTS age;')}) &&
|
176
|
+
destination_content.include?(%{execute('SET search_path = ag_catalog, "$user", public;')})
|
177
|
+
# if not all are found then remove any found
|
178
|
+
destination_content.gsub!(%r{^.*?execute("LOAD 'age';")*?\n}, '')
|
179
|
+
destination_content.gsub!(%r{^.*?enable_extension 'plpgsql'*?\n}, '')
|
180
|
+
destination_content.gsub!(%r{^.*?execute("SELECT create_graph('age_schema');")*?\n}, '')
|
181
|
+
destination_content.gsub!(%r{^.*?execute('CREATE EXTENSION IF NOT EXISTS age;')*?\n}, '')
|
182
|
+
destination_content.gsub!(%r{^.*?execute('SET search_path = ag_catalog, "$user", public;')*?\n}, '')
|
183
|
+
destination_content.gsub!(%r{^.*?# Allow age extension*?\n}, '')
|
184
|
+
destination_content.gsub!(%r{^.*?# Load the ag_catalog into the search path*?\n}, '')
|
185
|
+
destination_content.gsub!(%r{^.*?# Create age_schema graph if it doesn't exist*?\n}, '')
|
186
|
+
destination_content.gsub!(%r{^.*?# These are extensions that must be enabled in order to support this database*?\n}, '')
|
187
|
+
|
188
|
+
# add all of the correct settings back in
|
189
|
+
destination_content.sub!(
|
190
|
+
%r{(ActiveRecord::Schema\[\d+\.\d+\]\.define\(version: \d{4}(?:_\d{2}){2}(?:_\d{6})?\) do\n)},
|
191
|
+
"\\1#{new_content}\n"
|
192
|
+
)
|
193
|
+
puts 'db/schema.rb has been updated with the necessary configuration.'
|
194
|
+
else
|
195
|
+
puts 'db/schema.rb has the necessary configuration, no adjustments necessary'
|
196
|
+
end
|
197
|
+
|
198
|
+
existing_version = destination_content.match(/define\(version: (\d{4}(?:_\d{2}){2}(?:_\d{6})?)\)/)[1].gsub('_', '')
|
199
|
+
current_version = last_migration_version ? last_migration_version.gsub('_', '') : existing_version
|
200
|
+
|
201
|
+
# ensure we use the last migration version (not the source schema version)
|
202
|
+
if current_version.to_i > existing_version.to_i
|
203
|
+
destination_content.gsub!(
|
204
|
+
/define\(version: \d{4}(?:_\d{2}){2}(?:_\d{6})?\) do/,
|
205
|
+
"define(version: #{last_migration_version}) do"
|
206
|
+
)
|
207
|
+
puts "Updated schema version to the migration version #{last_migration_version}"
|
208
|
+
end
|
209
|
+
|
210
|
+
File.write(destination_schema, destination_content)
|
211
|
+
puts "Updated #{destination_schema} with necessary extensions and configurations."
|
212
|
+
else
|
213
|
+
puts "local db/schema.rb file not found."
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
def update_database_yml
|
218
|
+
db_config_file = File.expand_path("#{Rails.root}/config/database.yml", __FILE__)
|
219
|
+
|
220
|
+
# Read the file
|
221
|
+
lines = File.readlines(db_config_file)
|
222
|
+
|
223
|
+
# any uncommented "schema_search_path:" lines?
|
224
|
+
path_index = lines.find_index { |line| !line.include?('#') && line.include?('schema_search_path:') }
|
225
|
+
default_start_index = lines.index { |line| line.strip.start_with?('default:') }
|
226
|
+
|
227
|
+
# when it finds an existing schema_search_path, it updates it
|
228
|
+
if path_index && lines[path_index].include?('ag_catalog,age_schema')
|
229
|
+
puts "schema_search_path already set to ag_catalog,age_schema nothing to do."
|
230
|
+
return
|
231
|
+
elsif path_index
|
232
|
+
key, val = lines[path_index].split(': ')
|
233
|
+
# remove any unwanted characters
|
234
|
+
val = val.gsub(/[ "\s\"\"'\n]/, '')
|
235
|
+
lines[path_index] = "#{key}: ag_catalog,age_schema,#{val}\n"
|
236
|
+
puts "add ag_catalog,age_schema to schema_search_path"
|
237
|
+
elsif default_start_index
|
238
|
+
puts "add ag_catalog,age_schema,public to schema_search_path in the default section of database.yml"
|
239
|
+
sections_index = lines.map.with_index { |line, index| index if !line.start_with?(' ') }.compact.sort
|
240
|
+
|
241
|
+
# find the start of the default section
|
242
|
+
next_section_in_list = sections_index.index(default_start_index) + 1
|
243
|
+
|
244
|
+
# find the end of the default section (before the next section starts)
|
245
|
+
path_insert_index = sections_index[next_section_in_list]
|
246
|
+
|
247
|
+
lines.insert(path_insert_index, " schema_search_path: ag_catalog,age_schema,public\n")
|
248
|
+
else
|
249
|
+
puts "didn't find a default section in database.yml, please add the following line:"
|
250
|
+
puts " schema_search_path: ag_catalog,age_schema,public"
|
251
|
+
puts "to the apprpriate section of your database.yml"
|
252
|
+
end
|
253
|
+
|
254
|
+
# Write the modified lines back to the file
|
255
|
+
File.open(db_config_file, 'w') { |file| file.write(lines.join) }
|
256
|
+
end
|
257
|
+
end
|
data/lib/tasks/install.rake
CHANGED
@@ -2,209 +2,18 @@
|
|
2
2
|
# Usage: `rake apache_age:install`
|
3
3
|
#
|
4
4
|
namespace :apache_age do
|
5
|
-
desc "
|
5
|
+
desc "Install & configure Apache Age within Rails (updates migrations, schema & database.yml)"
|
6
6
|
task :install => :environment do
|
7
|
-
|
8
|
-
|
7
|
+
# copy our migrations to the application (if needed)
|
8
|
+
Rake::Task["apache_age:copy_migrations"].invoke
|
9
9
|
|
10
|
-
#
|
11
|
-
run_migrations
|
12
|
-
|
13
|
-
# copy our migrations to the application
|
14
|
-
last_migration_version = copy_migrations
|
15
|
-
|
16
|
-
# check if the schema is blank (NEW) before running migrations!
|
17
|
-
is_schema_blank = blank_schema?(destination_schema)
|
18
|
-
puts "Schema is blank: #{is_schema_blank}"
|
19
|
-
|
20
|
-
# run our new migrations
|
21
|
-
run_migrations
|
22
|
-
|
23
|
-
# adjust the schema file (unfortunately rails mangles the schema file)
|
24
|
-
if is_schema_blank
|
25
|
-
puts "creating new schema..."
|
26
|
-
create_new_schema(last_migration_version, destination_schema, source_schema)
|
27
|
-
else
|
28
|
-
puts "updating existing schema..."
|
29
|
-
update_existing_schema(last_migration_version, destination_schema, source_schema)
|
30
|
-
end
|
31
|
-
|
32
|
-
update_database_yml
|
33
|
-
end
|
34
|
-
|
35
|
-
def copy_migrations
|
36
|
-
migration_version = nil
|
37
|
-
|
38
|
-
source = File.expand_path('../../../db/migrate', __FILE__)
|
39
|
-
destination = File.expand_path("#{Rails.root}/db/migrate", __FILE__)
|
40
|
-
|
41
|
-
FileUtils.mkdir_p(destination) unless File.exist?(destination)
|
42
|
-
existing_migrations =
|
43
|
-
Dir.glob("#{destination}/*.rb").map { |file| File.basename(file).sub(/^\d+/, '') }
|
44
|
-
|
45
|
-
Dir.glob("#{source}/*.rb").each do |file|
|
46
|
-
filename = File.basename(file)
|
47
|
-
test_name = filename.sub(/^\d+/, '')
|
48
|
-
|
49
|
-
if existing_migrations.include?(test_name)
|
50
|
-
puts "Skipping #{filename}, it already exists"
|
51
|
-
else
|
52
|
-
migration_version = Time.now.utc.strftime("%Y_%m_%d_%H%M%S")
|
53
|
-
file_version = migration_version.delete('_')
|
54
|
-
new_filename = filename.sub(/^\d+/, file_version)
|
55
|
-
destination_file = File.join(destination, new_filename)
|
56
|
-
FileUtils.cp(file, destination_file)
|
57
|
-
puts "Copied #{filename} to #{destination} as #{new_filename}"
|
58
|
-
end
|
59
|
-
end
|
60
|
-
migration_version
|
61
|
-
end
|
62
|
-
|
63
|
-
def blank_schema?(destination_schema)
|
64
|
-
return false unless File.exist?(destination_schema)
|
65
|
-
|
66
|
-
content = File.read(destination_schema)
|
67
|
-
content.include?('define(version: 0)') &&
|
68
|
-
content.include?('enable_extension "plpgsql"') &&
|
69
|
-
content.scan(/enable_extension/).size == 1
|
70
|
-
end
|
71
|
-
|
72
|
-
def run_migrations
|
73
|
-
puts "Running migrations..."
|
10
|
+
# run any new migrations
|
74
11
|
Rake::Task["db:migrate"].invoke
|
75
|
-
end
|
76
|
-
|
77
|
-
def extract_rails_version(destination_schema)
|
78
|
-
if File.exist?(destination_schema)
|
79
|
-
content = File.read(destination_schema)
|
80
|
-
version_match = content.match(/ActiveRecord::Schema\[(.*?)\]/)
|
81
|
-
return version_match[1] if version_match
|
82
|
-
else
|
83
|
-
full_version = Rails.version
|
84
|
-
primary_secondary_version = full_version.split('.')[0..1].join('.')
|
85
|
-
primary_secondary_version
|
86
|
-
end
|
87
|
-
end
|
88
12
|
|
89
|
-
|
90
|
-
|
91
|
-
rails_version = extract_rails_version(destination_schema)
|
92
|
-
source_content = File.read(source_schema)
|
93
|
-
|
94
|
-
# ensure we use the Rails version from the destination schema
|
95
|
-
source_content.gsub!(
|
96
|
-
/ActiveRecord::Schema\[\d+\.\d+\]/,
|
97
|
-
"ActiveRecord::Schema[#{rails_version}]"
|
98
|
-
)
|
99
|
-
# ensure we use the last migration version (not the source schema version)
|
100
|
-
source_content.gsub!(
|
101
|
-
/define\(version: \d{4}(?:_\d{2}){2}(?:_\d{6})?\) do/,
|
102
|
-
"define(version: #{last_migration_version}) do"
|
103
|
-
)
|
104
|
-
|
105
|
-
File.write(destination_schema, source_content)
|
106
|
-
puts "Created new schema in #{destination_schema} with necessary extensions and configurations."
|
107
|
-
else
|
108
|
-
puts "local db/schema.rb file not found."
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
def update_existing_schema(last_migration_version, destination_schema, source_schema)
|
113
|
-
if File.exist?(source_schema) && File.exist?(destination_schema)
|
114
|
-
rails_version = extract_rails_version(destination_schema)
|
115
|
-
source_content = File.read(source_schema)
|
116
|
-
new_content =
|
117
|
-
source_content.gsub(
|
118
|
-
/.*ActiveRecord::Schema\[\d+\.\d+\]\.define\(version: \d{4}(?:_\d{2}){2}(?:_\d{6})?\) do\n|\nend$/,
|
119
|
-
''
|
120
|
-
)
|
121
|
-
|
122
|
-
destination_content = File.read(destination_schema)
|
123
|
-
|
124
|
-
# Remove unwanted schema statements
|
125
|
-
destination_content.gsub!(%r{^.*?# These are extensions that must be enabled in order to support this database.*?\n}, '')
|
126
|
-
|
127
|
-
destination_content.gsub!(%r{^.*?create_schema "ag_catalog".*?\n}, '')
|
128
|
-
destination_content.gsub!(%r{^.*?create_schema "age_schema".*?\n}, '')
|
129
|
-
destination_content.gsub!(%r{^.*?enable_extension "age".*?\n}, '')
|
130
|
-
destination_content.gsub!(%r{^.*?enable_extension "plpgsql".*?\n}, '')
|
131
|
-
destination_content.gsub!(%r{^.*?# Could not dump table "ag_graph" because of following StandardError.*?\n}, '')
|
132
|
-
destination_content.gsub!(%r{^.*?# Unknown type 'regnamespace' for column 'namespace'.*?\n}, '')
|
133
|
-
destination_content.gsub!(%r{^.*?# Could not dump table "ag_label" because of following StandardError.*?\n}, '')
|
134
|
-
destination_content.gsub!(%r{^.*?# Unknown type 'regclass' for column 'relation'.*?\n}, '')
|
135
|
-
destination_content.gsub!(%r{^.*?# Unknown type 'graphid' for column 'id'.*?\n}, '')
|
136
|
-
destination_content.gsub!(
|
137
|
-
%r{^.*?# Could not dump table "_ag_label_edge" because of following StandardError.*?\n}, ''
|
138
|
-
)
|
139
|
-
destination_content.gsub!(
|
140
|
-
%r{^.*?# Could not dump table "_ag_label_vertex" because of following StandardError.*?\n}, ''
|
141
|
-
)
|
142
|
-
destination_content.gsub!(%r{^.*?# Could not dump table "ag_graph" because of following StandardError.*?\n}, '')
|
143
|
-
destination_content.gsub!(%r{^.*?# Could not dump table "ag_label" because of following StandardError.*?\n}, '')
|
144
|
-
destination_content.gsub!(%r{^.*?add_foreign_key "ag_label", "ag_graph".*?\n}, '')
|
145
|
-
|
146
|
-
# add new wanted schema statements (at the top of the schema)
|
147
|
-
destination_content.sub!(
|
148
|
-
%r{(ActiveRecord::Schema\[\d+\.\d+\]\.define\(version: \d{4}(?:_\d{2}){2}(?:_\d{6})?\) do\n)},
|
149
|
-
"\\1#{new_content}\n"
|
150
|
-
)
|
151
|
-
|
152
|
-
existing_version = destination_content.match(/define\(version: (\d{4}(?:_\d{2}){2}(?:_\d{6})?)\)/)[1].gsub('_', '')
|
153
|
-
current_version = last_migration_version ? last_migration_version.gsub('_', '') : existing_version
|
154
|
-
|
155
|
-
# ensure we use the last migration version (not the source schema version)
|
156
|
-
if current_version.to_i > existing_version.to_i
|
157
|
-
destination_content.gsub!(
|
158
|
-
/define\(version: \d{4}(?:_\d{2}){2}(?:_\d{6})?\) do/,
|
159
|
-
"define(version: #{last_migration_version}) do"
|
160
|
-
)
|
161
|
-
end
|
162
|
-
|
163
|
-
File.write(destination_schema, destination_content)
|
164
|
-
puts "Updated #{destination_schema} with necessary extensions and configurations."
|
165
|
-
else
|
166
|
-
puts "local db/schema.rb file not found."
|
167
|
-
end
|
168
|
-
end
|
169
|
-
|
170
|
-
def update_database_yml
|
171
|
-
db_config_file = File.expand_path("#{Rails.root}/config/database.yml", __FILE__)
|
172
|
-
|
173
|
-
# Read the file
|
174
|
-
lines = File.readlines(db_config_file)
|
175
|
-
|
176
|
-
# any uncommented "schema_search_path:" lines?
|
177
|
-
path_index = lines.find_index { |line| !line.include?('#') && line.include?('schema_search_path:') }
|
178
|
-
default_start_index = lines.index { |line| line.strip.start_with?('default:') }
|
179
|
-
|
180
|
-
# when it finds an existing schema_search_path, it updates it
|
181
|
-
if path_index && lines[path_index].include?('ag_catalog,age_schema')
|
182
|
-
puts "schema_search_path already set to ag_catalog,age_schema nothing to do."
|
183
|
-
return
|
184
|
-
elsif path_index
|
185
|
-
key, val = lines[path_index].split(': ')
|
186
|
-
# remove any unwanted characters
|
187
|
-
val = val.gsub(/[ "\s\"\"'\n]/, '')
|
188
|
-
lines[path_index] = "#{key}: ag_catalog,age_schema,#{val}\n"
|
189
|
-
puts "add ag_catalog,age_schema to schema_search_path"
|
190
|
-
elsif default_start_index
|
191
|
-
puts "add ag_catalog,age_schema,public to schema_search_path in the default section of database.yml"
|
192
|
-
sections_index = lines.map.with_index { |line, index| index if !line.start_with?(' ') }.compact.sort
|
193
|
-
|
194
|
-
# find the start of the default section
|
195
|
-
next_section_in_list = sections_index.index(default_start_index) + 1
|
196
|
-
|
197
|
-
# find the end of the default section (before the next section starts)
|
198
|
-
path_insert_index = sections_index[next_section_in_list]
|
199
|
-
|
200
|
-
lines.insert(path_insert_index, " schema_search_path: ag_catalog,age_schema,public\n")
|
201
|
-
else
|
202
|
-
puts "didn't find a default section in database.yml, please add the following line:"
|
203
|
-
puts " schema_search_path: ag_catalog,age_schema,public"
|
204
|
-
puts "to the apprpriate section of your database.yml"
|
205
|
-
end
|
13
|
+
# adjust the schema file (unfortunately rails mangles the schema file)
|
14
|
+
Rake::Task["apache_age:schema_config"].invoke
|
206
15
|
|
207
|
-
#
|
208
|
-
|
16
|
+
# ensure the config/database.yml file has the proper configurations
|
17
|
+
Rake::Task["apache_age:database_config"].invoke
|
209
18
|
end
|
210
19
|
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# lib/tasks/install.rake
|
2
|
+
# Usage: `rake apache_age:schema_config`
|
3
|
+
#
|
4
|
+
namespace :apache_age do
|
5
|
+
desc "Copy migrations from rails_age to application and update schema"
|
6
|
+
task :schema_config => :environment do
|
7
|
+
# source_schema = File.expand_path('../../../db/schema.rb', __FILE__)
|
8
|
+
destination_schema = File.expand_path("#{Rails.root}/db/schema.rb", __FILE__)
|
9
|
+
|
10
|
+
unless File.exist?(destination_schema)
|
11
|
+
puts "local db/schema.rb file not found. please run db:create and db:migrate first"
|
12
|
+
else
|
13
|
+
destination_content = File.read(destination_schema)
|
14
|
+
|
15
|
+
# Remove unwanted schema statements
|
16
|
+
destination_content.gsub!(%r{^.*?create_schema "ag_catalog".*?\n}, '')
|
17
|
+
destination_content.gsub!(%r{^.*?create_schema "age_schema".*?\n}, '')
|
18
|
+
destination_content.gsub!(%r{^.*?enable_extension "age".*?\n}, '')
|
19
|
+
destination_content.gsub!(%r{^.*?enable_extension "plpgsql".*?\n}, '')
|
20
|
+
destination_content.gsub!(%r{^.*?# Could not dump table "ag_graph" because of following StandardError.*?\n}, '')
|
21
|
+
destination_content.gsub!(%r{^.*?# Unknown type 'regnamespace' for column 'namespace'.*?\n}, '')
|
22
|
+
destination_content.gsub!(%r{^.*?# Could not dump table "ag_label" because of following StandardError.*?\n}, '')
|
23
|
+
destination_content.gsub!(%r{^.*?# Unknown type 'regclass' for column 'relation'.*?\n}, '')
|
24
|
+
destination_content.gsub!(%r{^.*?# Unknown type 'graphid' for column 'id'.*?\n}, '')
|
25
|
+
destination_content.gsub!(
|
26
|
+
%r{^.*?# Could not dump table "_ag_label_edge" because of following StandardError.*?\n}, ''
|
27
|
+
)
|
28
|
+
destination_content.gsub!(
|
29
|
+
%r{^.*?# Could not dump table "_ag_label_vertex" because of following StandardError.*?\n}, ''
|
30
|
+
)
|
31
|
+
destination_content.gsub!(%r{^.*?# Could not dump table "ag_graph" because of following StandardError.*?\n}, '')
|
32
|
+
destination_content.gsub!(%r{^.*?# Could not dump table "ag_label" because of following StandardError.*?\n}, '')
|
33
|
+
destination_content.gsub!(%r{^.*?add_foreign_key "ag_label", "ag_graph".*?\n}, '')
|
34
|
+
|
35
|
+
# add necessary contents (as needed)
|
36
|
+
if destination_content.include?(%{execute("LOAD 'age';")}) &&
|
37
|
+
destination_content.include?(%{enable_extension 'plpgsql'}) &&
|
38
|
+
destination_content.include?(%{execute("SELECT create_graph('age_schema');")}) &&
|
39
|
+
destination_content.include?(%{execute('CREATE EXTENSION IF NOT EXISTS age;')}) &&
|
40
|
+
destination_content.include?(%{execute('SET search_path = ag_catalog, "$user", public;')})
|
41
|
+
puts "schema.rb is properly configured, nothing to do"
|
42
|
+
else
|
43
|
+
# if not all are found then remove any found
|
44
|
+
destination_content.gsub!(%r{^.*?execute("LOAD 'age';")*?\n}, '')
|
45
|
+
destination_content.gsub!(%r{^.*?enable_extension 'plpgsql'*?\n}, '')
|
46
|
+
destination_content.gsub!(%r{^.*?execute("SELECT create_graph('age_schema');")*?\n}, '')
|
47
|
+
destination_content.gsub!(%r{^.*?execute('CREATE EXTENSION IF NOT EXISTS age;')*?\n}, '')
|
48
|
+
destination_content.gsub!(%r{^.*?execute('SET search_path = ag_catalog, "$user", public;')*?\n}, '')
|
49
|
+
destination_content.gsub!(%r{^.*?# Allow age extension*?\n}, '')
|
50
|
+
destination_content.gsub!(%r{^.*?# Load the ag_catalog into the search path*?\n}, '')
|
51
|
+
destination_content.gsub!(%r{^.*?# Create age_schema graph if it doesn't exist*?\n}, '')
|
52
|
+
destination_content.gsub!(%r{^.*?# These are extensions that must be enabled in order to support this database*?\n}, '')
|
53
|
+
|
54
|
+
# add all of the correct settings back in
|
55
|
+
# source_content = File.read(source_schema)
|
56
|
+
source_content =
|
57
|
+
<<~RUBY
|
58
|
+
ActiveRecord::Schema[7.1].define(version: 2024_05_21_062349) do
|
59
|
+
# These are extensions that must be enabled in order to support this database
|
60
|
+
enable_extension 'plpgsql'
|
61
|
+
|
62
|
+
# Allow age extension
|
63
|
+
execute('CREATE EXTENSION IF NOT EXISTS age;')
|
64
|
+
|
65
|
+
# Load the age code
|
66
|
+
execute("LOAD 'age';")
|
67
|
+
|
68
|
+
# Load the ag_catalog into the search path
|
69
|
+
execute('SET search_path = ag_catalog, "$user", public;')
|
70
|
+
|
71
|
+
# Create age_schema graph if it doesn't exist
|
72
|
+
execute("SELECT create_graph('age_schema');")
|
73
|
+
end
|
74
|
+
RUBY
|
75
|
+
|
76
|
+
age_config_contents =
|
77
|
+
source_content.gsub(
|
78
|
+
/.*ActiveRecord::Schema\[\d+\.\d+\]\.define\(version: \d{4}(?:_\d{2}){2}(?:_\d{6})?\) do\n|\nend$/,
|
79
|
+
''
|
80
|
+
)
|
81
|
+
|
82
|
+
destination_content.sub!(
|
83
|
+
%r{(ActiveRecord::Schema\[\d+\.\d+\]\.define\(version: \d{4}(?:_\d{2}){2}(?:_\d{6})?\) do\n)},
|
84
|
+
"\\1#{age_config_contents}\n"
|
85
|
+
)
|
86
|
+
end
|
87
|
+
|
88
|
+
# Remove multiple consecutive empty lines
|
89
|
+
destination_content.gsub!(/\n{2,}/, "\n\n")
|
90
|
+
|
91
|
+
File.write(destination_schema, destination_content)
|
92
|
+
puts "The schema '#{destination_schema}' is ready to work with Apache Age."
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rails_age
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bill Tihen
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-06-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -79,8 +79,11 @@ files:
|
|
79
79
|
- lib/rails_age.rb
|
80
80
|
- lib/rails_age/engine.rb
|
81
81
|
- lib/rails_age/version.rb
|
82
|
+
- lib/tasks/copy_migrations.rake
|
83
|
+
- lib/tasks/database_config.rake
|
84
|
+
- lib/tasks/install.original.rake
|
82
85
|
- lib/tasks/install.rake
|
83
|
-
- lib/tasks/
|
86
|
+
- lib/tasks/schema_config.rake
|
84
87
|
homepage: https://github.com/marpori/rails_age
|
85
88
|
licenses:
|
86
89
|
- MIT
|