rails_age 0.4.1 → 0.5.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (31) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +27 -10
  3. data/README.md +7 -4
  4. data/lib/apache_age/validators/{unique_edge_validator.rb → unique_edge.rb} +8 -4
  5. data/lib/apache_age/validators/{unique_vertex_validator.rb → unique_vertex.rb} +7 -3
  6. data/lib/generators/apache_age/edge/USAGE +18 -15
  7. data/lib/generators/apache_age/edge/edge_generator.rb +14 -41
  8. data/lib/generators/apache_age/edge/templates/edge.rb.tt +22 -14
  9. data/lib/generators/apache_age/generator_entity_helpers.rb +84 -0
  10. data/lib/generators/apache_age/generator_resource_helpers.rb +6 -0
  11. data/lib/generators/apache_age/node/USAGE +7 -7
  12. data/lib/generators/apache_age/node/node_generator.rb +9 -82
  13. data/lib/generators/apache_age/node/templates/node.rb.tt +2 -2
  14. data/lib/generators/apache_age/scaffold_node/USAGE +16 -0
  15. data/lib/generators/apache_age/scaffold_node/scaffold_node_generator.rb +68 -0
  16. data/lib/generators/apache_age/scaffold_node/templates/node_controller.rb.tt +50 -0
  17. data/lib/generators/apache_age/scaffold_node/templates/views/_form.html.erb copy.tt +37 -0
  18. data/lib/generators/apache_age/scaffold_node/templates/views/_form.html.erb.tt +37 -0
  19. data/lib/generators/apache_age/scaffold_node/templates/views/edit.html.erb copy.tt +12 -0
  20. data/lib/generators/apache_age/scaffold_node/templates/views/edit.html.erb.tt +12 -0
  21. data/lib/generators/apache_age/scaffold_node/templates/views/index.html.erb copy.tt +16 -0
  22. data/lib/generators/apache_age/scaffold_node/templates/views/index.html.erb.tt +16 -0
  23. data/lib/generators/apache_age/scaffold_node/templates/views/new.html.erb copy.tt +11 -0
  24. data/lib/generators/apache_age/scaffold_node/templates/views/new.html.erb.tt +11 -0
  25. data/lib/generators/apache_age/scaffold_node/templates/views/partial.html.erb copy.tt +17 -0
  26. data/lib/generators/apache_age/scaffold_node/templates/views/partial.html.erb.tt +17 -0
  27. data/lib/generators/apache_age/scaffold_node/templates/views/show.html.erb copy.tt +10 -0
  28. data/lib/generators/apache_age/scaffold_node/templates/views/show.html.erb.tt +10 -0
  29. data/lib/rails_age/version.rb +1 -1
  30. data/lib/rails_age.rb +2 -2
  31. metadata +21 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 03e419984be6f29b1da74d0de6e31ccb218ba966e3818537884fcff715024e02
4
- data.tar.gz: cb5a30c1e17ee7bf30394691232e3185e317ef5e827ece3ab02ef7d14cb0aef5
3
+ metadata.gz: d54712ca67a303ffa92d78165d30a500b1f695be6176b3198e7ff3f9f60ab4f9
4
+ data.tar.gz: 8f8f999c42777dc432bf543b6256852d10a0fbcbcd4fe33ad06817277a47bb5d
5
5
  SHA512:
6
- metadata.gz: 555b80c544a8d5217d5c40ef3f24c15cd8fbf0c13bf96d1445845d9afc21d5e2ab835a60ac678ba5177fa5562ef1b87d7f293226783c94f1470d8b64e7a56fd9
7
- data.tar.gz: 303f2776ebc5320711f50ec54e9a136ba7d9727fcb28c8d0038ffdcb0edb94d6715b93f40598a70d3eb3b8f1405a05610a707458f91209288414f0a4a7251374
6
+ metadata.gz: 75c804a5b29705a18344ea70d9a799ea3578d90055b056ba48b70984132f2fbd04bdd906ac744e2a587fe095e9a8e112d773ecc84cf6325be192c212d769090d
7
+ data.tar.gz: 932a6c5843243a23ef48b69e87f0fef940030c9e47ce652be141bc6efb45a8cbde04c191853b3d15e754e3ee71d7033b301ab6432982c1fc357250fceb892f02
data/CHANGELOG.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Change Log
2
2
 
3
- ## VERSION 0.5.1 - 2024-xx-xx
3
+ ## VERSION 0.6.2 - 2024-xx-xx
4
4
 
5
5
  - **cypher queries** (like active record queries)
6
6
  * schema override
@@ -8,32 +8,49 @@
8
8
  * paths support
9
9
  * select attributes support
10
10
 
11
- ## VERSION 0.5.0 - 2024-xx-xx
11
+ ## VERSION 0.6.1 - 2024-xx-xx
12
12
 
13
13
  - **Age Path**
14
14
 
15
- ## VERSION 0.4.3 - 2024-xx-xx
15
+ ## VERSION 0.6.0 - 2024-xx-xx
16
+
17
+ breaking change?: namespaces (by default) will use their own schema? (add to database.yml & schema.rb ?)
16
18
 
17
19
  - **AGE Schema override**
18
20
 
19
21
  - **multiple AGE Schema**
20
22
 
21
- ## VERSION 0.4.3 - 2024-xx-xx
23
+ ## VERSION 0.5.3 - 2024-xx-xx
22
24
 
23
25
  - **Edge Scaffold** (generates edge, type, view and controller)
24
26
  * add `rails generate apache_age:edge_scaffold HasJob employee_role start_node:person end_node:company`
25
27
 
