neo4j_ancestry 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +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
|
+
[](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
|