Skip to content

Commit

Permalink
starting on relationships
Browse files Browse the repository at this point in the history
  • Loading branch information
maxdemarzi committed Nov 15, 2010
1 parent 0eff227 commit 0b5b547
Show file tree
Hide file tree
Showing 9 changed files with 328 additions and 4 deletions.
19 changes: 19 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
Copyright (c) 2010 Max De Marzi

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
44 changes: 44 additions & 0 deletions README.rdoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
== Welcome to Neography

Neography is a thin ruby wrapper to the Neo4j Rest API, for more information:
* {Getting Started with REST for Neo4j}[http://wiki.neo4j.org/content/Getting_Started_REST]
* {Neo4j Rest API Reference}[http://components.neo4j.org/neo4j-rest/]


=== Installation

gem install 'neography'
require 'neography'


==== Configuration

Neography::Config.use do |config|
config[:protocol] = 'http://'
config[:server] = 'localhost'
config[:port] = '9999'
end

==== Rails

Just add gem 'neography' to your Gemfile and run bundle install

Use the defaults (shown above) or create neography.rb in your config/initializers directory.

=== Documentation

Neography::Node.new # Create an empty node
Neography::Node.new(:age => 31, :name => "Max") # Create a node with some properties
Neography::Node.load(id) # Get a node and its properties
Neography::Node.set_properties(3, {:age => 31, :name => "Max"} ) # Deletes any existing properties with the passed hash
Neography::Node.properties(3) # Returns a hash of a node's properties or nil
Neography::Node.remove_property(3, :age) # Deletes the existing property
Neography::Node.del(3) # Deletes the node


=== License
* Neography - MIT, see the LICENSE file http://github.com/maxdemarzi/neography/tree/master/LICENSE.
* Lucene - Apache, see http://lucene.apache.org/java/docs/features.html
* Neo4j - Dual free software/commercial license, see http://neo4j.org/


3 changes: 2 additions & 1 deletion lib/neography.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,9 @@ def evaluate_response(response)
#Net::HTTP.http_logger_options = {:verbose => true}
#Net::HTTP.http_logger_options = {:body => true}

require 'neography/config'
require 'neography/neo'
require 'neography/node'

require 'neography/relationship'

find_and_require_user_defined_code
152 changes: 152 additions & 0 deletions lib/neography/config.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
module Neography

# == Keeps configuration for neography
#
# The most important configuration options are <tt>Neograophy::Config[:server]</tt> and <tt>Neograophy::Config[:port]</tt> which are
# used to locate where the neo4j database and is stored on the network.
# If these options are not supplied then the default of localhost:9999 will be used.
#
# ==== Default Configurations
# <tt>:protocol</tt>:: default <tt>http://</tt> protocol to use (can be https://)
# <tt>:server</tt>:: default <tt>localhost</tt> where the database is stored on the network
# <tt>:port</tt>:: default <tt>9999</tt> what port is listening
#
class Config
# This code is copied from merb-core/config.rb.
class << self
# Returns the hash of default config values for neography
#
# ==== Returns
# Hash:: The defaults for the config.
def defaults
@defaults ||= {
:protocol => 'http://',
:server => 'localhost',
:port => '9999'
}
end


# Yields the configuration.
#
# ==== Block parameters
# c :: The configuration parameters, a hash.
#
# ==== Examples
# Neography::Config.use do |config|
# config[:server] = '192.168.1.13'
# end
#
# ==== Returns
# nil
def use
@configuration ||= {}
yield @configuration
nil
end


# Set the value of a config entry.
#
# ==== Parameters
# key :: The key to set the parameter for.
# val :: The value of the parameter.
#
def []=(key, val)
(@configuration ||= setup)[key] = val
end


# Gets the the value of a config entry
#
# ==== Parameters
# key:: The key of the config entry value we want
#
def [](key)
(@configuration ||= setup)[key]
end


# Remove the value of a config entry.
#
# ==== Parameters
# key<Object>:: The key of the parameter to delete.
#
# ==== Returns
# The value of the removed entry.
#
def delete(key)
@configuration.delete(key)
end


# Remove all configuration. This can be useful for testing purpose.
#
#
# ==== Returns
# nil
#
def delete_all
@configuration = nil
end


# Retrieve the value of a config entry, returning the provided default if the key is not present
#
# ==== Parameters
# key:: The key to retrieve the parameter for.
# default::The default value to return if the parameter is not set.
#
# ==== Returns
# The value of the configuration parameter or the default.
#
def fetch(key, default)
@configuration.fetch(key, default)
end

# Sets up the configuration
#
# ==== Returns
# The configuration as a hash.
#
def setup()
@configuration = {}
@configuration.merge!(defaults)
@configuration
end


# Returns the configuration as a hash.
#
# ==== Returns
# The config as a hash.
#
def to_hash
@configuration
end

# Returns the config as YAML.
#
# ==== Returns
# The config as YAML.
#
def to_yaml
require "yaml"
@configuration.to_yaml
end

# Returns the configuration as a string.
#
# ==== Returns
# The config as a string.
#
def to_s
setup
@configuration[:protocol] + @configuration[:server].to_s + ':' + @configuration[:port].to_s
end


end
end

end
6 changes: 6 additions & 0 deletions lib/neography/node.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@ def remove_property(id, property)
response.parsed_response
end

def remove_properties(id)
response = delete("/node/#{id}/properties")
evaluate_response(response)
response.parsed_response
end

def del(id)
response = delete("/node/#{id}")
evaluate_response(response)
Expand Down
69 changes: 69 additions & 0 deletions lib/neography/relationship.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
module Neography
class Relationship
include HTTParty
base_uri Neography::Config.to_s
format :json

class << self

def new(type, from, to, props = nil)
options = { :body => {:to => Neography::Config.to_s + "/node/#{to[:neo_id]}", :data => props, :type => type }.to_json, :headers => {'Content-Type' => 'application/json'} }
response = post("/node/#{from[:neo_id]}/relationships", options)
evaluate_response(response)
build_relationship(response)
end

def load(id)
begin
response = get("/node/#{id}")
evaluate_response(response)
build_relationship(response)
rescue
nil
end
end

def properties(id)
get("/relationship/#{id}/properties")
end

def set_properties(id, properties)
options = { :body => properties.to_json, :headers => {'Content-Type' => 'application/json'} }
response = put("/relationship/#{id}/properties", options)
evaluate_response(response)
response.parsed_response
end

def remove_property(id, property)
response = delete("/relationship/#{id}/properties/#{property}")
evaluate_response(response)
response.parsed_response
end

def remove_properties(id)
response = delete("/relationship/#{id}/properties")
evaluate_response(response)
response.parsed_response
end

def del(id)
response = delete("/relationship/#{id}")
evaluate_response(response)
response.parsed_response
end

private

def build_relationship(response)
begin
relationship = response.parsed_response["data"]
rescue
relationship = Array.new
end
relationship[:rel_id] = response.parsed_response["self"].split('/').last
relationship
end

end
end
end
8 changes: 7 additions & 1 deletion spec/integration/node_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@
Neography::Node.remove_property(9999, :height).should be_nil
end

it "can delete all of a node's properties" do
Neography::Node.set_properties(2, {:age => 32, :name => "Tom", :weight => 200} ).should be_nil
Neography::Node.remove_properties(2).should be_nil
Neography::Node.properties(2).should be_nil
end

it "can delete an unrelated node" do
newnode = Neography::Node.new
Neography::Node.del(newnode[:neo_id]).should be_nil
Expand All @@ -72,7 +78,7 @@
it "returns nil if it tries to delete a node that has existing relationships" do
node1 = Neography::Node.new
node2 = Neography::Node.new
pending "create relationship from node1 to node2"
Neography::Relationship.new(:friends, node1, node2)
Neography::Node.del(node1[:neo_id]).should be_nil
Neography::Node.del(node2[:neo_id]).should be_nil
end
Expand Down
27 changes: 27 additions & 0 deletions spec/integration/relationship_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
require File.join(File.dirname(__FILE__), '..', 'spec_helper')

describe Neography::Relationship do
it "can create an empty relationship" do
Neography::Relationship.new(:friends, Neography::Node.new, Neography::Node.new).should include(:rel_id)
end

it "can create a relationship with one property" do
Neography::Relationship.new(:friends, Neography::Node.new, Neography::Node.new, {:since => '10-1-2010'}).should include("since")
end

it "can create a relationship with multiple properties" do
Neography::Relationship.new(:friends, Neography::Node.new, Neography::Node.new, {:since => '10-1-2010', :closeness => 'bff'}).should include("closeness"=>"bff", "since"=>"10-1-2010")
end

it "can get a relationship's properties" do
rel = Neography::Relationship.new(:friends, Neography::Node.new, Neography::Node.new)
Neography::Relationship.set_properties(rel[:rel_id], {:since => '10-1-2010'} ).should be_nil
Neography::Relationship.properties(rel[:rel_id]).should include("since"=>"10-1-2010")
end

it "returns nil if a relationship has no properties" do
rel = Neography::Relationship.new(:friends, Neography::Node.new, Neography::Node.new)
Neography::Relationship.properties(rel[:rel_id]).should be_nil
end

end
4 changes: 2 additions & 2 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@
#To test against a real database:
#1. Make sure empty database is running (./bin/neo4j-rest start)
#2. Uncomment the next two lines
#FakeWeb.clean_registry
#FakeWeb.allow_net_connect = true
FakeWeb.clean_registry
FakeWeb.allow_net_connect = true

0 comments on commit 0b5b547

Please sign in to comment.