diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 0e8cb13e..991677ed 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1,6 +1,6 @@ # This configuration was generated by # `rubocop --auto-gen-config` -# on 2015-09-07 09:42:54 +1200 using RuboCop version 0.34.0. +# on 2016-11-21 16:05:50 -0800 using RuboCop version 0.34.2. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new @@ -31,29 +31,37 @@ Lint/UnusedMethodArgument: - 'lib/neo4j/session.rb' - 'lib/neo4j/transaction.rb' -# Offense count: 15 +# Offense count: 20 Metrics/AbcSize: - Max: 17 + Max: 23 -# Offense count: 8 +# Offense count: 9 # Configuration parameters: CountComments. Metrics/ClassLength: Max: 190 -# Offense count: 419 +# Offense count: 1 +Metrics/CyclomaticComplexity: + Max: 8 + +# Offense count: 517 # Configuration parameters: AllowURI, URISchemes. Metrics/LineLength: Max: 180 -# Offense count: 17 +# Offense count: 21 # Configuration parameters: CountComments. Metrics/MethodLength: Max: 14 -# Offense count: 3 +# Offense count: 1 # Configuration parameters: CountComments. Metrics/ModuleLength: - Max: 174 + Max: 133 + +# Offense count: 1 +Metrics/PerceivedComplexity: + Max: 8 # Offense count: 8 Style/AccessorMethodName: @@ -71,15 +79,13 @@ Style/ClassVars: Exclude: - 'lib/neo4j/session.rb' -# Offense count: 67 +# Offense count: 81 +# Configuration parameters: Exclude. Style/Documentation: Enabled: false -# Offense count: 4 +# Offense count: 1 # Cop supports --auto-correct. Style/RescueEnsureAlignment: Exclude: - - 'lib/neo4j-embedded/label.rb' - - 'spec/shared_examples/label.rb' - 'spec/shared_examples/node_with_tx.rb' - diff --git a/Gemfile b/Gemfile index 9eb142b3..f9df56b5 100644 --- a/Gemfile +++ b/Gemfile @@ -18,10 +18,18 @@ group 'development' do end group 'test' do + gem 'term-ansicolor', '~> 1.3.0' if RUBY_VERSION.to_f < 2.0 gem 'coveralls', require: false gem 'simplecov-html', require: false gem 'tins', '< 1.7' if RUBY_VERSION.to_f < 2.0 gem 'rspec', '~> 3.0' gem 'rspec-its' gem 'dotenv' + gem 'activesupport', '>= 4.0' unless RUBY_VERSION.to_f < 2.2 + + gem 'em-http-request', '>= 1.1', require: 'em-http', platforms: :ruby + gem 'em-synchrony', '>= 1.0.3', require: ['em-synchrony', 'em-synchrony/em-http'], platforms: :ruby + gem 'excon', '>= 0.27.4' + gem 'patron', '>= 0.4.2', platforms: :ruby + gem 'typhoeus', '>= 0.3.3' end diff --git a/README.md b/README.md index 8e603c90..d39437a8 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,31 @@ A simple Ruby wrapper around the Neo4j graph database that works with the server and embedded Neo4j API. This gem can be used both from JRuby and normal MRI. It can be used standalone without the neo4j gem. +## Basic usage + +### Executing Cypher queries + +To make a basic connection to Neo4j to execute Cypher queries, first choose an adaptor. Adaptors for HTTP and Embedded mode (jRuby only) are available. You can create an adaptor like: + + http_adaptor = Neo4j::Core::CypherSession::Adaptors::HTTP.new('http://neo4j:pass@localhost:7474') + + # or + + neo4j_adaptor = Neo4j::Core::CypherSession::Adaptors::Embedded.new('/file/path/to/graph.db') + +The HTTP Adaptor can also take `:faraday_options`. Currently, only :adapter is supported (defaulting to `:net_http_persistent`): + + http_adaptor = Neo4j::Core::CypherSession::Adaptors::HTTP.new('http://neo4j:pass@localhost:7474', faraday_options: { adapter: :typhoeus }) + +Note you **must** install any required http adaptor gems yourself as per [Faraday](https://github.com/lostisland/faraday). Ex for `:typhoeus`, add to your Gemfile: + + gem 'typhoeus' + +Once you have an adaptor you can create a session like so: + + neo4j_session = Neo4j::Core::CypherSession.new(http_adaptor) + + ## Documentation ### 3.0+ Documentation: diff --git a/lib/neo4j-server/cypher_session.rb b/lib/neo4j-server/cypher_session.rb index 9b3bc834..98f58e27 100644 --- a/lib/neo4j-server/cypher_session.rb +++ b/lib/neo4j-server/cypher_session.rb @@ -23,6 +23,10 @@ def initialize(data_url, connection) # @return [Faraday] # @see https://github.com/lostisland/faraday def self.create_connection(params, url = nil) + faraday_options = params.delete(:faraday_options) || params.delete('faraday_options') || {} + adapter = (faraday_options[:adapter] || faraday_options['adapter'] || :net_http_persistent).to_sym + require 'typhoeus/adapters/faraday' if adapter == :typhoeus + init_params = params[:initialize] && params.delete(:initialize) conn = Faraday.new(url, init_params) do |b| b.request :basic_auth, params[:basic_auth][:username], params[:basic_auth][:password] if params[:basic_auth] @@ -31,8 +35,7 @@ def self.create_connection(params, url = nil) b.response :multi_json, symbolize_keys: true, content_type: 'application/json' # b.use Faraday::Response::RaiseError - b.use Faraday::Adapter::NetHttpPersistent - # b.adapter Faraday.default_adapter + b.adapter adapter end conn.headers = {'Content-Type' => 'application/json', 'User-Agent' => ::Neo4j::Session.user_agent_string} conn diff --git a/lib/neo4j/core/cypher_session/adaptors/http.rb b/lib/neo4j/core/cypher_session/adaptors/http.rb index 31b1d454..1ba89653 100644 --- a/lib/neo4j/core/cypher_session/adaptors/http.rb +++ b/lib/neo4j/core/cypher_session/adaptors/http.rb @@ -10,10 +10,11 @@ class HTTP < Base # @transaction_state valid states # nil, :open_requested, :open, :close_requested - def initialize(url, _options = {}) + def initialize(url, options = {}) @url = url @url_components = url_components!(url) @transaction_state = nil + @faraday_options = options[:faraday_options] || options['faraday_options'] || {} end def connect @@ -136,12 +137,15 @@ def url_base end def connection + adapter = (@faraday_options[:adapter] || @faraday_options['adapter'] || :net_http_persistent).to_sym + require 'typhoeus/adapters/faraday' if adapter == :typhoeus + Faraday.new(@url) do |c| c.request :basic_auth, user, password c.request :multi_json c.response :multi_json, symbolize_keys: true, content_type: 'application/json' - c.use Faraday::Adapter::NetHttpPersistent + c.adapter adapter c.headers['Content-Type'] = 'application/json' c.headers['User-Agent'] = user_agent_string diff --git a/spec/neo4j-server/e2e/cypher_session_spec.rb b/spec/neo4j-server/e2e/cypher_session_spec.rb index b1a6222d..35f029e2 100644 --- a/spec/neo4j-server/e2e/cypher_session_spec.rb +++ b/spec/neo4j-server/e2e/cypher_session_spec.rb @@ -1,4 +1,5 @@ require 'spec_helper' +require './spec/neo4j-server/shared_examples/cypher_session' module Neo4j module Server @@ -37,6 +38,29 @@ def open_session expect(connection.port).to eq 7474 expect(connection.host).to eq 'localhost' end + + describe 'faraday_options' do + describe 'the http_adaptor options' do + it 'will pass through a symbol key' do + faraday_hash = {farday_options: {adapter: :something}} + expect(Neo4j::Server::CypherSession).to receive(:open).with(anything, hash_including(faraday_hash)) + create_server_session(faraday_hash) + end + + it 'will pass through a string key' do + faraday_hash = {farday_options: {adapter: :something}} + expect(Neo4j::Server::CypherSession).to receive(:open).with(anything, hash_including(faraday_hash)) + create_server_session(faraday_hash) + end + + with_each_faraday_adaptor do |adapter_name| + describe "when set to :#{adapter_name}" do + let(:adapter) { adapter_name } + it_behaves_like 'Neo4j::Server::CypherSession' + end + end + end + end end diff --git a/spec/neo4j-server/shared_examples/cypher_session.rb b/spec/neo4j-server/shared_examples/cypher_session.rb new file mode 100644 index 00000000..9abb6df8 --- /dev/null +++ b/spec/neo4j-server/shared_examples/cypher_session.rb @@ -0,0 +1,6 @@ +# Requires that an `http_adaptor` let variable exist with the Faraday adaptor name +RSpec.shared_examples 'Neo4j::Server::CypherSession' do + it 'should be able to connect and query' do + create_server_session(faraday_options: {adapter: adapter}).query.create('(n)').return('ID(n) AS id').first[:id] + end +end diff --git a/spec/neo4j/core/cypher_session/adaptors/http_spec.rb b/spec/neo4j/core/cypher_session/adaptors/http_spec.rb index b81cd161..647a6dd8 100644 --- a/spec/neo4j/core/cypher_session/adaptors/http_spec.rb +++ b/spec/neo4j/core/cypher_session/adaptors/http_spec.rb @@ -1,6 +1,7 @@ require 'spec_helper' require 'neo4j/core/cypher_session/adaptors/http' require './spec/neo4j/core/shared_examples/adaptor' +require './spec/neo4j/core/shared_examples/http' describe Neo4j::Core::CypherSession::Adaptors::HTTP, new_cypher_session: true do before(:all) { setup_http_request_subscription } @@ -16,10 +17,33 @@ expect { adaptor_class.new('https://localhost:7474/') }.not_to raise_error expect { adaptor_class.new('https://foo:bar@localhost:7474') }.not_to raise_error end + + describe 'the http_adaptor option' do + it 'uses net_http_persistent by default' do + expect_any_instance_of(Faraday::Connection).to receive(:adapter).with(:net_http_persistent) + adaptor_class.new(server_url).connect + end + + it 'will pass through a symbol key' do + expect_any_instance_of(Faraday::Connection).to receive(:adapter).with(:something) + adaptor_class.new(server_url, faraday_options: {adapter: :something}).connect + end + + it 'will pass through a string key' do + expect_any_instance_of(Faraday::Connection).to receive(:adapter).with(:something) + adaptor_class.new(server_url, faraday_options: {'adapter' => :something}).connect + end + + with_each_faraday_adaptor do |adapter_name| + describe "the :#{adapter_name} adaptor" do + let(:adapter) { adapter_name } + it_behaves_like 'Neo4j::Core::CypherSession::Adaptors::HTTP' + end + end + end end - let(:url) { ENV['NEO4J_URL'] } - let(:adaptor) { adaptor_class.new(url) } + let(:adaptor) { adaptor_class.new(server_url) } before { adaptor.connect } diff --git a/spec/neo4j/core/shared_examples/http.rb b/spec/neo4j/core/shared_examples/http.rb new file mode 100644 index 00000000..96cebf90 --- /dev/null +++ b/spec/neo4j/core/shared_examples/http.rb @@ -0,0 +1,6 @@ +# Requires that an `http_adaptor` let variable exist with the Faraday adaptor name +RSpec.shared_examples 'Neo4j::Core::CypherSession::Adaptors::HTTP' do + it 'should connect properly' do + Neo4j::Core::CypherSession::Adaptors::HTTP.new(server_url, faraday_options: {adapter: adapter}).connect.get('/') + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 0e081f9e..9493f670 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -154,3 +154,11 @@ def setup_http_request_subscription end } end + +def with_each_faraday_adaptor + adaptors = Faraday::Adapter.instance_variable_get(:@registered_middleware).keys - [:test, :rack] + adaptors -= [:patron, :em_synchrony, :em_http] if RUBY_PLATFORM == 'java' + adaptors.each do |adaptor_name| + yield adaptor_name + end +end