From 6288ee1b791bb6ae5ccb9439870d46e71feac5a3 Mon Sep 17 00:00:00 2001 From: Dieter Pisarewski Date: Mon, 1 Dec 2014 17:19:27 +0100 Subject: [PATCH] Neo4j support --- Gemfile | 1 + Gemfile.lock | 42 ++++++++++++++ README.markdown | 8 +++ .../features/step_definitions/neo4j_steps.rb | 31 ++++++++++ examples/features/support/env.rb | 3 + examples/lib/neo4j_models.rb | 17 ++++++ features/cleaning.feature | 3 + features/cleaning_default_strategy.feature | 1 + features/cleaning_multiple_dbs.feature | 3 + features/cleaning_multiple_orms.feature | 4 ++ .../database_cleaner_steps.rb | 2 +- lib/database_cleaner/base.rb | 4 ++ lib/database_cleaner/configuration.rb | 2 + lib/database_cleaner/neo4j/base.rb | 58 +++++++++++++++++++ lib/database_cleaner/neo4j/deletion.rb | 16 +++++ lib/database_cleaner/neo4j/transaction.rb | 34 +++++++++++ lib/database_cleaner/neo4j/truncation.rb | 9 +++ 17 files changed, 237 insertions(+), 1 deletion(-) create mode 100644 examples/features/step_definitions/neo4j_steps.rb create mode 100644 examples/lib/neo4j_models.rb create mode 100644 lib/database_cleaner/neo4j/base.rb create mode 100644 lib/database_cleaner/neo4j/deletion.rb create mode 100644 lib/database_cleaner/neo4j/transaction.rb create mode 100644 lib/database_cleaner/neo4j/truncation.rb diff --git a/Gemfile b/Gemfile index ae0c187..b42dffe 100755 --- a/Gemfile +++ b/Gemfile @@ -24,6 +24,7 @@ group :development, :test do gem "mongo_mapper" gem "moped" + gem "neo4j-core" gem "couch_potato" gem "sequel", "~>3.21.0" diff --git a/Gemfile.lock b/Gemfile.lock index a663958..52f5e5e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -29,9 +29,13 @@ GEM arel (1.0.1) activesupport (~> 3.0.0) bcrypt (3.1.7) + bcrypt (3.1.7-java) bcrypt-ruby (3.1.5) bcrypt (>= 3.1.3) + bcrypt-ruby (3.1.5-java) + bcrypt (>= 3.1.3) bson (1.11.1) + bson (1.11.1-java) bson_ext (1.11.1) bson (~> 1.11.1) builder (2.1.2) @@ -190,11 +194,18 @@ GEM data_objects (= 0.10.14) erubis (2.6.6) abstract (>= 1.0.0) + faraday (0.9.0) + multipart-post (>= 1.2, < 3) + faraday_middleware (0.9.1) + faraday (>= 0.7.4, < 0.10) fastercsv (1.5.5) ffi (1.9.6) + ffi (1.9.6-java) formatador (0.2.5) gherkin (2.11.6) json (>= 1.7.6) + gherkin (2.11.6-java) + json (>= 1.7.6) git (1.2.8) guard (1.8.3) formatador (>= 0.2.4) @@ -205,6 +216,10 @@ GEM guard-rspec (2.5.4) guard (>= 1.1) rspec (~> 2.11) + httparty (0.13.3) + json (~> 1.8) + multi_xml (>= 0.5.2) + httpclient (2.5.3.3) i18n (0.4.2) jeweler (1.8.4) bundler (~> 1.0) @@ -212,6 +227,7 @@ GEM rake rdoc json (1.8.1) + json (1.8.1-java) json_pure (1.8.1) linecache (0.46) rbx-require-relative (> 0.0.4) @@ -239,12 +255,28 @@ GEM mongoid (~> 2.0) moped (1.5.2) multi_json (1.2.0) + multi_xml (0.5.5) + multipart-post (2.0.0) mysql (2.8.1) mysql2 (0.3.16) + neo4j-community (2.1.5) + neo4j-core (3.0.8) + activesupport + faraday (~> 0.9.0) + faraday_middleware (~> 0.9.1) + httparty + httpclient + json + neo4j-community (~> 2.1.1) + net-http-persistent + os + zip nest (1.1.2) redis + net-http-persistent (2.9.4) ohm (0.1.5) nest (~> 1.0) + os (0.9.6) pg (0.17.1) plucky (0.5.2) mongo (~> 1.5) @@ -252,6 +284,11 @@ GEM coderay (~> 1.1.0) method_source (~> 0.8.1) slop (~> 3.4) + pry (0.10.1-java) + coderay (~> 1.1.0) + method_source (~> 0.8.1) + slop (~> 3.4) + spoon (~> 0.0) rack (1.2.8) rack-mount (0.6.14) rack (>= 1.0.0) @@ -305,6 +342,8 @@ GEM archive-tar-minitar (>= 0.5.2) sequel (3.21.0) slop (3.6.0) + spoon (0.0.4) + ffi sqlite3 (1.3.9) sqlite3-ruby (1.3.3) sqlite3 (>= 1.3.3) @@ -312,8 +351,10 @@ GEM thor (0.14.6) tzinfo (0.3.41) uuidtools (2.1.5) + zip (2.0.2) PLATFORMS + java ruby DEPENDENCIES @@ -336,6 +377,7 @@ DEPENDENCIES moped mysql (~> 2.8.1) mysql2 + neo4j-core ohm (~> 0.1.3) pg rake diff --git a/README.markdown b/README.markdown index 1257161..c957a29 100644 --- a/README.markdown +++ b/README.markdown @@ -67,9 +67,17 @@ Here is an overview of the strategies supported for each library: No No + + Neo4j + Yes + Yes* + Yes* + +* Truncation and Deletion strategies for Neo4j will just delete all nodes and relationships from the database. + diff --git a/examples/features/step_definitions/neo4j_steps.rb b/examples/features/step_definitions/neo4j_steps.rb new file mode 100644 index 0000000..bbf8bd2 --- /dev/null +++ b/examples/features/step_definitions/neo4j_steps.rb @@ -0,0 +1,31 @@ +Given /^I have setup database cleaner to clean multiple databases using neo4j$/ do + #DatabaseCleaner + # require "#{File.dirname(__FILE__)}/../../../lib/neo4j_models" + # + # DatabaseCleaner[:neo4j, :connection => {:type => :server_db, :path => 'http://localhost:7475'} ] + # DatabaseCleaner[:neo4j, :connection => {:type => :server_db, :path => 'http://localhost:7476'} ] +end + +When /^I create a widget using neo4j$/ do + Neo4jWidget.create! +end + +Then /^I should see ([\d]+) widget using neo4j$/ do |widget_count| + Neo4jWidget.count.should == widget_count.to_i +end + +When /^I create a widget in one db using neo4j$/ do + Neo4jWidgetUsingDatabaseOne.create! +end + +When /^I create a widget in another db using neo4j$/ do + Neo4jWidgetUsingDatabaseTwo.create! +end + +Then /^I should see ([\d]+) widget in one db using neo4j$/ do |widget_count| + Neo4jWidgetUsingDatabaseOne.count.should == widget_count.to_i +end + +Then /^I should see ([\d]+) widget in another db using neo4j$/ do |widget_count| + Neo4jWidgetUsingDatabaseTwo.count.should == widget_count.to_i +end diff --git a/examples/features/support/env.rb b/examples/features/support/env.rb index fad0cf1..b5986db 100644 --- a/examples/features/support/env.rb +++ b/examples/features/support/env.rb @@ -47,6 +47,9 @@ if orm && strategy when :active_record DatabaseCleaner[:active_record, {:model => ActiveRecordWidgetUsingDatabaseOne} ].strategy = strategy.to_sym DatabaseCleaner[:active_record, {:model => ActiveRecordWidgetUsingDatabaseTwo} ].strategy = strategy.to_sym + when :neo4j + DatabaseCleaner[:neo4j, {:connection => {:type => :server_db, :path => 'http://localhost:7475/'}} ].strategy = strategy.to_sym + DatabaseCleaner[:neo4j, {:connection => {:type => :server_db, :path => 'http://localhost:7476/'}} ].strategy = strategy.to_sym else DatabaseCleaner[ orm_sym, {:connection => :one} ].strategy = strategy.to_sym DatabaseCleaner[ orm_sym, {:connection => :two} ].strategy = strategy.to_sym diff --git a/examples/lib/neo4j_models.rb b/examples/lib/neo4j_models.rb new file mode 100644 index 0000000..496017d --- /dev/null +++ b/examples/lib/neo4j_models.rb @@ -0,0 +1,17 @@ +require 'neo4j-core' + +class Neo4jWidget < Neo4j::Node + def self.create!(*args) + create(*args) + end + + def self.count + Neo4j::Session.query.pluck('count(*) AS result').first + end +end + +class Neo4jWidgetUsingDatabaseOne < Neo4jWidget +end + +class Neo4jWidgetUsingDatabaseTwo < Neo4jWidget +end \ No newline at end of file diff --git a/features/cleaning.feature b/features/cleaning.feature index da1a347..a3613d9 100644 --- a/features/cleaning.feature +++ b/features/cleaning.feature @@ -22,3 +22,6 @@ Feature: database cleaning | CouchPotato | truncation | | Redis | truncation | | Ohm | truncation | + | Neo4j | deletion | + | Neo4j | truncation | + | Neo4j | transaction | diff --git a/features/cleaning_default_strategy.feature b/features/cleaning_default_strategy.feature index cb565ab..7f77c4f 100644 --- a/features/cleaning_default_strategy.feature +++ b/features/cleaning_default_strategy.feature @@ -19,3 +19,4 @@ Feature: database cleaning | CouchPotato | | Redis | | Ohm | + | Neo4j | diff --git a/features/cleaning_multiple_dbs.feature b/features/cleaning_multiple_dbs.feature index a426b5c..992f3d2 100644 --- a/features/cleaning_multiple_dbs.feature +++ b/features/cleaning_multiple_dbs.feature @@ -18,3 +18,6 @@ Feature: multiple database cleaning | MongoMapper | truncation | | DataMapper | transaction | | ActiveRecord | transaction | + | Neo4j | deletion | + | Neo4j | truncation | + | Neo4j | transaction | diff --git a/features/cleaning_multiple_orms.feature b/features/cleaning_multiple_orms.feature index 5368e50..91f433e 100644 --- a/features/cleaning_multiple_orms.feature +++ b/features/cleaning_multiple_orms.feature @@ -46,3 +46,7 @@ Feature: database cleaning using multiple ORMs | Redis | Mongoid | | Redis | CouchPotato | | Redis | Ohm | + | Neo4j | ActiveRecord | + | Neo4j | Redis | + | Neo4j | Ohm | + | Neo4j | MongoMapper | diff --git a/features/step_definitions/database_cleaner_steps.rb b/features/step_definitions/database_cleaner_steps.rb index 4a663d6..f561079 100644 --- a/features/step_definitions/database_cleaner_steps.rb +++ b/features/step_definitions/database_cleaner_steps.rb @@ -1,4 +1,4 @@ -orms_pattern = /(ActiveRecord|DataMapper|MongoMapper|Mongoid|CouchPotato|Redis|Ohm)/ +orms_pattern = /(ActiveRecord|DataMapper|MongoMapper|Mongoid|CouchPotato|Redis|Ohm|Neo4j)/ Given /^I am using #{orms_pattern}$/ do |orm| @feature_runner = FeatureRunner.new diff --git a/lib/database_cleaner/base.rb b/lib/database_cleaner/base.rb index 7d583f8..1fababc 100644 --- a/lib/database_cleaner/base.rb +++ b/lib/database_cleaner/base.rb @@ -120,6 +120,8 @@ module DatabaseCleaner :ohm elsif defined? ::Redis :redis + elsif defined? ::Neo4j + :neo4j end end @@ -153,6 +155,8 @@ module DatabaseCleaner self.strategy = :transaction when :mongo_mapper, :mongoid, :couch_potato, :moped, :ohm, :redis self.strategy = :truncation + when :neo4j + self.strategy = :transaction end end end diff --git a/lib/database_cleaner/configuration.rb b/lib/database_cleaner/configuration.rb index 9b626f1..6fb1e06 100644 --- a/lib/database_cleaner/configuration.rb +++ b/lib/database_cleaner/configuration.rb @@ -123,6 +123,8 @@ module DatabaseCleaner DatabaseCleaner::Ohm when :redis DatabaseCleaner::Redis + when :neo4j + DatabaseCleaner::Neo4j end end end diff --git a/lib/database_cleaner/neo4j/base.rb b/lib/database_cleaner/neo4j/base.rb new file mode 100644 index 0000000..e2db2f3 --- /dev/null +++ b/lib/database_cleaner/neo4j/base.rb @@ -0,0 +1,58 @@ +require 'database_cleaner/generic/base' +module DatabaseCleaner + module Neo4j + def self.available_strategies + %w[transaction truncation deletion] + end + + module Base + include ::DatabaseCleaner::Generic::Base + + def db=(desired_db) + @db = desired_db == :default ? nil : desired_db + end + + def db + @db ||= nil + end + + def start + if db_type == :embedded_db and not session.running? + session.start + else + session + end + end + + def database + db && default_db.merge(db) || default_db + end + + private + + def default_db + {type: default_db_type, path: default_db_path} + end + + def default_db_type + :server_db + end + + def default_db_path(type = default_db_type) + type == :server_db ? 'http://localhost:7475/' : './db/test' + end + + def db_type + database[:type] + end + + def db_path + database[:path] + end + + def session + @session ||= ::Neo4j::Session.open(db_type, db_path) + end + end + end +end diff --git a/lib/database_cleaner/neo4j/deletion.rb b/lib/database_cleaner/neo4j/deletion.rb new file mode 100644 index 0000000..c6166ef --- /dev/null +++ b/lib/database_cleaner/neo4j/deletion.rb @@ -0,0 +1,16 @@ +require 'database_cleaner/neo4j/base' +require 'neo4j-core' + +module DatabaseCleaner + module Neo4j + class Deletion + include ::DatabaseCleaner::Neo4j::Base + + def clean + ::Neo4j::Transaction.run do + session._query('MATCH (n) OPTIONAL MATCH (n)-[r]-() DELETE n,r') + end + end + end + end +end diff --git a/lib/database_cleaner/neo4j/transaction.rb b/lib/database_cleaner/neo4j/transaction.rb new file mode 100644 index 0000000..32f78af --- /dev/null +++ b/lib/database_cleaner/neo4j/transaction.rb @@ -0,0 +1,34 @@ +require 'database_cleaner/neo4j/base' +require 'database_cleaner/generic/transaction' +require 'neo4j-core' + +module DatabaseCleaner + module Neo4j + class Transaction + include ::DatabaseCleaner::Generic::Transaction + include ::DatabaseCleaner::Neo4j::Base + + attr_accessor :tx + + def start + super + rollback + self.tx = ::Neo4j::Transaction.new + end + + def clean + rollback + end + + + private + + def rollback + return unless tx + tx.failure + tx.close + self.tx = nil + end + end + end +end diff --git a/lib/database_cleaner/neo4j/truncation.rb b/lib/database_cleaner/neo4j/truncation.rb new file mode 100644 index 0000000..6d92e1c --- /dev/null +++ b/lib/database_cleaner/neo4j/truncation.rb @@ -0,0 +1,9 @@ +require 'database_cleaner/neo4j/base' +require 'database_cleaner/neo4j/deletion' + +module DatabaseCleaner + module Neo4j + class Truncation < DatabaseCleaner::Neo4j::Deletion + end + end +end