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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 349925c4b715d64987c69a6a20b23e67c9076d91152477a976ade763805fdbf7
4
- data.tar.gz: 4c7f1e430fe94ac3cb59eac8e6cb94bc03edab9532074c0df75be233b1210973
3
+ metadata.gz: aa956147280cd1ef2125eb39f3dd7867eadafde15806d95b90dab30d1290b135
4
+ data.tar.gz: a5b3a61d2fcf3026f9503b1bb4a9c6e60c6317f92266501f2890c2a02af1a01d
5
5
  SHA512:
6
- metadata.gz: af26f1a10253235703203804e508aa0d0dfbe7e44cc92097f70111587663c9af75e6cfd730fcb0986dc6093bb9bb16c847ab66ad7d3249057d3fe8adf443c78e
7
- data.tar.gz: f98980a1937efeef70c1e548b2f62f5b2a7e2f383f707a92e8392a8f45b1bc9ac882a1f478fff0f24f1fcb3cb145e0f037202356ea4a2e76737ee81f4c70b459
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.0 - 2024-xx-xx
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
- * Create, Read, Update, Delete & .find(by id), .find_by(age_property), .all
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
- * Create, Read, Update, Delete & .find(by id), .find_by(age_property), .all
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 (by id), find_by(age_property), all; when class/label and/or edge/node is unknown)
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
- And then execute:
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
- Or install it yourself as:
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
- ```bash
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
- # db/migrate/20240521062349_configure_apache_age.rb
32
- class ConfigureApacheAge < ActiveRecord::Migration[7.1]
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
- and fix the TOP of `schema.rb` file to match the following (note: the version number should be the same as the LARGEST version number in your `db/migrations` folder)
70
- https://github.com/marpori/rails_age/blob/main/db/schema.rb
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/works_at.rb
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 # if using optional age types
158
- # attribute :end_node, :person # if using optional age types
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
  ```
@@ -1,4 +1,4 @@
1
- class ConfigureApacheAge < ActiveRecord::Migration[7.1]
1
+ class AddApacheAge < ActiveRecord::Migration[7.1]
2
2
  def up
3
3
  # Allow age extension
4
4
  execute('CREATE EXTENSION IF NOT EXISTS age;')
@@ -8,29 +8,15 @@ module ApacheAge
8
8
  instance
9
9
  end
10
10
 
11
- def find_edge(attributes)
12
- where_attribs =
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
- cypher_sql = find_edge_sql(where_clause)
28
- execute_find(cypher_sql)
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.find_edge(edge_attribs.compact)
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')
@@ -1,3 +1,3 @@
1
1
  module RailsAge
2
- VERSION = "0.2.0"
2
+ VERSION = '0.3.0'
3
3
  end
@@ -1,91 +1,210 @@
1
1
  # lib/tasks/install.rake
2
- # Usage: `rake rails_age:install`
2
+ # Usage: `rake apache_age:install`
3
3
  #
4
- namespace :rails_age do
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('../../../../db/migrate', __FILE__)
39
+ destination = File.expand_path("#{Rails.root}/db/migrate", __FILE__)
9
40
 
10
- FileUtils.mkdir_p(destination) unless File.exists?(destination)
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
- destination_file = File.join(destination, filename)
47
+ test_name = filename.sub(/^\d+/, '')
15
48
 
16
- if File.exists?(destination_file)
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
- # Update the schema.rb file
25
- schema_file = File.expand_path('../../../../db/schema.rb', __FILE__)
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
- # These are extensions that must be enabled in order to support this database
33
- enable_extension "plpgsql"
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
- # Allow age extension
36
- execute('CREATE EXTENSION IF NOT EXISTS age;')
72
+ def run_migrations
73
+ puts "Running migrations..."
74
+ Rake::Task["db:migrate"].invoke
75
+ end
37
76
 
38
- # Load the age code
39
- execute("LOAD 'age';")
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
- # Load the ag_catalog into the search path
42
- execute('SET search_path = ag_catalog, "$user", public;')
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
- # Create age_schema graph if it doesn't exist
45
- execute("SELECT create_graph('age_schema');")
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
- RUBY
122
+ destination_content = File.read(destination_schema)
48
123
 
49
- unless content.include?(insert_statements.strip)
50
- content.sub!(/^# These are extensions that must be enabled in order to support this database.*?\n\n/m, insert_statements)
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
- # Remove unwanted schema statements
54
- content.gsub!(/^.*?create_schema "ag_catalog".*?\n\n/m, '')
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. Please ensure migrations have been run."
166
+ puts "local db/schema.rb file not found."
67
167
  end
68
168
  end
69
- end
70
169
 
71
- # namespace :rails_age do
72
- # desc "Copy migrations from rails_age to application"
73
- # task :install => :environment do
74
- # source = File.expand_path('../../../db/migrate', __FILE__)
75
- # destination = File.expand_path('../../../../db/migrate', __FILE__)
76
-
77
- # FileUtils.mkdir_p(destination) unless File.exists?(destination)
78
-
79
- # Dir.glob("#{source}/*.rb").each do |file|
80
- # filename = File.basename(file)
81
- # destination_file = File.join(destination, filename)
82
-
83
- # if File.exists?(destination_file)
84
- # puts "Skipping #{filename}, it already exists"
85
- # else
86
- # FileUtils.cp(file, destination_file)
87
- # puts "Copied #{filename} to #{destination}"
88
- # end
89
- # end
90
- # end
91
- # end
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.2.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-26 00:00:00.000000000 Z
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 tools and
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/20240521062349_configure_apache_age.rb
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