26
- ## VERSION 0.4.2 - 2024-xx-xx
28
+ ## VERSION 0.5.2 - 2024-xx-xx
29
+
30
+ - **Edge Generator**
31
+ * add start-/end-nodes types to edge generator (would make scaffold easier), ie:
32
+ `rails generate apache_age:edge HasPet owner_role start_node:person end_node:pet`
33
+ with property and specified start-/end-nodes (person and pet nodes must have already been created)
34
+
35
+ ## VERSION 0.5.2 - 2024-06-16
36
+
37
+ - **Node Scaffold** (generates node, type, view and controller)
38
+ * add `rails generate apache_age:node_scaffold Person first_name last_name age:integer`
39
+
40
+ ## VERSION 0.5.1 - 2024-06-16
41
+
42
+ **yanked** (2024-06-16) - had an issue with the generator
27
43
 
28
44
  - **Node Scaffold** (generates node, type, view and controller)
29
45
  * add `rails generate apache_age:node_scaffold Person first_name last_name age:integer`
30
46
 
31
- ## VERSION 0.4.2 - 2024-xx-xx
47
+ ## VERSION 0.5.0 - 2024-06-15
48
+
49
+ **breaking change**: renamed the validators to UniqueVertex and UniqueEdge
32
50
 
33
51
  - **Edge Generator**
34
- * add `rails generate apache_age:edge HasPet owner_role` just a property
35
- * add `rails generate apache_age:edge HasPet owner_role start_node:person end_node:pet`
36
- with property and specified start-/end-nodes (person and pet nodes must have already been created)
52
+ * add `rails generate apache_age:edge HasPet owner_role`
53
+ caveate: start_node and end_node are of type `:vertex` in the generator but can be changed manually in the class file - having trouble with the generator loading the types (the generator rejects custom types - but rails still works with custom types)
37
54
 
38
55
  ## VERSION 0.4.1 - 2024-06-15
39
56
 
@@ -43,7 +60,7 @@
43
60
 
44
61
  ## VERSION 0.4.0 - 2024-06-14
45
62
 
46
- Minor breaking change: type (:vertix) is now required in core for edges
63
+ **breaking change**: type (:vertix) is now required in core for edges
47
64
 
48
65
  - **Installer**
49
66
  * AGE types added to installer (with tests)
data/README.md CHANGED
@@ -55,8 +55,11 @@ install Apache Age (you can ignore the `unknown OID` warnings)
55
55
  bundle add rails_age
56
56
  bundle install
57
57
  bin/rails apache_age:install
58
+ # optional: prevents `bin/rails db:migrate` from modifying the schema file,
59
+ # alternatively you can use: `bin/rails apache_age:migrate` to run safe migrations
60
+ bin/rails apache_age:override_db_migrate
58
61
  git add .
59
- git commit -m "Add Apache Age to Rails"
62
+ git commit -m "Add & configure Apache Age within Rails"
60
63
  ```
61
64
 
62
65
  make some nodes :string is the default type
@@ -69,10 +72,10 @@ make some edges (`:vertex` is the default type) for start_node and end_node
69
72
  ```bash
70
73
  # when start node and end node are not specified they are of type `:vertex`
71
74
  # this is generally not recommended - exept when very generic relationships are needed
72
- rails generate apache_age:edge HasJob employee_role
75
+ rails generate apache_age:edge HasJob employee_role begin_date:date
73
76
 
74
- # this is recommended - use explicit start_node and end_node types
75
- rails generate apache_age:node HasPet start_node:person end_node:pet caretaker_role
77
+ # # this is recommended - (but not yet working) add explicit start_node and end_node types manually
78
+ # rails generate apache_age:node HasPet start_node:person end_node:pet caretaker_role
76
79
  ```
77
80
 
78
81
  **NOTE:** the default `rails db:migrate` inappropriately modifies the schema file. This installer patches the migration to prevent this (however this might break on rails updates, etc). **You can run `bin/rails apache_age:install` at any time to repair the schema file as needed.**
@@ -1,10 +1,14 @@
1
+ # lib/apache_age/validators/unique_edge.rb
2
+
1
3
  # Usage (within an Age Model)
2
- # validates_with UniqueEdgeValidator, attributes: [:employee_role, :start_node, :end_node]
3
- # validates_with UniqueEdgeValidator, attributes: [:start_id, :employee_role, :end_id]
4
- #
4
+ # validates_with(
5
+ # ApacheAge::Validators::UniqueEdge,
6
+ # attributes: [:start_id, :employee_role, :end_id]
7
+ # )
8
+
5
9
  module ApacheAge
6
10
  module Validators
7
- class UniqueEdgeValidator < ActiveModel::Validator
11
+ class UniqueEdge < ActiveModel::Validator
8
12
  def validate(record)
9
13
  allowed_keys = record.age_properties.keys
10
14
  attributes = options[:attributes] || []
@@ -1,10 +1,14 @@
1
+ # lib/apache_age/validators/unique_vertex.rb
2
+
1
3
  # Usage (within an Age Model)
2
- # validates_with UniqueVertexValidator, attributes: [:first_name, :last_name, :gender]
4
+ # validates_with(
5
+ # ApacheAge::Validators::UniqueVertex,
6
+ # attributes: [:first_name, :last_name, :gender]
7
+ # )
3
8
 
4
- # lib/apache_age/validators/unique_vertex_validator.rb
5
9
  module ApacheAge
6
10
  module Validators
7
- class UniqueVertexValidator < ActiveModel::Validator
11
+ class UniqueVertex < ActiveModel::Validator
8
12
  def validate(record)
9
13
  allowed_keys = record.age_properties.keys
10
14
  attributes = options[:attributes]
@@ -1,35 +1,38 @@
1
1
  Description:
2
- This creates Apache AGE nodes that work seamlessly with Rails.
3
- A node can be created with or without a namespace.
2
+ This creates Apache AGE edges that work seamlessly with Rails.
3
+ An edge can be created with or without a namespace.
4
4
  See the below examples.
5
5
 
6
6
  Example:
7
- `bin/rails g apache_age:node Cat name age:integer`
7
+ `bin/rails g apache_age:edge HasJob employee_role start_date:date`
8
+
9
+ (hopefully comming soon - but not yet ready is the ability to add start_node and end_node types)
10
+ `bin/rails g apache_age:edge HasJob employee_role start_date:date start_node:person end_node:company`
8
11
 
9
12
  This creates:
10
- `app/nodes/cat.rb`
13
+ `app/edges/has_job.rb`
11
14
 
12
15
  with the contents:
13
16
  ```
