Skip to content

Commit

Permalink
HasManyProxy#create for more convenient graph construction
Browse files Browse the repository at this point in the history
  • Loading branch information
jamis committed Aug 20, 2011
1 parent 159acbc commit bb04183
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 9 deletions.
23 changes: 21 additions & 2 deletions lib/runeo/has_many_proxy.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
require "runeo/node"

module Runeo
class HasManyProxy
include Enumerable
Expand All @@ -23,6 +25,24 @@ def length
@_result.length
end

def create(attributes={})
raise ArgumentError, "ambiguous #create due to too many :via specs" if @options[:via].length > 1
raise ArgumentError, "ambiguous #create due to :all direction" if @options[:via].first[1] == :all

node_class = (@options[:class] || "Runeo::Node").constantize
node = node_class.create(attributes)

via_type, via_direction = @options[:via].first
if via_direction == :in
from, to = node, @anchor
else
from, to = @anchor, node
end

from.relationships.create to, via_type
node
end

private

def load!
Expand All @@ -35,8 +55,7 @@ def load!
response = @anchor.class.connection.post("/db/data/node/#{@anchor.id}/traverse/node", payload.to_json, "application/json")

JSON.parse(response.body).map do |hash|
id = @anchor.class.extract_id(hash["self"])
(@options[:class] || Runeo::Node).new hash["data"].merge("id" => id)
Runeo::Node.instantiate(hash)
end
end
end
Expand Down
10 changes: 6 additions & 4 deletions lib/runeo/node.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ class Node < Base
class <<self
def find(id)
response = connection.get("/db/data/node/#{id.to_i}")
hash = JSON.parse(response.body)
instantiate JSON.parse(response.body)
end

def instantiate(hash)
id = extract_id(hash["self"])
data = hash["data"] || {}
type = data["_type"] || "Runeo::Node"
type.constantize.new data.merge("id" => id)
Expand All @@ -19,9 +23,7 @@ def find(id)
def create(attrs={})
payload = attrs.merge(_type: self.name).to_json
response = connection.post("/db/data/node", payload, "application/json")
hash = JSON.parse(response.body)
id = extract_id(hash["self"])
new hash["data"].merge("id" => id)
instantiate JSON.parse(response.body)
end

def has_many(association_name, options={})
Expand Down
19 changes: 19 additions & 0 deletions test/test_has_many_proxy.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
require 'helper'
require 'runeo/has_many_proxy'
require 'runeo/node'

class TestHasManyProxy < MiniTest::Unit::TestCase
include FlexMock::TestCase

class Person < Runeo::Node
end

def setup
@http = MockHTTP.new
Runeo::Base.transport = flexmock("transport", :start => @http)
Expand Down Expand Up @@ -41,6 +45,21 @@ def test_contents_should_be_nodes
assert_equal [12, 13], proxy.map(&:id)
assert_equal [Runeo::Node, Runeo::Node], proxy.map(&:class)
end

def test_create_should_create_new_node_and_new_relationship
expected_node_query = '{"name":"Jamis","_type":"TestHasManyProxy::Person"}'
expected_relationship_query = '{"to":"/db/data/node/11","type":"child"}'

@http.on :post, "/db/data/node with #{expected_node_query}", '{"self":"/db/data/node/12","data":{"name":"Jamis","_type":"TestHasManyProxy::Person"}}'
@http.on :post, "/db/data/node/12/relationships with #{expected_relationship_query}", '{"start":"/db/data/node/12","data":{},"type":"child","self":"/db/data/relationship/1","end":"/db/data/node/11"}'

proxy = Runeo::HasManyProxy.new(Runeo::Node.new("id" => 11), via: { child: :in }, class: "TestHasManyProxy::Person")
node = proxy.create("name" => "Jamis")

assert_equal 12, node.id
assert_equal "Jamis", node.name
assert_instance_of TestHasManyProxy::Person, node
end

# def test_create_should_build_outgoing_relationship_by_default
# @http.on :post, '/db/data/node/123/relationships with {"to":"/db/data/node/125","type":"SPOUSE"}',
Expand Down
6 changes: 3 additions & 3 deletions test/test_node.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,15 @@ def teardown
end

def test_find_should_return_new_node_object_with_given_nodes_properties
@http.on :get, "/db/data/node/1", '{"data":{"name":"Jamis"}}'
@http.on :get, "/db/data/node/1", '{"self":"/db/data/node/1","data":{"name":"Jamis"}}'
node = Runeo::Node.find(1)
assert_equal 1, node.id
assert_equal "Jamis", node.name
end

def test_find_should_instantiate_appropriate_node_type
@http.on :get, "/db/data/node/1", '{"data":{"name":"Jamis"}}'
@http.on :get, "/db/data/node/2", '{"data":{"name":"Jamis","_type":"TestNode::Person"}}'
@http.on :get, "/db/data/node/1", '{"self":"/db/data/node/1","data":{"name":"Jamis"}}'
@http.on :get, "/db/data/node/2", '{"self":"/db/data/node/2","data":{"name":"Jamis","_type":"TestNode::Person"}}'
assert_instance_of Runeo::Node, Runeo::Node.find(1)
assert_instance_of TestNode::Person, Runeo::Node.find(2)
end
Expand Down

0 comments on commit bb04183

Please sign in to comment.