neo4j_ancestry 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +23 -0
- data/.travis.yml +11 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +7 -0
- data/Guardfile +24 -0
- data/MIT-LICENSE +22 -0
- data/README.md +73 -0
- data/Rakefile +15 -0
- data/config/initializers/001_neo4j.rb +39 -0
- data/db/migrate/20131102235736_create_links.rb +10 -0
- data/lib/models/neo4j_ancestry/active_record_additions.rb +111 -0
- data/lib/models/neo4j_ancestry/link.rb +28 -0
- data/lib/models/neo4j_ancestry/node_instance_methods.rb +93 -0
- data/lib/neo4j_ancestry.rb +11 -0
- data/lib/neo4j_ancestry/engine.rb +13 -0
- data/lib/neo4j_ancestry/railtie.rb +22 -0
- data/lib/neo4j_ancestry/version.rb +3 -0
- data/lib/tasks/db_test_prepare.rake +26 -0
- data/lib/tasks/setup.rake +24 -0
- data/lib/tasks/start.rake +12 -0
- data/lib/tasks/stop.rake +12 -0
- data/neo4j_ancestry.gemspec +33 -0
- data/rails3.2.Gemfile +7 -0
- data/rails4.Gemfile +7 -0
- data/script/rails +8 -0
- data/spec/dummy-rails3/.gitignore +15 -0
- data/spec/dummy-rails3/Gemfile +40 -0
- data/spec/dummy-rails3/README.rdoc +261 -0
- data/spec/dummy-rails3/Rakefile +7 -0
- data/spec/dummy-rails3/app/assets/images/rails.png +0 -0
- data/spec/dummy-rails3/app/assets/javascripts/application.js +15 -0
- data/spec/dummy-rails3/app/assets/stylesheets/application.css +13 -0
- data/spec/dummy-rails3/app/controllers/application_controller.rb +3 -0
- data/spec/dummy-rails3/app/helpers/application_helper.rb +2 -0
- data/spec/dummy-rails3/app/mailers/.gitkeep +0 -0
- data/spec/dummy-rails3/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy-rails3/config.ru +4 -0
- data/spec/dummy-rails3/config/application.rb +62 -0
- data/spec/dummy-rails3/config/boot.rb +6 -0
- data/spec/dummy-rails3/config/database.yml +25 -0
- data/spec/dummy-rails3/config/environment.rb +5 -0
- data/spec/dummy-rails3/config/environments/development.rb +37 -0
- data/spec/dummy-rails3/config/environments/production.rb +67 -0
- data/spec/dummy-rails3/config/environments/test.rb +37 -0
- data/spec/dummy-rails3/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy-rails3/config/initializers/inflections.rb +15 -0
- data/spec/dummy-rails3/config/initializers/mime_types.rb +5 -0
- data/spec/dummy-rails3/config/initializers/secret_token.rb +7 -0
- data/spec/dummy-rails3/config/initializers/session_store.rb +8 -0
- data/spec/dummy-rails3/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy-rails3/config/locales/en.yml +5 -0
- data/spec/dummy-rails3/config/routes.rb +58 -0
- data/spec/dummy-rails3/db/schema.rb +35 -0
- data/spec/dummy-rails3/db/seeds.rb +7 -0
- data/spec/dummy-rails3/lib/assets/.gitkeep +0 -0
- data/spec/dummy-rails3/lib/tasks/.gitkeep +0 -0
- data/spec/dummy-rails3/log/.gitkeep +0 -0
- data/spec/dummy-rails3/public/404.html +26 -0
- data/spec/dummy-rails3/public/422.html +26 -0
- data/spec/dummy-rails3/public/500.html +25 -0
- data/spec/dummy-rails3/public/favicon.ico +0 -0
- data/spec/dummy-rails3/public/index.html +241 -0
- data/spec/dummy-rails3/public/robots.txt +5 -0
- data/spec/dummy-rails3/rails3.2.Gemfile.lock +131 -0
- data/spec/dummy-rails3/script/rails +6 -0
- data/spec/dummy-rails3/vendor/assets/javascripts/.gitkeep +0 -0
- data/spec/dummy-rails3/vendor/assets/stylesheets/.gitkeep +0 -0
- data/spec/dummy-rails3/vendor/plugins/.gitkeep +0 -0
- data/spec/dummy-rails4/.gitignore +16 -0
- data/spec/dummy-rails4/Gemfile +47 -0
- data/spec/dummy-rails4/README.rdoc +28 -0
- data/spec/dummy-rails4/Rakefile +6 -0
- data/spec/dummy-rails4/app/assets/images/.keep +0 -0
- data/spec/dummy-rails4/app/assets/javascripts/application.js +16 -0
- data/spec/dummy-rails4/app/assets/stylesheets/application.css +13 -0
- data/spec/dummy-rails4/app/controllers/application_controller.rb +5 -0
- data/spec/dummy-rails4/app/controllers/concerns/.keep +0 -0
- data/spec/dummy-rails4/app/helpers/application_helper.rb +2 -0
- data/spec/dummy-rails4/app/mailers/.keep +0 -0
- data/spec/dummy-rails4/app/models/.keep +0 -0
- data/spec/dummy-rails4/app/models/concerns/.keep +0 -0
- data/spec/dummy-rails4/app/models/group.rb +10 -0
- data/spec/dummy-rails4/app/models/user.rb +3 -0
- data/spec/dummy-rails4/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy-rails4/bin/bundle +3 -0
- data/spec/dummy-rails4/bin/rails +4 -0
- data/spec/dummy-rails4/bin/rake +4 -0
- data/spec/dummy-rails4/config.ru +4 -0
- data/spec/dummy-rails4/config/application.rb +23 -0
- data/spec/dummy-rails4/config/boot.rb +4 -0
- data/spec/dummy-rails4/config/database.yml +25 -0
- data/spec/dummy-rails4/config/environment.rb +5 -0
- data/spec/dummy-rails4/config/environments/development.rb +29 -0
- data/spec/dummy-rails4/config/environments/production.rb +80 -0
- data/spec/dummy-rails4/config/environments/test.rb +36 -0
- data/spec/dummy-rails4/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy-rails4/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/dummy-rails4/config/initializers/inflections.rb +16 -0
- data/spec/dummy-rails4/config/initializers/mime_types.rb +5 -0
- data/spec/dummy-rails4/config/initializers/secret_token.rb +12 -0
- data/spec/dummy-rails4/config/initializers/session_store.rb +3 -0
- data/spec/dummy-rails4/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy-rails4/config/locales/en.yml +23 -0
- data/spec/dummy-rails4/config/routes.rb +57 -0
- data/spec/dummy-rails4/db/migrate/20131102131519_create_users.rb +9 -0
- data/spec/dummy-rails4/db/migrate/20131102131531_create_groups.rb +9 -0
- data/spec/dummy-rails4/db/migrate/20131103162013_create_links.neo4j_ancestry.rb +11 -0
- data/spec/dummy-rails4/db/schema.rb +35 -0
- data/spec/dummy-rails4/db/seeds.rb +7 -0
- data/spec/dummy-rails4/lib/assets/.keep +0 -0
- data/spec/dummy-rails4/lib/tasks/.keep +0 -0
- data/spec/dummy-rails4/log/.keep +0 -0
- data/spec/dummy-rails4/public/404.html +58 -0
- data/spec/dummy-rails4/public/422.html +58 -0
- data/spec/dummy-rails4/public/500.html +57 -0
- data/spec/dummy-rails4/public/favicon.ico +0 -0
- data/spec/dummy-rails4/public/robots.txt +5 -0
- data/spec/dummy-rails4/vendor/assets/javascripts/.keep +0 -0
- data/spec/dummy-rails4/vendor/assets/stylesheets/.keep +0 -0
- data/spec/models/neo4j_ancestry/active_record_additions_spec.rb +78 -0
- data/spec/models/neo4j_ancestry/link_spec.rb +12 -0
- data/spec/spec_helper.rb +26 -0
- data/spec/support/schema.rb +42 -0
- metadata +409 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 41f4f1d28904e2ce9f72234d37fa139a1d3145ba
|
4
|
+
data.tar.gz: 172c0d6e21aa0053312c9a2ccdbd9bd3ae205ba5
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 8ef1393a7263e2bf86610d6e7f37e8ce74c62a7c2bbcae3d3de58328346b065328bd61c5242605d1250c75115239fb23acb2dea3c53f49fa810198e9ba306f54
|
7
|
+
data.tar.gz: c30f176d2e86e34cce179ed68fa0783b6b3b62bdd79e4d2b41f24d09b26a0b33e550968d52e001ef0a284d6b7b946127ef6312301b8f2cdefa17eff30447cb5a
|
data/.gitignore
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/version_tmp
|
17
|
+
tmp
|
18
|
+
|
19
|
+
# neo4j database of the dummy app
|
20
|
+
spec/dummy-rails4/db/neo4j
|
21
|
+
spec/dummy-rails3/db/neo4j
|
22
|
+
spec/dummy-rails4/neo4j
|
23
|
+
spec/dummy-rails3/neo4j
|
data/.travis.yml
ADDED
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
data/Guardfile
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# A sample Guardfile
|
2
|
+
# More info at https://github.com/guard/guard#readme
|
3
|
+
|
4
|
+
guard :rspec, cli: "--color" do
|
5
|
+
watch(%r{^spec/.+_spec\.rb$})
|
6
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
7
|
+
watch('spec/spec_helper.rb') { "spec" }
|
8
|
+
|
9
|
+
# Rails example
|
10
|
+
watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
|
11
|
+
watch(%r{^app/(.*)(\.erb|\.haml|\.slim)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
|
12
|
+
watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
|
13
|
+
watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
|
14
|
+
watch('config/routes.rb') { "spec/routing" }
|
15
|
+
watch('app/controllers/application_controller.rb') { "spec/controllers" }
|
16
|
+
|
17
|
+
# Capybara features specs
|
18
|
+
watch(%r{^app/views/(.+)/.*\.(erb|haml|slim)$}) { |m| "spec/features/#{m[1]}_spec.rb" }
|
19
|
+
|
20
|
+
# Turnip features and steps
|
21
|
+
watch(%r{^spec/acceptance/(.+)\.feature$})
|
22
|
+
watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }
|
23
|
+
end
|
24
|
+
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Sebastian Fiedlschuster
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
# Neo4jAncestry
|
2
|
+
|
3
|
+
[![Build Status](https://travis-ci.org/fiedl/neo4j_ancestry.png?branch=master)](https://travis-ci.org/fiedl/neo4j_ancestry)
|
4
|
+
|
5
|
+
This ruby on rails gem makes it easy to store polymorphic structure information --- `parents`, `children`, `ancestors`, `descendants`, ... --- in a [neo4j graph database](http://www.neo4j.org) parallel to using ActiveRecord.
|
6
|
+
|
7
|
+
All relevant information is stored in your default ActiveRecord database, including the parent-child relationships. But, in addition, the structure information is also stored in a neo4j graph database in order to use its power of fast graph traversing queries.
|
8
|
+
|
9
|
+
## Usage
|
10
|
+
|
11
|
+
TODO: Write usage instructions here
|
12
|
+
|
13
|
+
|
14
|
+
## Installation
|
15
|
+
|
16
|
+
Add the gem to your application's `Gemfile`:
|
17
|
+
|
18
|
+
# Gemfile
|
19
|
+
# ...
|
20
|
+
gem 'neo4j_ancestry'
|
21
|
+
|
22
|
+
And then execute:
|
23
|
+
|
24
|
+
# bash
|
25
|
+
bundle install
|
26
|
+
|
27
|
+
Install the neo4j database `db` directory and start the deamon:
|
28
|
+
|
29
|
+
# bash
|
30
|
+
bundle exec rake neo4j:install neo4j:setup neo4j:start
|
31
|
+
|
32
|
+
Next, migrate the database in order to add the neccessary tables.
|
33
|
+
|
34
|
+
# bash
|
35
|
+
bundle exec rake neo4j_ancestry:install:migrations
|
36
|
+
bundle exec rake db:migrate
|
37
|
+
|
38
|
+
|
39
|
+
## Underlying Technology
|
40
|
+
|
41
|
+
* The [neo4j graph database](http://www.neo4j.org)
|
42
|
+
* The [neography gem](https://github.com/maxdemarzi/neography) is used as datbase interface.
|
43
|
+
* The [neoid gem](https://github.com/elado/neoid) is used for database abstraction in parallel to ActiveRecord.
|
44
|
+
|
45
|
+
## Contributing
|
46
|
+
|
47
|
+
1. Fork it
|
48
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
49
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
50
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
51
|
+
5. Create new Pull Request
|
52
|
+
|
53
|
+
### Running the Gem's Specs Locally
|
54
|
+
|
55
|
+
Symlink the `Gemfile` according to the Rails version you would like to use:
|
56
|
+
|
57
|
+
# bash
|
58
|
+
rm Gemfile Gemfile.lock
|
59
|
+
ln -s rails3.2.Gemfile Gemfile # for Rails 3
|
60
|
+
ln -s rails4.Gemfile Gemfile # for Rails 4 (default)
|
61
|
+
|
62
|
+
Next, install the dependencies and run the specs.
|
63
|
+
|
64
|
+
# bash
|
65
|
+
bundle install
|
66
|
+
bundle exec rake neo4j_ancestry:db:test:prepare
|
67
|
+
bundle exec rake
|
68
|
+
|
69
|
+
## Author, License
|
70
|
+
|
71
|
+
(c) 2013, Sebastian Fiedlschuster
|
72
|
+
|
73
|
+
Released under the [MIT License](./MIT-LICENSE).
|
data/Rakefile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
begin
|
2
|
+
require 'bundler/setup'
|
3
|
+
rescue LoadError
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
|
+
end
|
6
|
+
|
7
|
+
require "bundler/gem_tasks"
|
8
|
+
Bundler::GemHelper.install_tasks
|
9
|
+
|
10
|
+
load "lib/tasks/db_test_prepare.rake"
|
11
|
+
|
12
|
+
require 'rspec/core/rake_task'
|
13
|
+
RSpec::Core::RakeTask.new(:spec)
|
14
|
+
|
15
|
+
task default: :spec
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# This initializers estableshes the connection to the neo4j graph database.
|
2
|
+
# The settings for this connection are stored in
|
3
|
+
#
|
4
|
+
# # TODO
|
5
|
+
#
|
6
|
+
# For further information how this connection works, have a look at:
|
7
|
+
#
|
8
|
+
# https://github.com/elado/neoid#usage
|
9
|
+
#
|
10
|
+
|
11
|
+
if Rails.env.development?
|
12
|
+
neo4j_url = "http://localhost:7474"
|
13
|
+
elsif Rails.env.test?
|
14
|
+
neo4j_url = "http://localhost:7574"
|
15
|
+
elsif Rails.env.production?
|
16
|
+
raise 'TODO: read the neo4j server connection from config file.'
|
17
|
+
end
|
18
|
+
|
19
|
+
uri = URI.parse(neo4j_url)
|
20
|
+
|
21
|
+
$neo = Neography::Rest.new(uri.to_s)
|
22
|
+
|
23
|
+
Neography.configure do |c|
|
24
|
+
c.server = uri.host
|
25
|
+
c.port = uri.port
|
26
|
+
|
27
|
+
if uri.user && uri.password
|
28
|
+
c.authentication = 'basic'
|
29
|
+
c.username = uri.user
|
30
|
+
c.password = uri.password
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
Neoid.db = $neo
|
35
|
+
|
36
|
+
Neoid.configure do |c|
|
37
|
+
# should Neoid create sub-reference from the ref node (id#0) to every node-model? default: true
|
38
|
+
c.enable_subrefs = false
|
39
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
module Neo4jAncestry
|
2
|
+
module ActiveRecordAdditions
|
3
|
+
require 'neo4j_ancestry/railtie' if defined?(Rails)
|
4
|
+
|
5
|
+
# Example options:
|
6
|
+
# parent_class_names: %w(Group),
|
7
|
+
# child_class_names: %w(Group User)
|
8
|
+
#
|
9
|
+
def has_neo4j_ancestry(options)
|
10
|
+
|
11
|
+
link_class_name = 'Neo4jAncestry::Link'
|
12
|
+
|
13
|
+
# Links (direct relationships between objects) are stored
|
14
|
+
# via ActiveRecord in the mysql database. (The neo4j database contains only
|
15
|
+
# redundant information and is used for fast queries.)
|
16
|
+
#
|
17
|
+
has_many :links_as_parent, foreign_key: :parent_id, class_name: link_class_name
|
18
|
+
has_many :links_as_child, foreign_key: :child_id, class_name: link_class_name
|
19
|
+
|
20
|
+
parent_class_names = options[:parent_class_names] || []
|
21
|
+
child_class_names = options[:child_class_names] || []
|
22
|
+
|
23
|
+
# links_as_child for specific parent object classes and
|
24
|
+
# links_as_parent for specific child object classes, e.g.
|
25
|
+
# group.links_as_child_for_groups
|
26
|
+
# group.links_as_parent_for_groups
|
27
|
+
# group.links_as_parent_for_users
|
28
|
+
#
|
29
|
+
parent_class_names.each do |parent_class_name|
|
30
|
+
has_many_for_rails_3_and_4(
|
31
|
+
"links_as_child_for_#{parent_class_name.underscore.pluralize}".to_sym,
|
32
|
+
{ parent_type: parent_class_name },
|
33
|
+
{ as: :child, class_name: link_class_name } )
|
34
|
+
end
|
35
|
+
child_class_names.each do |child_class_name|
|
36
|
+
has_many_for_rails_3_and_4(
|
37
|
+
"links_as_parent_for_#{child_class_name.underscore.pluralize}".to_sym,
|
38
|
+
{ child_type: child_class_name },
|
39
|
+
{ as: :parent, class_name: link_class_name } )
|
40
|
+
end
|
41
|
+
|
42
|
+
# parent and child associations for specific object classes, e.g.
|
43
|
+
# group.parent_groups
|
44
|
+
# group.child_groups
|
45
|
+
# group.child_users
|
46
|
+
#
|
47
|
+
parent_class_names.each do |parent_class_name|
|
48
|
+
has_many(
|
49
|
+
"parent_#{parent_class_name.underscore.pluralize}".to_sym,
|
50
|
+
through: "links_as_child_for_#{parent_class_name.underscore.pluralize}".to_sym,
|
51
|
+
as: :structureable,
|
52
|
+
foreign_key: :parent_id, source: 'parent',
|
53
|
+
source_type: parent_class_name )
|
54
|
+
end
|
55
|
+
child_class_names.each do |child_class_name|
|
56
|
+
has_many(
|
57
|
+
"child_#{child_class_name.underscore.pluralize}".to_sym,
|
58
|
+
through: "links_as_parent_for_#{child_class_name.underscore.pluralize}".to_sym,
|
59
|
+
as: :structureable,
|
60
|
+
foreign_key: :child_id, source: 'child',
|
61
|
+
source_type: child_class_name )
|
62
|
+
end
|
63
|
+
|
64
|
+
# Use the neoid gem to have this object represented as node
|
65
|
+
# in the neo4j graph database.
|
66
|
+
#
|
67
|
+
include Neoid::Node
|
68
|
+
|
69
|
+
# Copy the name attribute to the neo4j nodes.
|
70
|
+
# Other attributes can be copied as well by using the 'attributes_to_copy_to_neo4j'.
|
71
|
+
#
|
72
|
+
attributes_to_copy_to_neo4j do |c|
|
73
|
+
c.field :name
|
74
|
+
end
|
75
|
+
|
76
|
+
# Include the instance methods for interaction with the neo4j graph.
|
77
|
+
#
|
78
|
+
include Neo4jAncestry::NodeInstanceMethods
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
# Attributes to copy over to the neo4j database.
|
83
|
+
# This is just a wrapper for the 'neoidable' method of the neoid gem.
|
84
|
+
# https://github.com/elado/neoid
|
85
|
+
#
|
86
|
+
# Example:
|
87
|
+
# attributes_to_copy_to_neo4j do |c|
|
88
|
+
# c.field :name
|
89
|
+
# c.field :name_length do
|
90
|
+
# self.name.length
|
91
|
+
# end
|
92
|
+
# end
|
93
|
+
#
|
94
|
+
def attributes_to_copy_to_neo4j(&block)
|
95
|
+
neoidable(&block)
|
96
|
+
end
|
97
|
+
|
98
|
+
# The has_many method changes from Rails 3 to Rails 4.
|
99
|
+
# Since this gem supports both rails versions, this method
|
100
|
+
# is a wrapper.
|
101
|
+
#
|
102
|
+
def has_many_for_rails_3_and_4(association_name, conditions_hash, options)
|
103
|
+
if Rails.version.start_with? "4"
|
104
|
+
has_many(association_name, -> { where conditions_hash }, options)
|
105
|
+
elsif Rails.version.start_with? "3"
|
106
|
+
has_many(association_name, options.merge({conditions: conditions_hash}))
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Neo4jAncestry
|
2
|
+
def self.table_name_prefix
|
3
|
+
'neo4j_ancestry_'
|
4
|
+
end
|
5
|
+
|
6
|
+
class Link < ActiveRecord::Base
|
7
|
+
|
8
|
+
# ActiveRecord database columns
|
9
|
+
#
|
10
|
+
# create_table :neo4j_ancestry_links do |t|
|
11
|
+
# t.integer :parent_id
|
12
|
+
# t.string :parent_type
|
13
|
+
# t.integer :child_id
|
14
|
+
# t.integer :child_type
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
|
18
|
+
belongs_to :parent, polymorphic: true
|
19
|
+
belongs_to :child, polymorphic: true
|
20
|
+
|
21
|
+
include Neoid::Relationship
|
22
|
+
|
23
|
+
neoidable do |c|
|
24
|
+
c.relationship start_node: :parent, end_node: :child, type: :is_parent_of
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
module Neo4jAncestry
|
2
|
+
module NodeInstanceMethods
|
3
|
+
|
4
|
+
# The neoid gem provides a neo_node method, which returns an object
|
5
|
+
# representing the node in the neo4j database that corresponds to this
|
6
|
+
# object.
|
7
|
+
#
|
8
|
+
# Overriding the neo_node method ensures that for STI the same neo_node
|
9
|
+
# is returned for the same object regardless of the subclass.
|
10
|
+
#
|
11
|
+
# That means: group.neo_node == group.becomes(SpecialGroup).neo_node
|
12
|
+
#
|
13
|
+
def neo_node
|
14
|
+
super || self.becomes(self.class.base_class).neo_node
|
15
|
+
end
|
16
|
+
|
17
|
+
# The unique id of the neo4j node that corresponds to this object.
|
18
|
+
#
|
19
|
+
def neo_id
|
20
|
+
neo_node.try(:neo_id)
|
21
|
+
end
|
22
|
+
|
23
|
+
# Methods to query the neo4j database for parents, children,
|
24
|
+
# ancestors, descendants and siblings.
|
25
|
+
def parents
|
26
|
+
find_related_nodes_via_cypher("
|
27
|
+
match (parents)-[:is_parent_of]->(self)
|
28
|
+
return parents
|
29
|
+
")
|
30
|
+
end
|
31
|
+
def children
|
32
|
+
find_related_nodes_via_cypher("
|
33
|
+
match (self)-[:is_parent_of]->(children)
|
34
|
+
return children
|
35
|
+
")
|
36
|
+
end
|
37
|
+
def ancestors
|
38
|
+
find_related_nodes_via_cypher("
|
39
|
+
match (ancestors)-[:is_parent_of*1..100]->(self)
|
40
|
+
return ancestors
|
41
|
+
").uniq
|
42
|
+
end
|
43
|
+
def descendants
|
44
|
+
find_related_nodes_via_cypher("
|
45
|
+
match (self)-[:is_parent_of*1..100]->(descendants)
|
46
|
+
return descendants
|
47
|
+
").uniq
|
48
|
+
end
|
49
|
+
def siblings
|
50
|
+
find_related_nodes_via_cypher("
|
51
|
+
match (self)<-[:is_parent_of]-(parent)-[:is_parent_of]->(siblings)
|
52
|
+
return siblings
|
53
|
+
").uniq
|
54
|
+
end
|
55
|
+
|
56
|
+
# This method returns all ActiveRecord objects found by a cypher
|
57
|
+
# neo4j query defined through the given query_string.
|
58
|
+
#
|
59
|
+
# Within the query_string, no START expression is needed,
|
60
|
+
# because the start node is given by the neo_node of this
|
61
|
+
# structureable object. It is referred to just by 'self'.
|
62
|
+
#
|
63
|
+
# Example:
|
64
|
+
# group.find_related_nodes_via_cypher("
|
65
|
+
# match (self)-[:is_parent_of]->(children)
|
66
|
+
# return children
|
67
|
+
# ") # => [child_group1, child_group2, ...]
|
68
|
+
#
|
69
|
+
def find_related_nodes_via_cypher(query_string)
|
70
|
+
query_string = "
|
71
|
+
start self=node(#{neo_id})
|
72
|
+
#{query_string}
|
73
|
+
"
|
74
|
+
cypher_results_to_objects(
|
75
|
+
Neoid.db.execute_query(query_string)
|
76
|
+
)
|
77
|
+
end
|
78
|
+
|
79
|
+
# This method returns the ActiveRecord objects that match the
|
80
|
+
# given cypher query result.
|
81
|
+
#
|
82
|
+
# For an example, have a look at the method
|
83
|
+
# find_related_nodes_via_cypher.
|
84
|
+
#
|
85
|
+
def cypher_results_to_objects(cypher_results)
|
86
|
+
cypher_results["data"].collect do |result|
|
87
|
+
result.first["data"]["ar_type"].constantize.find(result.first["data"]["ar_id"])
|
88
|
+
end
|
89
|
+
end
|
90
|
+
private :cypher_results_to_objects
|
91
|
+
|
92
|
+
end
|
93
|
+
end
|