14
- class Cat
15
- include ApacheAge::Entities::Vertex
17
+ class HasJob
18
+ include ApacheAge::Entities::Edge
16
19
 
17
- attribute :name, :string
18
- attribute :age, :integer
20
+ attribute :employee_role, :string
21
+ attribute :start_date, :date
19
22
 
20
- validates :name, presence: true
21
- validates :age, presence: true
23
+ validates :employee_role, presence: true
24
+ validates :begin_date, presence: true
22
25
 
23
26
  # unique node validator (remove any attributes that are not important to uniqueness)
24
27
  validates_with(
25
- ApacheAge::Validators::UniqueVertexValidator,
26
- attributes: [:name, :age]
28
+ ApacheAge::Validators::UniqueVertex,
29
+ attributes: [:employee_role, :begin_date :start_node, :end_node]
27
30
  )
28
31
  end
29
32
  ```
30
33
 
31
34
  A namespace can also be used:
32
- `bin/rails g apache_age:node Animals/Cat name age:integer`
35
+ `bin/rails g apache_age:edge Animals/Cat name age:integer`
33
36
 
34
37
  This creates:
35
38
  `app/nodes/animals/cat.rb`
@@ -47,8 +50,8 @@ Example:
47
50
 
48
51
  # unique node validator (remove any attributes that are not important to uniqueness)
49
52
  validates_with(
50
- ApacheAge::Validators::UniqueVertexValidator,
51
- attributes: [:name, :age]
53
+ ApacheAge::Validators::UniqueVertex,
54
+ attributes: [:name, :age, :start_node, :end_node]
52
55
  )
53
56
  end
54
57
  ```
@@ -1,56 +1,29 @@
1
+ # lib/generators/apache_age/edge/edge_generator.rb
1
2
  require 'rails/generators'
2
3
  require 'rails/generators/named_base'
3
4
 
5
+ require_relative '../generator_entity_helpers'
6
+ # TODO: get generators to work with custom types!
7
+ # require_relative "#{Rails.root}/config/initializers/types"
8
+
4
9
  module ApacheAge
5
10
  class EdgeGenerator < Rails::Generators::NamedBase
11
+ include ApacheAge::GeneratorEntityHelpers
12
+
13
+ desc "Generates edge (model) with attributes."
14
+
6
15
  source_root File.expand_path('templates', __dir__)
7
16
  argument :attributes, type: :array, default: [], banner: "field:type field:type"
8
17
 
9
18
  def perform_task
10
- behavior == :invoke ? create_edge_file : destroy_edge_file
19
+ age_type = 'edge'
20
+ Rails.application.eager_load! # Ensure all initializers and dependencies are loaded
21
+ behavior == :invoke ? generate_age_entity(age_type) : destroy_age_entity(age_type)
11
22
  end
12
23
 
13
24
  private
14
25
 
15
- def create_edge_file
16
- template "edge.rb.tt", File.join("app/edge", class_path, "#{file_name}.rb")
17
- end
18
-
19
- def destroy_edge_file
20
- file_path = File.join("app/edge", class_path, "#{file_name}.rb")
21
- File.delete(file_path) if File.exist?(file_path)
22
- end
23
-
24
- def attributes_list
25
- attributes.map { |attr| { name: attr.name, type: attr.type } }
26
- end
27
-
28
- def unique_attributes
29
- attributes_list.map { |attr| attr[:name].to_sym }
30
- end
31
-
32
- def parent_module
33
- class_path.map(&:camelize).join('::')
34
- end
35
-
36
- def full_class_name
37
- parent_module.empty? ? class_name : "#{parent_module}::#{class_name}"
38
- end
39
-
40
- def indented_namespace
41
- return '' if parent_module.empty?
42
-
43
- parent_module.split('::').map.with_index do |namespace, index|
44
- "#{' ' * index}module #{namespace}"
45
- end.join("\n") + "\n"
46
- end
47
-
48
- def indented_end_namespace
49
- return '' if parent_module.empty?
50
-
51
- parent_module.split('::').map.with_index do |_, index|
52
- "#{' ' * (parent_module.split('::').length - 1 - index)}end"
53
- end.join("\n") + "\n"
54
- end
26
+ # different than node_generator.rb
27
+ def unique_edge_attributes = unique_attributes + [:start_node, :end_node]
55
28
  end
56
29
  end
@@ -1,20 +1,28 @@
1
- <%= indented_namespace %>
2
- <%= ' ' * class_path.length %>class <%= class_name %>
3
- <%= ' ' * class_path.length %> include ApacheAge::Entities::Edge
1
+ class <%= class_name %>
2
+ include ApacheAge::Entities::Edge
4
3
 
5
4
  <%- attributes_list.each do |attribute| -%>
6
- <%= ' ' * class_path.length %> attribute :<%= attribute[:name] %>, :<%= attribute[:reference] || attribute[:type] %>
5
+ attribute :<%= attribute[:name] %>, :<%= attribute[:reference] || attribute[:type] %>
7
6
  <%- end -%>
7
+ # recommendation for (start_node and end_node): change `:vertex` with the 'node' type
8
+ # see `config/initializers/apache_age.rb` for the list of available node types
9
+ attribute :start_node, :vertex
10
+ attribute :end_node, :vertex
8
11
 
9
- <%= ' ' * class_path.length %> validates :<%= unique_attributes.first %>, presence: true
10
- <%= ' ' * class_path.length %> validate :validate_unique
12
+ <%- attributes_list.each do |attribute| -%>
13
+ validates :<%= attribute[:name] %>, presence: true
14
+ <%- end -%>
15
+ validates :start_node, presence: true
16
+ validates :end_node, presence: true
17
+
18
+ validate :validate_unique_edge
11
19
 
