rails_age 0.2.0 → 0.3.0
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 +25 -5
- data/README.md +71 -18
- data/db/migrate/{20240521062349_configure_apache_age.rb → 20240521062349_add_apache_age.rb} +1 -1
- data/lib/apache_age/entities/class_methods.rb +26 -19
- data/lib/apache_age/validators/unique_edge_validator.rb +1 -1
- data/lib/rails_age/version.rb +1 -1
- data/lib/tasks/install.rake +181 -62
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: aa956147280cd1ef2125eb39f3dd7867eadafde15806d95b90dab30d1290b135
|
4
|
+
data.tar.gz: a5b3a61d2fcf3026f9503b1bb4a9c6e60c6317f92266501f2890c2a02af1a01d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a2dbb2a72e8f64056bf6531fab29da715bdc89d1748dce2fe92a44de11b5a8c74dbc354c18a903472c996c90e01f7947c921819d3cded09b4ffbfe1cbd0da33c
|
7
|
+
data.tar.gz: d5265daf4c4a1928bdd8f7f08a1efd884f8c4ce5da38d56321f58f6f507905a24d7587d2f92bacfe5a4141e500f7f81060726a2723368b443d8892bf2e66a9b3
|
data/CHANGELOG.md
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
-
## VERSION 0.
|
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
|
5
7
|
- **cypher**
|
6
8
|
* query support
|
7
9
|
* paths support
|
@@ -9,10 +11,28 @@
|
|
9
11
|
- **Paths**
|
10
12
|
* ?
|
11
13
|
|
14
|
+
## VERSION 0.3.1 - 2024-xx-xx
|
15
|
+
|
16
|
+
- **Genetator**
|
17
|
+
* add `rails generate apache_age:node` to create a node model (with its type in initializer)
|
18
|
+
* add `rails generate apache_age:edge` to create an edge model (with its type in initializer)
|
19
|
+
- **Installer**
|
20
|
+
* refactored into multiple independent tasks?
|
21
|
+
|
22
|
+
## VERSION 0.3.0 - 2024-05-28
|
23
|
+
|
24
|
+
- **Installer** (`rails generate apache_age:install`)
|
25
|
+
* copy Age PG Extenstion migration to `db/migrate`
|
26
|
+
* run the AGE PG Migration
|
27
|
+
* repair `db/schema.rb` (rails mangles schema after running pg extension)
|
28
|
+
* update `database.yml` with schema search paths
|
29
|
+
|
30
|
+
NOTE: the `rails generate apache_age:install` can be run at any time to repair the schema (or other config) file if needed.
|
31
|
+
|
12
32
|
## VERSION 0.2.0 - 2024-05-26
|
13
33
|
|
14
34
|
- **Edges**
|
15
|
-
* add class methods to find_edge(with {properties, end_id, start_id})
|
35
|
+
* add class methods to `find_edge` (with {properties, end_id, start_id})
|
16
36
|
* add missing methods to use in rails controllers
|
17
37
|
* validate edge start- & end-nodes are valid
|
18
38
|
* add unique edge validations
|
@@ -25,13 +45,13 @@
|
|
25
45
|
Initial release has the following features:
|
26
46
|
|
27
47
|
- **Nodes:**
|
28
|
-
*
|
48
|
+
* `.create`, `.read`, `.update`, `.delete`, `.all`, `.find(by id)`, `.find_by(age_properties)`
|
29
49
|
* verified with usage in a controller and views
|
30
50
|
- **Edges:**
|
31
|
-
|
51
|
+
*`.create`, `.read`, `.update`, `.delete`, `.all`, `.find(by id)`, `.find_by(age_properties)`
|
32
52
|
* verified with usage in a controller and views
|
33
53
|
- **Entities:**
|
34
|
-
* find
|
54
|
+
* `.all`, `.find(id)`, `.find_by(age_property)` use these when class, label, edge, node
|
35
55
|
|
36
56
|
These can be used within Rails applications using a Rails APIs including within controllers and views.
|
37
57
|
See the [README](README.md) for more information.
|
data/README.md
CHANGED
@@ -12,24 +12,26 @@ Add this line to your application's Gemfile:
|
|
12
12
|
gem "rails_age"
|
13
13
|
```
|
14
14
|
|
15
|
-
|
15
|
+
### Quick Install
|
16
16
|
|
17
17
|
```bash
|
18
18
|
$ bundle
|
19
|
+
$ bin/rails apache_age:install
|
20
|
+
$ git add .
|
21
|
+
$ git commit -m "Add Apache Age to Rails"
|
19
22
|
```
|
20
23
|
|
21
|
-
|
24
|
+
NOTE: it is important to add the db/schema.rb to your git repository because `rails db:migrate` will inappropriately modify the schema file. However, you can run `bin/rails apache_age:install` at any time to repair the schema file if needed.
|
22
25
|
|
23
|
-
|
24
|
-
$ gem install rails_age
|
25
|
-
```
|
26
|
-
|
27
|
-
finally (tempoarily you need to copy and run the migration)
|
28
|
-
https://github.com/marpori/rails_age/blob/main/db/migrate/20240521062349_configure_apache_age.rb
|
26
|
+
### Manual Install
|
29
27
|
|
28
|
+
create a migration to add the Apache Age extension to your database
|
30
29
|
```bash
|
31
|
-
|
32
|
-
|
30
|
+
$ bin/rails g migration AddApacheAge
|
31
|
+
```
|
32
|
+
copy the contents of https://github.com/marpori/rails_age/blob/main/db/migrate/20240521062349_add_apache_age.rb
|
33
|
+
```ruby
|
34
|
+
class AddApacheAge < ActiveRecord::Migration[7.1]
|
33
35
|
def up
|
34
36
|
# Allow age extension
|
35
37
|
execute('CREATE EXTENSION IF NOT EXISTS age;')
|
@@ -65,13 +67,42 @@ class ConfigureApacheAge < ActiveRecord::Migration[7.1]
|
|
65
67
|
end
|
66
68
|
end
|
67
69
|
```
|
70
|
+
into your new migration file
|
71
|
+
|
72
|
+
then run the migration
|
73
|
+
```bash
|
74
|
+
$ bin/rails db:migrate
|
75
|
+
```
|
76
|
+
|
77
|
+
Rails migrate will mangle the schema `db/schema.rb` file. You need to remove the lines that look like:
|
78
|
+
```ruby
|
79
|
+
create_schema "ag_catalog"
|
80
|
+
create_schema "age_schema"
|
81
|
+
|
82
|
+
# These are extensions that must be enabled in order to support this database
|
83
|
+
enable_extension "age"
|
84
|
+
enable_extension "plpgsql"
|
68
85
|
|
69
|
-
|
70
|
-
|
86
|
+
# Could not dump table "_ag_label_edge" because of following StandardError
|
87
|
+
# Unknown type 'graphid' for column 'id'
|
71
88
|
|
89
|
+
# Could not dump table "_ag_label_vertex" because of following StandardError
|
90
|
+
# Unknown type 'graphid' for column 'id'
|
91
|
+
|
92
|
+
# Could not dump table "ag_graph" because of following StandardError
|
93
|
+
# Unknown type 'regnamespace' for column 'namespace'
|
94
|
+
|
95
|
+
# Could not dump table "ag_label" because of following StandardError
|
96
|
+
# Unknown type 'regclass' for column 'relation'
|
97
|
+
|
98
|
+
add_foreign_key "ag_label", "ag_graph", column: "graph", primary_key: "graphid", name: "fk_graph_oid"
|
99
|
+
|
100
|
+
# other migrations
|
101
|
+
# ...
|
102
|
+
```
|
103
|
+
|
104
|
+
and replace them with the following lines:
|
72
105
|
```ruby
|
73
|
-
# db/schema.rb
|
74
|
-
ActiveRecord::Schema[7.1].define(version: 2024_05_21_062349) do
|
75
106
|
# These are extensions that must be enabled in order to support this database
|
76
107
|
enable_extension "plpgsql"
|
77
108
|
|
@@ -89,9 +120,11 @@ ActiveRecord::Schema[7.1].define(version: 2024_05_21_062349) do
|
|
89
120
|
|
90
121
|
# other migrations
|
91
122
|
# ...
|
92
|
-
end
|
93
123
|
```
|
94
124
|
|
125
|
+
NOTE: I like to add the schema.rb to git so that it is easy to revert the unwanted changes and keep the desired changes.
|
126
|
+
ALSO note that running: `bin/rails apache_age:install` will check and non-destructively repair any config files at any time (however a git commit before hand as a backup is a good idea incase something goes wrong!)
|
127
|
+
|
95
128
|
## Contributing
|
96
129
|
|
97
130
|
Create an MR and tests and I will review it.
|
@@ -115,7 +148,12 @@ module Nodes
|
|
115
148
|
include ApacheAge::Entities::Vertex
|
116
149
|
|
117
150
|
attribute :company_name, :string
|
151
|
+
|
118
152
|
validates :company_name, presence: true
|
153
|
+
validates_with(
|
154
|
+
ApacheAge::Validators::UniqueVertexValidator,
|
155
|
+
attributes: [:company_name]
|
156
|
+
)
|
119
157
|
end
|
120
158
|
end
|
121
159
|
```
|
@@ -148,15 +186,30 @@ end
|
|
148
186
|
### Edges
|
149
187
|
|
150
188
|
```ruby
|
151
|
-
# app/graphs/edges/
|
189
|
+
# app/graphs/edges/has_job.rb
|
152
190
|
module Edges
|
153
191
|
class HasJob
|
154
192
|
include ApacheAge::Entities::Edge
|
155
193
|
|
156
194
|
attribute :employee_role, :string
|
157
|
-
attribute :start_node, :person
|
158
|
-
|
195
|
+
attribute :start_node, :person
|
196
|
+
attribute :end_node, :company
|
197
|
+
|
159
198
|
validates :employee_role, presence: true
|
199
|
+
validate :validate_unique
|
200
|
+
# or with a one-liner
|
201
|
+
# validates_with(
|
202
|
+
# ApacheAge::Validators::UniqueEdgeValidator,
|
203
|
+
# attributes: %i[employee_role start_node end_node]
|
204
|
+
# )
|
205
|
+
|
206
|
+
private
|
207
|
+
|
208
|
+
def validate_unique
|
209
|
+
ApacheAge::Validators::UniqueEdgeValidator
|
210
|
+
.new(attributes: %i[employee_role start_node end_node])
|
211
|
+
.validate(self)
|
212
|
+
end
|
160
213
|
end
|
161
214
|
end
|
162
215
|
```
|
@@ -8,29 +8,15 @@ module ApacheAge
|
|
8
8
|
instance
|
9
9
|
end
|
10
10
|
|
11
|
-
def
|
12
|
-
|
13
|
-
attributes
|
14
|
-
.compact
|
15
|
-
.except(:end_id, :start_id, :end_node, :start_node)
|
16
|
-
.map { |k, v| "find.#{k} = '#{v}'" }.join(' AND ')
|
17
|
-
where_attribs = where_attribs.empty? ? nil : where_attribs
|
18
|
-
|
19
|
-
end_id = attributes[:end_id] || attributes[:end_node]&.id
|
20
|
-
start_id = attributes[:start_id] || attributes[:start_node]&.id
|
21
|
-
where_end_id = end_id ? "id(end_node) = #{end_id}" : nil
|
22
|
-
where_start_id = start_id ? "id(start_node) = #{start_id}" : nil
|
23
|
-
|
24
|
-
where_clause = [where_attribs, where_start_id, where_end_id].compact.join(' AND ')
|
25
|
-
return nil if where_clause.empty?
|
11
|
+
def find_by(attributes)
|
12
|
+
return nil if attributes.reject{ |k,v| v.blank? }.empty?
|
26
13
|
|
27
|
-
|
28
|
-
|
29
|
-
end
|
14
|
+
edge_keys = [:start_id, :start_node, :end_id, :end_node]
|
15
|
+
return find_edge(attributes) if edge_keys.any? { |key| attributes.include?(key) }
|
30
16
|
|
31
|
-
def find_by(attributes)
|
32
17
|
where_clause = attributes.map { |k, v| "find.#{k} = '#{v}'" }.join(' AND ')
|
33
18
|
cypher_sql = find_sql(where_clause)
|
19
|
+
|
34
20
|
execute_find(cypher_sql)
|
35
21
|
end
|
36
22
|
|
@@ -55,6 +41,27 @@ module ApacheAge
|
|
55
41
|
|
56
42
|
# Private stuff
|
57
43
|
|
44
|
+
def find_edge(attributes)
|
45
|
+
where_attribs =
|
46
|
+
attributes
|
47
|
+
.compact
|
48
|
+
.except(:end_id, :start_id, :end_node, :start_node)
|
49
|
+
.map { |k, v| "find.#{k} = '#{v}'" }.join(' AND ')
|
50
|
+
where_attribs = where_attribs.empty? ? nil : where_attribs
|
51
|
+
|
52
|
+
end_id = attributes[:end_id] || attributes[:end_node]&.id
|
53
|
+
start_id = attributes[:start_id] || attributes[:start_node]&.id
|
54
|
+
where_end_id = end_id ? "id(end_node) = #{end_id}" : nil
|
55
|
+
where_start_id = start_id ? "id(start_node) = #{start_id}" : nil
|
56
|
+
|
57
|
+
where_clause = [where_attribs, where_start_id, where_end_id].compact.join(' AND ')
|
58
|
+
return nil if where_clause.empty?
|
59
|
+
|
60
|
+
cypher_sql = find_edge_sql(where_clause)
|
61
|
+
|
62
|
+
execute_find(cypher_sql)
|
63
|
+
end
|
64
|
+
|
58
65
|
def age_graph = 'age_schema'
|
59
66
|
def age_label = name.gsub('::', '__')
|
60
67
|
def age_type = name.constantize.new.age_type
|
@@ -32,7 +32,7 @@ module ApacheAge
|
|
32
32
|
end
|
33
33
|
return if attributes.blank? && (end_query.blank? || start_query.blank?)
|
34
34
|
|
35
|
-
query = record.class.
|
35
|
+
query = record.class.find_by(edge_attribs.compact)
|
36
36
|
return if query.blank? || (query.id == record.id)
|
37
37
|
|
38
38
|
record.errors.add(:base, 'attribute combination not unique')
|
data/lib/rails_age/version.rb
CHANGED
data/lib/tasks/install.rake
CHANGED
@@ -1,91 +1,210 @@
|
|
1
1
|
# lib/tasks/install.rake
|
2
|
-
# Usage: `rake
|
2
|
+
# Usage: `rake apache_age:install`
|
3
3
|
#
|
4
|
-
namespace :
|
4
|
+
namespace :apache_age do
|
5
5
|
desc "Copy migrations from rails_age to application and update schema"
|
6
6
|
task :install => :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
|
+
# ensure we have a schema file
|
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
|
+
|
7
38
|
source = File.expand_path('../../../db/migrate', __FILE__)
|
8
|
-
destination = File.expand_path(
|
39
|
+
destination = File.expand_path("#{Rails.root}/db/migrate", __FILE__)
|
9
40
|
|
10
|
-
FileUtils.mkdir_p(destination) unless File.
|
41
|
+
FileUtils.mkdir_p(destination) unless File.exist?(destination)
|
42
|
+
existing_migrations =
|
43
|
+
Dir.glob("#{destination}/*.rb").map { |file| File.basename(file).sub(/^\d+/, '') }
|
11
44
|
|
12
45
|
Dir.glob("#{source}/*.rb").each do |file|
|
13
46
|
filename = File.basename(file)
|
14
|
-
|
47
|
+
test_name = filename.sub(/^\d+/, '')
|
15
48
|
|
16
|
-
if
|
49
|
+
if existing_migrations.include?(test_name)
|
17
50
|
puts "Skipping #{filename}, it already exists"
|
18
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)
|
19
56
|
FileUtils.cp(file, destination_file)
|
20
|
-
puts "Copied #{filename} to #{destination}"
|
57
|
+
puts "Copied #{filename} to #{destination} as #{new_filename}"
|
21
58
|
end
|
22
59
|
end
|
60
|
+
migration_version
|
61
|
+
end
|
23
62
|
|
24
|
-
|
25
|
-
|
26
|
-
if File.exists?(schema_file)
|
27
|
-
content = File.read(schema_file)
|
28
|
-
|
29
|
-
# Add the necessary extensions and configurations at the top of the schema
|
30
|
-
insert_statements = <<-RUBY
|
63
|
+
def blank_schema?(destination_schema)
|
64
|
+
return false unless File.exist?(destination_schema)
|
31
65
|
|
32
|
-
|
33
|
-
|
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
|
34
71
|
|
35
|
-
|
36
|
-
|
72
|
+
def run_migrations
|
73
|
+
puts "Running migrations..."
|
74
|
+
Rake::Task["db:migrate"].invoke
|
75
|
+
end
|
37
76
|
|
38
|
-
|
39
|
-
|
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
|
40
88
|
|
41
|
-
|
42
|
-
|
89
|
+
def create_new_schema(last_migration_version, destination_schema, source_schema)
|
90
|
+
if File.exist?(source_schema) && File.exist?(destination_schema)
|
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
|
43
111
|
|
44
|
-
|
45
|
-
|
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
|
+
)
|
46
121
|
|
47
|
-
|
122
|
+
destination_content = File.read(destination_schema)
|
48
123
|
|
49
|
-
|
50
|
-
|
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
|
+
)
|
51
161
|
end
|
52
162
|
|
53
|
-
|
54
|
-
|
55
|
-
content.gsub!(/^.*?create_schema "age_schema".*?\n\n/m, '')
|
56
|
-
content.gsub!(/^.*?enable_extension "age".*?\n\n/m, '')
|
57
|
-
content.gsub!(/^.*?# Could not dump table "_ag_label_edge" because of following StandardError.*?\n\n/m, '')
|
58
|
-
content.gsub!(/^.*?# Could not dump table "_ag_label_vertex" because of following StandardError.*?\n\n/m, '')
|
59
|
-
content.gsub!(/^.*?# Could not dump table "ag_graph" because of following StandardError.*?\n\n/m, '')
|
60
|
-
content.gsub!(/^.*?# Could not dump table "ag_label" because of following StandardError.*?\n\n/m, '')
|
61
|
-
content.gsub!(/^.*?add_foreign_key "ag_label", "ag_graph".*?\n\n/m, '')
|
62
|
-
|
63
|
-
File.write(schema_file, content)
|
64
|
-
puts "Updated #{schema_file} with necessary extensions and configurations."
|
163
|
+
File.write(destination_schema, destination_content)
|
164
|
+
puts "Updated #{destination_schema} with necessary extensions and configurations."
|
65
165
|
else
|
66
|
-
puts "schema.rb file not found.
|
166
|
+
puts "local db/schema.rb file not found."
|
67
167
|
end
|
68
168
|
end
|
69
|
-
end
|
70
169
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
#
|
75
|
-
|
76
|
-
|
77
|
-
#
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
#
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
#
|
88
|
-
|
89
|
-
#
|
90
|
-
|
91
|
-
|
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
|
206
|
+
|
207
|
+
# Write the modified lines back to the file
|
208
|
+
File.open(db_config_file, 'w') { |file| file.write(lines.join) }
|
209
|
+
end
|
210
|
+
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.
|
4
|
+
version: 0.3.0
|
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-05-
|
11
|
+
date: 2024-05-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -44,8 +44,8 @@ dependencies:
|
|
44
44
|
- - "~>"
|
45
45
|
- !ruby/object:Gem::Version
|
46
46
|
version: '6.0'
|
47
|
-
description: This plugin integrates Apache AGE with Rails 7.x, providing
|
48
|
-
helpers for working with graph databases within a Rails application.
|
47
|
+
description: This plugin integrates Apache AGE for PostgreSQL with Rails 7.x, providing
|
48
|
+
tools and helpers for working with graph databases within a Rails application.
|
49
49
|
email:
|
50
50
|
- btihen@gmail.com
|
51
51
|
executables: []
|
@@ -65,7 +65,7 @@ files:
|
|
65
65
|
- app/models/rails_age/application_record.rb
|
66
66
|
- app/views/layouts/rails_age/application.html.erb
|
67
67
|
- config/routes.rb
|
68
|
-
- db/migrate/
|
68
|
+
- db/migrate/20240521062349_add_apache_age.rb
|
69
69
|
- db/schema.rb
|
70
70
|
- lib/apache_age/entities/class_methods.rb
|
71
71
|
- lib/apache_age/entities/common_methods.rb
|