12
- <%= ' ' * class_path.length %> private
20
+ private
13
21
 
14
- <%= ' ' * class_path.length %> def validate_unique
15
- <%= ' ' * class_path.length %> ApacheAge::Validators::UniqueEdgeValidator
16
- <%= ' ' * class_path.length %> .new(attributes: <%= unique_attributes.inspect %>)
17
- <%= ' ' * class_path.length %> .validate(self)
18
- <%= ' ' * class_path.length %> end
19
- <%= ' ' * class_path.length %>end
20
- <%= indented_end_namespace %>
22
+ # custom unique edge validator (remove any attributes that are NOT important to uniqueness)
23
+ def validate_unique_edge
24
+ ApacheAge::Validators::UniqueEdge
25
+ .new(attributes: <%= unique_edge_attributes.inspect %>)
26
+ .validate(self)
27
+ end
28
+ end
@@ -0,0 +1,84 @@
1
+ # lib/generators/apache_age/generator_entity_helpers.rb
2
+
3
+ module ApacheAge
4
+ module GeneratorEntityHelpers
5
+ def generate_age_entity(age_type)
6
+ template "#{age_type}.rb.tt", File.join(destination_root, "app/#{age_type}s", class_path, "#{file_name}.rb")
7
+ add_type_config
8
+ end
9
+
10
+ def destroy_age_entity(age_type)
11
+ file_path = File.join(destination_root, "app/#{age_type}s", class_path, "#{file_name}.rb")
12
+ File.delete(file_path) if File.exist?(file_path)
13
+ remove_type_config
14
+ end
15
+
16
+ def attributes_list
17
+ attributes.map { |attr| { name: attr.name, type: attr.type } }
18
+ end
19
+
20
+ def parent_module
21
+ class_path.map(&:camelize).join('::')
22
+ end
23
+
24
+ def unique_attributes
25
+ attributes_list.map { |attr| attr[:name].to_sym }
26
+ end
27
+
28
+ def full_class_name
29
+ parent_module.empty? ? class_name : "#{parent_module}::#{class_name}"
30
+ end
31
+
32
+ def indented_namespace
33
+ return '' if parent_module.empty?
34
+
35
+ parent_module.split('::').map.with_index do |namespace, index|
36
+ "#{' ' * index}module #{namespace}"
37
+ end.join("\n") + "\n"
38
+ end
39
+
40
+ # def indented_end_namespace
41
+ # return '' if parent_module.empty?
42
+
43
+ # parent_module.split('::').map.with_index do |_, index|
44
+ # "#{' ' * (parent_module.split('::').length - 1 - index)}end"
45
+ # end.join("\n") + "\n"
46
+ # end
47
+
48
+ def add_type_config
49
+ return unless File.exist?(types_config_file)
50
+
51
+ types_content = File.read(types_config_file)
52
+ types_content.sub!(/^end\s*$/, "#{new_type_content}end")
53
+ File.open(types_config_file, 'w') { |file| file.write(types_content) }
54
+ puts " modified: config/initializers/types.rb"
55
+ end
56
+
57
+ def remove_type_config
58
+ return unless File.exist?(types_config_file)
59
+
60
+ type_to_remove = new_type_content
61
+
62
+ types_content = File.read(types_config_file)
63
+ types_content.gsub!(type_to_remove, '')
64
+ File.open(types_config_file, 'w') { |file| file.write(types_content) }
65
+ end
66
+
67
+ def types_config_file = File.join(Rails.root, 'config/initializers/types.rb')
68
+
69
+ def new_type_content
70
+ file_path = [class_path, file_name].reject(&:blank?).join('/').downcase
71
+ entity_namespace = class_path.map(&:capitalize).join('::')
72
+ entity_class_name = file_name.split('_').map(&:capitalize).join
73
+ entity_namespaced_class = [entity_namespace, entity_class_name].reject(&:blank?).join('::')
74
+ type_name = [class_path.join('_'), file_name].reject(&:blank?).join('_')
75
+ content =
76
+ <<-RUBY
77
+ require_dependency '#{file_path}'
78
+ ActiveModel::Type.register(
79
+ :#{type_name}, ApacheAge::Types::AgeTypeGenerator.create_type_for(#{entity_namespaced_class})
80
+ )
81
+ RUBY
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,6 @@
1
+ module ApacheAge
2
+ # Some helpers for generating scaffolding
3
+ module GeneratorResourceHelpers
4
+
5
+ end
6
+ end
@@ -14,16 +14,16 @@ Example:
14
14
  class Cat
15
15
  include ApacheAge::Entities::Vertex
16
16
 
17
- attribute :name, :string
18
- attribute :age, :integer
17
+ attribute :full_name, :string
18
+ attribute :birthdate, :date
19
19
 
20
- validates :name, presence: true
21
- validates :age, presence: true
20
+ validates :full_name, presence: true
21
+ validates :birthdate, presence: true
22
22
 
23
23
  # unique node validator (remove any attributes that are not important to uniqueness)
24
24
  validates_with(
25
- ApacheAge::Validators::UniqueVertexValidator,
26
- attributes: [:name, :age]
25
+ ApacheAge::Validators::UniqueVertex,
26
+ attributes: [:full_name, :birthdate]
27
27
  )
28
28
  end
29
29
  ```
@@ -47,7 +47,7 @@ Example:
47
47
 
48
48
  # unique node validator (remove any attributes that are not important to uniqueness)
49
49
  validates_with(
50
- ApacheAge::Validators::UniqueVertexValidator,
50
+ ApacheAge::Validators::UniqueVertex,
51
51
  attributes: [:name, :age]
52
52
  )
53
53
  end
@@ -1,94 +1,21 @@
1
+ # lib/generators/apache_age/node/entity_generator.rb
1
2
  require 'rails/generators'
2
3
  require 'rails/generators/named_base'
3
4
 
5
+ require_relative '../generator_entity_helpers'
6
+
4
7
  module ApacheAge
5
8
  class NodeGenerator < Rails::Generators::NamedBase
9
+ include ApacheAge::GeneratorEntityHelpers
10
+
11
+ desc "Generates node (model) with attributes."
12
+
6
13
  source_root File.expand_path('templates', __dir__)
7
14
  argument :attributes, type: :array, default: [], banner: "field:type field:type"
8
15
 
9
16
  def perform_task
10
- behavior == :invoke ? create_node_file : destroy_node_file
11
- end
12
-
13
- private
14
-
15
- def create_node_file
16
- template "node.rb.tt", File.join(destination_root, "app/nodes", class_path, "#{file_name}.rb")
17
- add_type_config
18
- end
19
-
20
- def destroy_node_file
21
- file_path = File.join(destination_root, "app/nodes", class_path, "#{file_name}.rb")
22
- File.delete(file_path) if File.exist?(file_path)
23
- remove_type_config
24
- end
25
-
26
- def attributes_list
27
- attributes.map { |attr| { name: attr.name, type: attr.type } }
28
- end
29
-
30
- def unique_attributes
31
- attributes_list.map { |attr| attr[:name].to_sym }
32
- end
33
-
34
- def parent_module
35
- class_path.map(&:camelize).join('::')
36
- end
37
-
38
- def full_class_name
39
- parent_module.empty? ? class_name : "#{parent_module}::#{class_name}"
40
- end
41
-
42
- def indented_namespace
43
- return '' if parent_module.empty?
44
-
45
- parent_module.split('::').map.with_index do |namespace, index|
46
- "#{' ' * index}module #{namespace}"
47
- end.join("\n") + "\n"
48
- end
49
-
50
- def indented_end_namespace
51
- return '' if parent_module.empty?
52
-
53
- parent_module.split('::').map.with_index do |_, index|
54
- "#{' ' * (parent_module.split('::').length - 1 - index)}end"
55
- end.join("\n") + "\n"
56
- end
57
-
58
- def add_type_config
59
- return unless File.exist?(types_config_file)
60
-
61
- types_content = File.read(types_config_file)
62
- types_content.sub!(/^end\s*$/, "#{new_type_content}end")
63
- File.open(types_config_file, 'w') { |file| file.write(types_content) }
64
- puts " modified: config/initializers/types.rb"
65
- end
66
-
67
- def remove_type_config
68
- return unless File.exist?(types_config_file)
69
-
70
- type_to_remove = new_type_content
71
-
72
- types_content = File.read(types_config_file)
73
- types_content.gsub!(type_to_remove, '')
74
- File.open(types_config_file, 'w') { |file| file.write(types_content) }
75
- end
76
-
77
- def types_config_file = File.join(Rails.root, 'config/initializers/types.rb')
78
-
79
- def new_type_content
80
- file_path = [class_path, file_name].reject(&:blank?).join('/').downcase
81
- node_namespace = class_path.map(&:capitalize).join('::')
82
- node_class_name = file_name.split('_').map(&:capitalize).join
83
- node_namespaced_class = [node_namespace, node_class_name].reject(&:blank?).join('::')
84
- type_name = [class_path.join('_'), file_name].reject(&:blank?).join('_')
85
- content =
86
- <<-RUBY
87
- require_dependency '#{file_path}'
88
- ActiveModel::Type.register(
89
- :#{type_name}, ApacheAge::Types::AgeTypeGenerator.create_type_for(#{node_namespaced_class})
90
- )
91
- RUBY
17
+ age_type = 'node'
18
+ behavior == :invoke ? generate_age_entity(age_type) : destroy_age_entity(age_type)
92
19
  end
93
20
  end
94
21
  end
@@ -9,9 +9,9 @@ class <%= class_name %>
9
9
  validates :<%= attribute[:name] %>, presence: true
10
10
  <%- end -%>
11
11
 
12
- # unique node validator (remove any attributes that are not important to uniqueness)
12
+ # custom unique node validator (remove any attributes that are NOT important to uniqueness)
13
13
  validates_with(
14
- ApacheAge::Validators::UniqueVertexValidator,
14
+ ApacheAge::Validators::UniqueVertex,
15
15
  attributes: <%= unique_attributes.inspect %>
16
16
  )
17
17
  end
@@ -0,0 +1,16 @@
1
+ Description:
2
+ Explain the generator
3
+
4
+ Example:
5
+ bin/rails generate apache_age:scaffold_node Pet name birthdate:date
6
+
7
+ This will create:
8
+ create app/nodes/pet.rb
9
+ modified: config/initializers/types.rb
10
+ create app/controllers/pets_controller.rb
11
+ route resources :pets
12
+ create app/views/pets/index.html.erb
13
+ create app/views/pets/edit.html.erb
14
+ create app/views/pets/show.html.erb
15
+ create app/views/pets/new.html.erb
16
+ create app/views/pets/partial.html.erb
@@ -0,0 +1,68 @@
1
+ # lib/generators/apache_age/scaffold_node/scaffold_node_generator.rb
2
+
3
+ require 'rails/generators'
4
+ require 'rails/generators/named_base'
5
+ require 'rails/generators/resource_helpers'
6
+
7
+ require_relative '../generator_entity_helpers'
8
+ require_relative '../generator_resource_helpers'
9
+
10
+ module ApacheAge
11
+ class ScaffoldNodeGenerator < Rails::Generators::NamedBase
12
+ include Rails::Generators::ResourceHelpers
13
+ # include ApacheAge::GeneratorEntityHelpers
14
+ # include ApacheAge::GeneratorResourceHelpers
15
+
16
+ desc "Generates a node, and its controller and views with the given attributes."
17
+
18
+ source_root File.expand_path("templates", __dir__)
19
+
20
+ argument :attributes, type: :array, default: [], banner: "field:type field:type"
21
+
22
+ def create_model_file
23
+ invoke 'apache_age:node', [name] + attributes.collect { |attr| "#{attr.name}:#{attr.type}" }
24
+ end
25
+
26
+ def create_controller_files
27
+ template(
28
+ "node_controller.rb.tt",
29
+ File.join("app/controllers", controller_class_path, "#{controller_file_name}_controller.rb")
30
+ )
31
+ end
32
+
33
+ def create_route
34
+ if class_path.empty?
35
+ route "resources :#{file_name.pluralize}"
36
+ else
37
+ route nested_route(class_path, file_name)
38
+ end
39
+ end
40
+
41
+ def copy_view_files
42
+ available_views.each do |view|
43
+ view_name = view == 'partial' ? "_#{singular_table_name}" : view
44
+ filename = filename_with_extensions(view_name)
45
+ template "views/#{view}.html.erb.tt", File.join("app/views", controller_file_path, filename)
46
+ end
47
+ end
48
+
49
+ private
50
+
51
+ def available_views
52
+ %w[index edit show new partial _form]
53
+ end
54
+
55
+ def filename_with_extensions(view)
56
+ [view, :html, :erb].compact.join('.')
57
+ end
58
+
59
+ def nested_route(class_path, file_name)
60
+ # "namespace :#{class_path.join(':')} do\n resources :#{file_name.pluralize}\nend"
61
+ <<~RUBY
62
+ namespace :#{class_path.join(':')} do
63
+ resources :#{file_name.pluralize}
64
+ end
65
+ RUBY
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,50 @@
1
+ class <%= controller_class_name %>Controller < ApplicationController
2
+ before_action :set_<%= singular_table_name %>, only: %i[show edit update destroy]
3
+
4
+ def index
5
+ @<%= plural_table_name %> = <%= class_name %>.all
6
+ end
7
+
8
+ def show
9
+ end
10
+
11
+ def new
12
+ @<%= singular_table_name %> = <%= class_name %>.new
13
+ end
14
+
15
+ def edit
16
+ end
17
+
18
+ def create
19
+ @<%= singular_table_name %> = <%= class_name %>.new(<%= singular_table_name %>_params)
20
+
21
+ if @<%= singular_table_name %>.save
22
+ redirect_to @<%= singular_table_name %>, notice: '<%= human_name %> was successfully created.'
23
+ else
24
+ render :new
25
+ end
26
+ end
27
+
28
+ def update
29
+ if @<%= singular_table_name %>.update(<%= singular_table_name %>_params)
30
+ redirect_to @<%= singular_table_name %>, notice: '<%= human_name %> was successfully updated.'
31
+ else
32
+ render :edit
33
+ end
34
+ end
35
+
36
+ def destroy
37
+ @<%= singular_table_name %>.destroy
38
+ redirect_to <%= index_helper %>_url, notice: '<%= human_name %> was successfully destroyed.'
39
+ end
40
+
41
+ private
42
+
43
+ def set_<%= singular_table_name %>
44
+ @<%= singular_table_name %> = <%= class_name %>.find(params[:id])
45
+ end
46
+
47
+ def <%= singular_table_name %>_params
48
+ params.require(:<%= singular_table_name %>).permit(<%= attributes.map { |attr| ":#{attr.name}" }.join(', ') %>)
49
+ end
50
+ end
@@ -0,0 +1,37 @@
1
+ <%%= form_with(model: <%= model_resource_name %>) do |form| %>
2
+ <%% if <%= singular_table_name %>.errors.any? %>
3
+ <div style="color: red">
4
+ <h2><%%= pluralize(<%= singular_table_name %>.errors.count, "error") %> prohibited this <%= singular_table_name %> from being saved:</h2>
5
+
6
+ <ul>
7
+ <%% <%= singular_table_name %>.errors.each do |error| %>
8
+ <li><%%= error.full_message %></li>
9
+ <%% end %>
10
+ </ul>
11
+ </div>
12
+ <%% end %>
13
+
14
+ <% attributes.each do |attribute| -%>
15
+ <div>
16
+ <% if attribute.password_digest? -%>
17
+ <%%= form.label :password, style: "display: block" %>
18
+ <%%= form.password_field :password %>
19
+ </div>
20
+
21
+ <div>
22
+ <%%= form.label :password_confirmation, style: "display: block" %>
23
+ <%%= form.password_field :password_confirmation %>
24
+ <% elsif attribute.attachments? -%>
25
+ <%%= form.label :<%= attribute.column_name %>, style: "display: block" %>
26
+ <%%= form.<%= attribute.field_type %> :<%= attribute.column_name %>, multiple: true %>
27
+ <% else -%>
28
+ <%%= form.label :<%= attribute.column_name %>, style: "display: block" %>
29
+ <%%= form.<%= attribute.field_type %> :<%= attribute.column_name %> %>
30
+ <% end -%>
31
+ </div>
32
+
33
+ <% end -%>
34
+ <div>
35
+ <%%= form.submit %>
36
+ </div>
37
+ <%% end %>
@@ -0,0 +1,37 @@
1
+ <%%= form_with(model: <%= model_resource_name %>) do |form| %>
2
+ <%% if <%= singular_table_name %>.errors.any? %>
3
+ <div style="color: red">
4
+ <h2><%%= pluralize(<%= singular_table_name %>.errors.count, "error") %> prohibited this <%= singular_table_name %> from being saved:</h2>
5
+
6
+ <ul>
7
+ <%% <%= singular_table_name %>.errors.each do |error| %>
8
+ <li><%%= error.full_message %></li>
9
+ <%% end %>
10
+ </ul>
11
+ </div>
12
+ <%% end %>
13
+
14
+ <% attributes.each do |attribute| -%>
15
+ <div>
16
+ <% if attribute.password_digest? -%>
17
+ <%%= form.label :password, style: "display: block" %>
18
+ <%%= form.password_field :password %>
19
+ </div>
20
+
21
+ <div>
22
+ <%%= form.label :password_confirmation, style: "display: block" %>
23
+ <%%= form.password_field :password_confirmation %>
24
+ <% elsif attribute.attachments? -%>
25
+ <%%= form.label :<%= attribute.column_name %>, style: "display: block" %>
26
+ <%%= form.<%= attribute.field_type %> :<%= attribute.column_name %>, multiple: true %>
27
+ <% else -%>
28
+ <%%= form.label :<%= attribute.column_name %>, style: "display: block" %>
29
+ <%%= form.<%= attribute.field_type %> :<%= attribute.column_name %> %>
30
+ <% end -%>
31
+ </div>
32
+
33
+ <% end -%>
34
+ <div>
35
+ <%%= form.submit %>
36
+ </div>
37
+ <%% end %>
@@ -0,0 +1,12 @@
1
+ <%% content_for :title, "Editing <%= human_name.downcase %>" %>
2
+
3
+ <h1>Editing <%= human_name.downcase %></h1>
4
+
5
+ <%%= render "form", <%= singular_table_name %>: @<%= singular_table_name %> %>
6
+
7
+ <br>
8
+
9
+ <div>
10
+ <%%= link_to "Show this <%= human_name.downcase %>", <%= model_resource_name(prefix: "@") %> %> |
11
+ <%%= link_to "Back to <%= human_name.pluralize.downcase %>", <%= index_helper(type: :path) %> %>
12
+ </div>
@@ -0,0 +1,12 @@
1
+ <%% content_for :title, "Editing <%= human_name.downcase %>" %>
2
+
3
+ <h1>Editing <%= human_name.downcase %></h1>
4
+
5
+ <%%= render "form", <%= singular_table_name %>: @<%= singular_table_name %> %>
6
+
7
+ <br>
8
+
9
+ <div>
10
+ <%%= link_to "Show this <%= human_name.downcase %>", <%= model_resource_name(prefix: "@") %> %> |
11
+ <%%= link_to "Back to <%= human_name.pluralize.downcase %>", <%= index_helper(type: :path) %> %>
12
+ </div>
@@ -0,0 +1,16 @@
1
+ <p style="color: green"><%%= notice %></p>
2
+
3
+ <%% content_for :title, "<%= human_name.pluralize %>" %>
4
+
5
+ <h1><%= human_name.pluralize %></h1>
6
+
7
+ <div id="<%= plural_table_name %>">
8
+ <%% @<%= plural_table_name %>.each do |<%= singular_table_name %>| %>
9
+ <%%= render <%= singular_table_name %> %>
10
+ <p>
11
+ <%%= link_to "Show this <%= human_name.downcase %>", <%= model_resource_name(singular_table_name) %> %>
12
+ </p>
13
+ <%% end %>
14
+ </div>
15
+
16
+ <%%= link_to "New <%= human_name.downcase %>", <%= new_helper(type: :path) %> %>
@@ -0,0 +1,16 @@
1
+ <p style="color: green"><%%= notice %></p>
2
+
3
+ <%% content_for :title, "<%= human_name.pluralize %>" %>
4
+
5
+ <h1><%= human_name.pluralize %></h1>
6
+
7
+ <div id="<%= plural_table_name %>">
8
+ <%% @<%= plural_table_name %>.each do |<%= singular_table_name %>| %>
9
+ <%%= render '<%= singular_table_name %>', <%= singular_table_name %>: <%= singular_table_name %> %>
10
+ <p>
11
+ <%%= link_to "Show this <%= human_name.downcase %>", <%= model_resource_name(singular_table_name) %> %>
12
+ </p>
13
+ <%% end %>
14
+ </div>
15
+
16
+ <%%= link_to "New <%= human_name.downcase %>", <%= new_helper(type: :path) %> %>
@@ -0,0 +1,11 @@
1
+ <%% content_for :title, "New <%= human_name.downcase %>" %>
2
+
3
+ <h1>New <%= human_name.downcase %></h1>
4
+
5
+ <%%= render "form", <%= singular_table_name %>: @<%= singular_table_name %> %>
6
+
7
+ <br>
8
+
9
+ <div>
10
+ <%%= link_to "Back to <%= human_name.pluralize.downcase %>", <%= index_helper(type: :path) %> %>
11
+ </div>
@@ -0,0 +1,11 @@
1
+ <%% content_for :title, "New <%= human_name.downcase %>" %>
2
+
3
+ <h1>New <%= human_name.downcase %></h1>
4
+
5
+ <%%= render "form", <%= singular_table_name %>: @<%= singular_table_name %> %>
6
+
7
+ <br>
8
+
9
+ <div>
10
+ <%%= link_to "Back to <%= human_name.pluralize.downcase %>", <%= index_helper(type: :path) %> %>
11
+ </div>
@@ -0,0 +1,17 @@
1
+ <div id="<%%= dom_id <%= singular_table_name %> %>">
2
+ <% attributes.reject(&:password_digest?).each do |attribute| -%>
3
+ <p>
4
+ <strong><%= attribute.human_name %>:</strong>
5
+ <% if attribute.attachment? -%>
6
+ <%%= link_to <%= singular_table_name %>.<%= attribute.column_name %>.filename, <%= singular_table_name %>.<%= attribute.column_name %> if <%= singular_table_name %>.<%= attribute.column_name %>.attached? %>
7
+ <% elsif attribute.attachments? -%>
8
+ <%% <%= singular_table_name %>.<%= attribute.column_name %>.each do |<%= attribute.singular_table_name %>| %>
9
+ <div><%%= link_to <%= attribute.singular_table_name %>.filename, <%= attribute.singular_table_name %> %></div>
10
+ <%% end %>
11
+ <% else -%>
12
+ <%%= <%= singular_table_name %>.<%= attribute.column_name %> %>
13
+ <% end -%>
14
+ </p>
15
+
16
+ <% end -%>
17
+ </div>
@@ -0,0 +1,17 @@
1
+ <div id="<%%= dom_id <%= singular_table_name %> %>">
2
+ <% attributes.reject(&:password_digest?).each do |attribute| -%>
3
+ <p>
4
+ <strong><%= attribute.human_name %>:</strong>
5
+ <% if attribute.attachment? -%>
6
+ <%%= link_to <%= singular_table_name %>.<%= attribute.column_name %>.filename, <%= singular_table_name %>.<%= attribute.column_name %> if <%= singular_table_name %>.<%= attribute.column_name %>.attached? %>
7
+ <% elsif attribute.attachments? -%>
8
+ <%% <%= singular_table_name %>.<%= attribute.column_name %>.each do |<%= attribute.singular_name %>| %>
9
+ <div><%%= link_to <%= attribute.singular_name %>.filename, <%= attribute.singular_name %> %></div>
10
+ <%% end %>
11
+ <% else -%>
12
+ <%%= <%= singular_table_name %>.<%= attribute.column_name %> %>
13
+ <% end -%>
14
+ </p>
15
+
16
+ <% end -%>
17
+ </div>
@@ -0,0 +1,10 @@
1
+ <p style="color: green"><%%= notice %></p>
2
+
3
+ <%%= render @<%= singular_table_name %> %>
4
+
5
+ <div>
6
+ <%%= link_to "Edit this <%= human_name.downcase %>", <%= edit_helper(type: :path) %> %> |
7
+ <%%= link_to "Back to <%= human_name.pluralize.downcase %>", <%= index_helper(type: :path) %> %>
8
+
9
+ <%%= button_to "Destroy this <%= human_name.downcase %>", <%= model_resource_name(prefix: "@") %>, method: :delete %>
10
+ </div>
@@ -0,0 +1,10 @@
1
+ <p style="color: green"><%%= notice %></p>
2
+
3
+ <%%= render '<%= singular_table_name %>', <%= singular_table_name %>: @<%= singular_table_name %> %>
4
+
5
+ <div>
6
+ <%%= link_to "Edit this <%= human_name.downcase %>", <%= edit_helper(type: :path) %> %> |
7
+ <%%= link_to "Back to <%= human_name.pluralize.downcase %>", <%= index_helper(type: :path) %> %>
8
+
9
+ <%%= button_to "Destroy this <%= human_name.downcase %>", <%= model_resource_name(prefix: "@") %>, method: :delete %>
10
+ </div>
@@ -1,3 +1,3 @@
1
1
  module RailsAge
2
- VERSION = '0.4.1'
2
+ VERSION = '0.5.2'
3
3
  end
data/lib/rails_age.rb CHANGED
@@ -11,7 +11,7 @@ module ApacheAge
11
11
  require 'apache_age/entities/edge'
12
12
  require 'apache_age/entities/entity'
13
13
  require 'apache_age/entities/vertex'
14
+ require 'apache_age/validators/unique_edge'
15
+ require 'apache_age/validators/unique_vertex'
14
16
  require 'apache_age/types/age_type_generator'
15
- require 'apache_age/validators/unique_edge_validator'
16
- require 'apache_age/validators/unique_vertex_validator'
17
17
  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.1
4
+ version: 0.5.2
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-06-15 00:00:00.000000000 Z
11
+ date: 2024-06-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -73,15 +73,32 @@ files:
73
73
  - lib/apache_age/entities/entity.rb
74
74
  - lib/apache_age/entities/vertex.rb
75
75
  - lib/apache_age/types/age_type_generator.rb
76
- - lib/apache_age/validators/unique_edge_validator.rb
77
- - lib/apache_age/validators/unique_vertex_validator.rb
76
+ - lib/apache_age/validators/unique_edge.rb
77
+ - lib/apache_age/validators/unique_vertex.rb
78
78
  - lib/apache_age/validators/vertex_type_validator.rb
79
79
  - lib/generators/apache_age/edge/USAGE
80
80
  - lib/generators/apache_age/edge/edge_generator.rb
81
81
  - lib/generators/apache_age/edge/templates/edge.rb.tt
82
+ - lib/generators/apache_age/generator_entity_helpers.rb
83
+ - lib/generators/apache_age/generator_resource_helpers.rb
82
84
  - lib/generators/apache_age/node/USAGE
83
85
  - lib/generators/apache_age/node/node_generator.rb
84
86
  - lib/generators/apache_age/node/templates/node.rb.tt
87
+ - lib/generators/apache_age/scaffold_node/USAGE
88
+ - lib/generators/apache_age/scaffold_node/scaffold_node_generator.rb
89
+ - lib/generators/apache_age/scaffold_node/templates/node_controller.rb.tt
90
+ - lib/generators/apache_age/scaffold_node/templates/views/_form.html.erb copy.tt
91
+ - lib/generators/apache_age/scaffold_node/templates/views/_form.html.erb.tt
92
+ - lib/generators/apache_age/scaffold_node/templates/views/edit.html.erb copy.tt
93
+ - lib/generators/apache_age/scaffold_node/templates/views/edit.html.erb.tt
94
+ - lib/generators/apache_age/scaffold_node/templates/views/index.html.erb copy.tt
95
+ - lib/generators/apache_age/scaffold_node/templates/views/index.html.erb.tt
96
+ - lib/generators/apache_age/scaffold_node/templates/views/new.html.erb copy.tt
97
+ - lib/generators/apache_age/scaffold_node/templates/views/new.html.erb.tt
98
+ - lib/generators/apache_age/scaffold_node/templates/views/partial.html.erb copy.tt
99
+ - lib/generators/apache_age/scaffold_node/templates/views/partial.html.erb.tt
100
+ - lib/generators/apache_age/scaffold_node/templates/views/show.html.erb copy.tt
101
+ - lib/generators/apache_age/scaffold_node/templates/views/show.html.erb.tt
85
102
  - lib/rails_age.rb
86
103
  - lib/rails_age/engine.rb
87
104
  - lib/rails_age/version.rb