keymaker 0.0.9 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. data/Rakefile +1 -1
  2. data/keymaker.gemspec +5 -37
  3. data/lib/keymaker.rb +8 -5
  4. data/lib/keymaker/node.rb +69 -45
  5. data/lib/keymaker/parsers/cypher_response_parser.rb +25 -0
  6. data/lib/keymaker/serialization.rb +2 -1
  7. data/lib/keymaker/service.rb +4 -17
  8. data/spec/keymaker/node_spec.rb +92 -0
  9. data/spec/keymaker/requests/add_node_to_index_request_spec.rb +13 -13
  10. data/spec/keymaker/requests/batch_request_spec.rb +3 -56
  11. data/spec/keymaker/requests/create_node_request_spec.rb +15 -9
  12. data/spec/keymaker/requests/create_relationship_request_spec.rb +19 -11
  13. data/spec/keymaker/requests/execute_cypher_request_spec.rb +1 -1
  14. data/spec/keymaker/requests/get_relationship_types_request_spec.rb +3 -4
  15. data/spec/keymaker/requests/update_node_properties_request_spec.rb +1 -1
  16. data/spec/keymaker_spec.rb +38 -8
  17. data/spec/support/active_model_lint.rb +17 -0
  18. data/spec/support/keymaker.rb +1 -1
  19. metadata +8 -73
  20. data/spec/cassettes/Keymaker_AddNodeToIndexRequest/with_valid_options/returns_a_201_status_code.yml +0 -203
  21. data/spec/cassettes/Keymaker_AddNodeToIndexRequest/with_valid_options/returns_application/json.yml +0 -203
  22. data/spec/cassettes/Keymaker_AddNodeToIndexRequest/with_valid_options/returns_the_Neo4j_REST_API_starting_point_response_request.yml +0 -203
  23. data/spec/cassettes/Keymaker_BatchRequest/when_a_resource_is_not_found/raises_BatchRequestError.yml +0 -120
  24. data/spec/cassettes/Keymaker_BatchRequest/when_to_and_method_are_not_set/raises_BatchRequestError.yml +0 -106
  25. data/spec/cassettes/Keymaker_BatchRequest/with_valid_options/returns_a_200_status_code.yml +0 -129
  26. data/spec/cassettes/Keymaker_BatchRequest/with_valid_options/runs_the_commands_and_returns_their_respective_results.yml +0 -129
  27. data/spec/cassettes/Keymaker_CreateNodeRequest/returns_a_201_status_code.yml +0 -112
  28. data/spec/cassettes/Keymaker_CreateNodeRequest/returns_application/json.yml +0 -112
  29. data/spec/cassettes/Keymaker_CreateNodeRequest/with_properties/creates_a_node_with_the_given_properties.yml +0 -112
  30. data/spec/cassettes/Keymaker_CreateNodeRequest/without_properties/creates_an_empty_node.yml +0 -112
  31. data/spec/cassettes/Keymaker_CreateRelationshipRequest/with_invalid_options/raises_ClientError.yml +0 -201
  32. data/spec/cassettes/Keymaker_CreateRelationshipRequest/with_properties/creates_a_node_with_the_given_properties.yml +0 -233
  33. data/spec/cassettes/Keymaker_CreateRelationshipRequest/with_properties/returns_a_201_status_code.yml +0 -196
  34. data/spec/cassettes/Keymaker_CreateRelationshipRequest/with_properties/returns_application/json.yml +0 -196
  35. data/spec/cassettes/Keymaker_CreateRelationshipRequest/without_properties/creates_an_empty_relationship_of_type_birthed_.yml +0 -195
  36. data/spec/cassettes/Keymaker_DeleteRelationshipRequest/with_a_non-existent_relationship/raises_ResourceNotFound.yml +0 -191
  37. data/spec/cassettes/Keymaker_DeleteRelationshipRequest/with_an_existing_relationship/deletes_the_relationship.yml +0 -219
  38. data/spec/cassettes/Keymaker_ExecuteCypherRequest/with_a_valid_Cypher_Query/returns_a_200_status_code.yml +0 -111
  39. data/spec/cassettes/Keymaker_ExecuteCypherRequest/with_an_invalid_Cypher_Query/raises_ClientError.yml +0 -108
  40. data/spec/cassettes/Keymaker_ExecuteGremlinRequest/with_a_valid_Gremlin_Script/returns_a_200_status_code.yml +0 -98
  41. data/spec/cassettes/Keymaker_ExecuteGremlinRequest/with_an_invalid_Gremlin_Script/raises_ClientError.yml +0 -107
  42. data/spec/cassettes/Keymaker_GetNodeRequest/with_a_non-existent_node_id/raises_ResourceNotFound.yml +0 -101
  43. data/spec/cassettes/Keymaker_GetNodeRequest/with_an_empty_node_id/raises_ClientError.yml +0 -111
  44. data/spec/cassettes/Keymaker_GetRelationshipTypesRequest/with_existing_relationships/returns_a_unique_array_of_relationship_types.yml +0 -220
  45. data/spec/cassettes/Keymaker_ServiceRootRequest/returns_a_200_status_code.yml +0 -105
  46. data/spec/cassettes/Keymaker_ServiceRootRequest/returns_application/json.yml +0 -105
  47. data/spec/cassettes/Keymaker_ServiceRootRequest/returns_the_Neo4j_REST_API_starting_point_response_request.yml +0 -105
  48. data/spec/cassettes/Keymaker_TraversePathRequest/_traverse_path_properties/with_options/builds_the_query_properties_with_defaults.yml +0 -157
  49. data/spec/cassettes/Keymaker_TraversePathRequest/with_invalid_options/raise_a_ClientError.yml +0 -193
  50. data/spec/cassettes/Keymaker_TraversePathRequest/with_valid_options/returns_status_code_200.yml +0 -269
  51. data/spec/cassettes/Keymaker_UpdateNodePropertiesRequest/_node_properties/excludes_the_node_id.yml +0 -157
  52. data/spec/cassettes/Keymaker_UpdateNodePropertiesRequest/with_invalid_options/raises_a_ClientError.yml +0 -193
  53. data/spec/cassettes/Keymaker_UpdateNodePropertiesRequest/with_valid_options/returns_a_status_of_204.yml +0 -182
  54. data/spec/cassettes/Keymaker_UpdateNodePropertiesRequest/with_valid_options/updates_the_properties.yml +0 -214
data/Rakefile CHANGED
@@ -134,7 +134,7 @@ NEO4J_PORT = ENV['NEO4J_PORT'] || '7477' # Don't clobber standard neo4j ports 74
134
134
 
135
135
  namespace :neo4j do
136
136
 
137
- desc "Install neo4j on localhost:#{NEO4J_PORT}. e.g. rake neo4j:install[community,1.7.M03]"
137
+ desc "Install neo4j on localhost:#{NEO4J_PORT}. e.g. rake neo4j:install[community,1.8.RC1]"
138
138
  task :install, :edition, :version do |t, args|
139
139
  args.with_defaults(:edition => "community", :version => "1.7")
140
140
 
@@ -5,8 +5,8 @@ Gem::Specification.new do |s|
5
5
  s.rubygems_version = '1.3.5'
6
6
 
7
7
  s.name = 'keymaker'
8
- s.version = '0.0.9'
9
- s.date = '2012-09-22'
8
+ s.version = '0.1.0'
9
+ s.date = '2012-10-14'
10
10
 
11
11
  s.description = %q{A multi-layer REST API wrapper for neo4j.}
12
12
  s.summary = %q{A multi-layer REST API wrapper for neo4j.}
@@ -48,6 +48,7 @@ Gem::Specification.new do |s|
48
48
  lib/keymaker/indexing.rb
49
49
  lib/keymaker/match_method.rb
50
50
  lib/keymaker/node.rb
51
+ lib/keymaker/parsers/cypher_response_parser.rb
51
52
  lib/keymaker/rails_tasks.rb
52
53
  lib/keymaker/railtie.rb
53
54
  lib/keymaker/request.rb
@@ -69,42 +70,8 @@ Gem::Specification.new do |s|
69
70
  lib/keymaker/response.rb
70
71
  lib/keymaker/serialization.rb
71
72
  lib/keymaker/service.rb
72
- spec/cassettes/Keymaker_AddNodeToIndexRequest/with_valid_options/returns_a_201_status_code.yml
73
- spec/cassettes/Keymaker_AddNodeToIndexRequest/with_valid_options/returns_application/json.yml
74
- spec/cassettes/Keymaker_AddNodeToIndexRequest/with_valid_options/returns_the_Neo4j_REST_API_starting_point_response_request.yml
75
- spec/cassettes/Keymaker_BatchRequest/when_a_resource_is_not_found/raises_BatchRequestError.yml
76
- spec/cassettes/Keymaker_BatchRequest/when_to_and_method_are_not_set/raises_BatchRequestError.yml
77
- spec/cassettes/Keymaker_BatchRequest/with_valid_options/returns_a_200_status_code.yml
78
- spec/cassettes/Keymaker_BatchRequest/with_valid_options/runs_the_commands_and_returns_their_respective_results.yml
79
- spec/cassettes/Keymaker_CreateNodeRequest/returns_a_201_status_code.yml
80
- spec/cassettes/Keymaker_CreateNodeRequest/returns_application/json.yml
81
- spec/cassettes/Keymaker_CreateNodeRequest/with_properties/creates_a_node_with_the_given_properties.yml
82
- spec/cassettes/Keymaker_CreateNodeRequest/without_properties/creates_an_empty_node.yml
83
- spec/cassettes/Keymaker_CreateRelationshipRequest/with_invalid_options/raises_ClientError.yml
84
- spec/cassettes/Keymaker_CreateRelationshipRequest/with_properties/creates_a_node_with_the_given_properties.yml
85
- spec/cassettes/Keymaker_CreateRelationshipRequest/with_properties/returns_a_201_status_code.yml
86
- spec/cassettes/Keymaker_CreateRelationshipRequest/with_properties/returns_application/json.yml
87
- spec/cassettes/Keymaker_CreateRelationshipRequest/without_properties/creates_an_empty_relationship_of_type_birthed_.yml
88
- spec/cassettes/Keymaker_DeleteRelationshipRequest/with_a_non-existent_relationship/raises_ResourceNotFound.yml
89
- spec/cassettes/Keymaker_DeleteRelationshipRequest/with_an_existing_relationship/deletes_the_relationship.yml
90
- spec/cassettes/Keymaker_ExecuteCypherRequest/with_a_valid_Cypher_Query/returns_a_200_status_code.yml
91
- spec/cassettes/Keymaker_ExecuteCypherRequest/with_an_invalid_Cypher_Query/raises_ClientError.yml
92
- spec/cassettes/Keymaker_ExecuteGremlinRequest/with_a_valid_Gremlin_Script/returns_a_200_status_code.yml
93
- spec/cassettes/Keymaker_ExecuteGremlinRequest/with_an_invalid_Gremlin_Script/raises_ClientError.yml
94
- spec/cassettes/Keymaker_GetNodeRequest/with_a_non-existent_node_id/raises_ResourceNotFound.yml
95
- spec/cassettes/Keymaker_GetNodeRequest/with_an_empty_node_id/raises_ClientError.yml
96
- spec/cassettes/Keymaker_GetRelationshipTypesRequest/with_existing_relationships/returns_a_unique_array_of_relationship_types.yml
97
- spec/cassettes/Keymaker_ServiceRootRequest/returns_a_200_status_code.yml
98
- spec/cassettes/Keymaker_ServiceRootRequest/returns_application/json.yml
99
- spec/cassettes/Keymaker_ServiceRootRequest/returns_the_Neo4j_REST_API_starting_point_response_request.yml
100
- spec/cassettes/Keymaker_TraversePathRequest/_traverse_path_properties/with_options/builds_the_query_properties_with_defaults.yml
101
- spec/cassettes/Keymaker_TraversePathRequest/with_invalid_options/raise_a_ClientError.yml
102
- spec/cassettes/Keymaker_TraversePathRequest/with_valid_options/returns_status_code_200.yml
103
- spec/cassettes/Keymaker_UpdateNodePropertiesRequest/_node_properties/excludes_the_node_id.yml
104
- spec/cassettes/Keymaker_UpdateNodePropertiesRequest/with_invalid_options/raises_a_ClientError.yml
105
- spec/cassettes/Keymaker_UpdateNodePropertiesRequest/with_valid_options/returns_a_status_of_204.yml
106
- spec/cassettes/Keymaker_UpdateNodePropertiesRequest/with_valid_options/updates_the_properties.yml
107
73
  spec/configuration_spec.rb
74
+ spec/keymaker/node_spec.rb
108
75
  spec/keymaker/requests/add_node_to_index_request_spec.rb
109
76
  spec/keymaker/requests/batch_get_nodes_request_spec.rb
110
77
  spec/keymaker/requests/batch_request_spec.rb
@@ -123,6 +90,7 @@ Gem::Specification.new do |s|
123
90
  spec/keymaker_spec.rb
124
91
  spec/service_spec.rb
125
92
  spec/spec_helper.rb
93
+ spec/support/active_model_lint.rb
126
94
  spec/support/keymaker.rb
127
95
  spec/support/vcr.rb
128
96
  ]
@@ -2,11 +2,18 @@ require 'faraday'
2
2
  require 'faraday_middleware'
3
3
  require 'hashie'
4
4
  require 'active_model'
5
+ require 'active_model/validations'
6
+ require 'active_model/callbacks'
5
7
  require 'active_support/core_ext/string/inflections'
8
+ require 'active_support/core_ext/object/blank'
9
+ require 'active_support/core_ext/class/attribute'
10
+ require 'active_support/core_ext/string/conversions'
11
+ require 'active_support/hash_with_indifferent_access'
6
12
 
7
13
  require 'keymaker/match_method'
8
14
  require 'keymaker/errors'
9
15
  require 'keymaker/response'
16
+ require 'keymaker/parsers/cypher_response_parser'
10
17
  require 'keymaker/configuration'
11
18
  require 'keymaker/service'
12
19
 
@@ -14,19 +21,15 @@ require 'keymaker/request'
14
21
 
15
22
  require 'keymaker/requests/batch_request'
16
23
  require 'keymaker/requests/batch_get_nodes_request'
17
-
18
24
  require 'keymaker/requests/create_node_request'
19
25
  require 'keymaker/requests/delete_node_request'
20
26
  require 'keymaker/requests/get_node_request'
21
-
22
27
  require 'keymaker/requests/add_node_to_index_request'
23
28
  require 'keymaker/requests/remove_node_from_index_request'
24
29
  require 'keymaker/requests/update_node_properties_request'
25
-
26
30
  require 'keymaker/requests/create_relationship_request'
27
31
  require 'keymaker/requests/delete_relationship_request'
28
32
  require 'keymaker/requests/get_relationship_types_request'
29
-
30
33
  require 'keymaker/requests/execute_cypher_request'
31
34
  require 'keymaker/requests/execute_gremlin_request'
32
35
  require 'keymaker/requests/traverse_path_request'
@@ -40,7 +43,7 @@ require 'keymaker/railtie' if defined? Rails::Railtie
40
43
 
41
44
  module Keymaker
42
45
 
43
- VERSION = "0.0.9"
46
+ VERSION = "0.1.0"
44
47
 
45
48
  def self.service
46
49
  @service ||= Keymaker::Service.new(Keymaker::Configuration.new)
@@ -5,16 +5,21 @@ module Keymaker
5
5
  module Node
6
6
 
7
7
  def self.included(base)
8
- base.extend ActiveModel::Callbacks
9
- base.extend ClassMethods
10
8
 
11
9
  base.class_eval do
12
- attr_writer :new_node
10
+ extend ActiveModel::Callbacks
11
+ extend ActiveModel::Naming
13
12
  include ActiveModel::MassAssignmentSecurity
13
+ include ActiveModel::Validations
14
+ include ActiveModel::Conversion
14
15
 
15
16
  include Keymaker::Indexing
16
17
  include Keymaker::Serialization
17
18
 
19
+ extend Keymaker::Node::ClassMethods
20
+ include Keymaker::Node::InstanceMethods
21
+
22
+ attr_writer :new_node
18
23
  attr_protected :created_at, :updated_at
19
24
  end
20
25
 
@@ -30,10 +35,10 @@ module Keymaker
30
35
  base.property :node_id, Integer
31
36
  base.property :created_at, DateTime
32
37
  base.property :updated_at, DateTime
38
+
33
39
  end
34
40
 
35
41
  module ClassMethods
36
-
37
42
  extend Forwardable
38
43
 
39
44
  def_delegator :Keymaker, :service, :neo_service
@@ -47,63 +52,82 @@ module Keymaker
47
52
  attr_accessor attribute
48
53
  end
49
54
 
50
- def execute_cypher(query, params={}, return_type=:results_only)
51
- executed_query = neo_service.execute_query(query, params)
52
- if executed_query.present?
53
- case return_type
54
- when :results_only
55
- executed_query["data"].flatten
56
- # TODO: Make this less specific
57
- when :full_user
58
- {"user" => executed_query["data"].flatten[0]["data"], "neo_id" => executed_query["data"].flatten[1]}
55
+ def create(attributes)
56
+ new(attributes).save
57
+ end
58
+
59
+ def find_by_cypher(query, params={})
60
+ find_all_by_cypher(query, params).first
61
+ end
62
+
63
+ def find_all_by_cypher(query, params={})
64
+ neo_service.execute_cypher(query, params)
65
+ end
66
+
67
+ def find(node_id)
68
+ node = neo_service.get_node(node_id)
69
+ if node.present?
70
+ new(node.slice(*properties)).tap do |neo_node|
71
+ neo_node.node_id = node.neo4j_id
72
+ neo_node.new_node = false
59
73
  end
60
- else
61
- return []
62
74
  end
63
75
  end
64
76
 
65
77
  end
66
78
 
67
- def initialize(attrs)
68
- @new_node = true
69
- process_attrs(attrs) if attrs.present?
70
- end
79
+ module InstanceMethods
71
80
 
72
- def neo_service
73
- self.class.neo_service
74
- end
81
+ def initialize(attrs = {})
82
+ @new_node = true
83
+ process_attrs(attrs) if attrs.present?
84
+ end
75
85
 
76
- def new?
77
- @new_node
78
- end
86
+ def neo_service
87
+ self.class.neo_service
88
+ end
79
89
 
80
- def sanitize(attrs)
81
- serializable_hash(except: :node_id).merge(attrs.except('node_id')).reject {|k,v| v.blank?}
82
- end
90
+ def new?
91
+ @new_node
92
+ end
83
93
 
84
- def save
85
- create_or_update
86
- end
94
+ def sanitize(attrs)
95
+ serializable_hash(except: :node_id).merge(attrs.except('node_id')).reject {|k,v| v.blank?}
96
+ end
87
97
 
88
- def create_or_update
89
- run_callbacks :save do
90
- new? ? create : update(attributes)
98
+ def save
99
+ create_or_update
91
100
  end
92
- end
93
101
 
94
- def create
95
- run_callbacks :create do
96
- neo_service.create_node(sanitize(attributes)).on_success do |response|
97
- self.node_id = response.neo4j_id
98
- self.new_node = false
102
+ def create_or_update
103
+ run_callbacks :save do
104
+ new? ? create : update(attributes)
99
105
  end
100
- self
101
106
  end
102
- end
103
107
 
104
- def update(attrs)
105
- process_attrs(sanitize(attrs.merge(updated_at: Time.now.utc.to_i)))
106
- neo_service.update_node_properties(node_id, sanitize(attributes))
108
+ def create
109
+ run_callbacks :create do
110
+ neo_service.create_node(sanitize(attributes)).on_success do |response|
111
+ self.node_id = response.neo4j_id
112
+ self.new_node = false
113
+ end
114
+ self
115
+ end
116
+ end
117
+
118
+ def update(attrs)
119
+ process_attrs(sanitize(attrs.merge(updated_at: Time.now.utc.to_i)))
120
+ neo_service.update_node_properties(node_id, sanitize(attributes))
121
+ end
122
+
123
+ def persisted?
124
+ node_id.present?
125
+ end
126
+
127
+ def to_key
128
+ persisted? ? [node_id] : nil
129
+ end
130
+
107
131
  end
108
132
 
109
133
  end
@@ -0,0 +1,25 @@
1
+ module Keymaker
2
+ class CypherResponseParser
3
+
4
+ def self.parse(response_body)
5
+ response_body.data.map do |result|
6
+ if response_body.columns.one? && result.first.kind_of?(Hashie::Mash)
7
+ result.first.data
8
+ else
9
+ translate_response(response_body, result)
10
+ end
11
+ end
12
+ end
13
+
14
+ def self.translate_response(response_body, result)
15
+ Hashie::Mash.new(Hash[sanitized_column_names(response_body).zip(result)])
16
+ end
17
+
18
+ def self.sanitized_column_names(response_body)
19
+ response_body.columns.map do |column|
20
+ column[/[^\.]+$/]
21
+ end
22
+ end
23
+
24
+ end
25
+ end
@@ -12,7 +12,7 @@ module Keymaker::Serialization
12
12
  when Time
13
13
  Time.at(v)
14
14
  when String
15
- DateTime.strptime(v).to_time
15
+ v.to_time
16
16
  else
17
17
  Time.now.utc
18
18
  end
@@ -43,4 +43,5 @@ module Keymaker::Serialization
43
43
  self.class.properties.each{|property| hash[property.to_s] }
44
44
  end
45
45
  end
46
+
46
47
  end
@@ -18,8 +18,8 @@ module Keymaker
18
18
 
19
19
  def connection
20
20
  @connection ||= Faraday.new(url: config.connection_service_root_url) do |conn|
21
- conn.use FaradayMiddleware::Mashify
22
21
  conn.request :json
22
+ conn.response :mashify
23
23
  conn.response :json, :content_type => /\bjson$/
24
24
  conn.adapter :net_http
25
25
  end
@@ -36,8 +36,6 @@ module Keymaker
36
36
  super
37
37
  end
38
38
 
39
- ## Nodes
40
- # Create Node
41
39
  def create_node(attrs)
42
40
  # TODO: parse response into manageable Ruby objects
43
41
  create_node_request(attrs)
@@ -49,58 +47,47 @@ module Keymaker
49
47
  data.merge!("neo4j_id" => response.neo4j_id, "__raw_response__" => response)
50
48
  end
51
49
 
52
- # Update Node properties
53
50
  def update_node_properties(node_id, attrs)
54
51
  update_node_properties_request({node_id: node_id}.merge(attrs))
55
52
  end
56
53
 
57
- # Delete Node
58
54
  def delete_node(node_id)
59
55
  delete_node_request(node_id: node_id)
60
56
  end
61
57
 
62
- # Create Relationship
63
58
  def create_relationship(rel_type, start_node_id, end_node_id, data={})
64
59
  create_relationship_request({node_id: start_node_id, rel_type: rel_type, end_node_id: end_node_id, data: data})
65
60
  end
66
61
 
67
- # Delete Relationship
68
62
  def delete_relationship(relationship_id)
69
63
  delete_relationship_request(relationship_id: relationship_id)
70
64
  end
71
65
 
72
- # Add Node to Index
73
66
  def add_node_to_index(index_name, key, value, node_id)
74
67
  add_node_to_index_request(index_name: index_name, key: key, value: value, node_id: node_id)
75
68
  end
76
69
 
77
- # Remove Node from Index
78
70
  def remove_node_from_index(index_name, key, value, node_id)
79
71
  remove_node_from_index_request(index_name: index_name, key: key, value: value, node_id: node_id)
80
72
  end
81
73
 
82
- # Path Traverse
83
74
  def path_traverse(start_node_id, data={})
84
75
  traverse_path_request({node_id: start_node_id}.merge(data))
85
76
  end
86
77
 
87
- # Batch
88
- ## GET Nodes
89
78
  def batch_get_nodes(node_ids)
90
79
  batch_get_nodes_request(node_ids)
91
80
  end
92
81
 
93
- # Cypher Query
94
- def execute_query(query, params)
95
- execute_cypher_request({query: query, params: params}).body
82
+ def execute_cypher(query, params)
83
+ response = execute_cypher_request({query: query, params: params})
84
+ Keymaker::CypherResponseParser.parse(response.body)
96
85
  end
97
86
 
98
- # Gremlin Script
99
87
  def execute_script(script, params={})
100
88
  execute_gremlin_request({script: script, params: params})
101
89
  end
102
90
 
103
- # HTTP Verbs
104
91
  def get(url, body)
105
92
  faraday_response = connection.get(parse_url(url), body)
106
93
  Keymaker::Response.new(self, faraday_response)
@@ -0,0 +1,92 @@
1
+ require 'spec_helper'
2
+
3
+ class Terminator
4
+ include Keymaker::Node
5
+ property :name
6
+ end
7
+
8
+ describe Keymaker::Node do
9
+
10
+ let(:terminator) { Terminator.create(name: 'T1000') }
11
+
12
+ subject { terminator }
13
+
14
+ it_behaves_like "ActiveModel"
15
+
16
+ describe ".create" do
17
+ subject { terminator }
18
+ its(:node_id) { should be_present }
19
+ its(:name) { should == 'T1000' }
20
+ it { should_not be_new }
21
+ it { should be_a(Terminator) }
22
+ end
23
+
24
+ describe ".find(node_id)" do
25
+
26
+ subject { Terminator.find(node_id) }
27
+
28
+ context "when terminator is present" do
29
+ let(:node_id) { terminator.node_id }
30
+
31
+ its(:node_id) { should be_present }
32
+ its(:name) { should == 'T1000' }
33
+ it { should be_present }
34
+ it { should_not be_new }
35
+ it { should be_a(Terminator) }
36
+ end
37
+
38
+ context "when terminator is not present" do
39
+ let(:node_id) { 9001 }
40
+ it "raises an Keymaker::ResourceNotFound error" do
41
+ expect { subject }.to raise_error(Keymaker::ResourceNotFound)
42
+ end
43
+ end
44
+
45
+ end
46
+
47
+ describe "#persisted?" do
48
+ let(:new_node) { Terminator.new(name: "T1000") }
49
+ subject { node.persisted? }
50
+
51
+ context "when persisted" do
52
+ let(:node) { new_node.save }
53
+ it { subject.should be_true }
54
+ end
55
+
56
+ context "when not persisted" do
57
+ let(:node) { new_node }
58
+ it { subject.should be_false }
59
+ end
60
+
61
+ end
62
+
63
+ describe "#to_key" do
64
+
65
+ context "when persisted" do
66
+ subject { terminator.to_key }
67
+ it { subject.first.should be_a(Integer) }
68
+ it { subject.should include(terminator.node_id) }
69
+ end
70
+
71
+ context "when not persisted" do
72
+ subject { Terminator.new(name: "T1000").to_key }
73
+ it { subject.should be_blank }
74
+ end
75
+
76
+ end
77
+
78
+ describe "#to_param" do
79
+
80
+ context "when persisted" do
81
+ subject { terminator.to_param }
82
+ it { subject.should == terminator.node_id.to_s }
83
+ end
84
+
85
+ context "when not persisted" do
86
+ subject { Terminator.new(name: "T1000").to_param }
87
+ it { subject.should be_nil }
88
+ end
89
+
90
+ end
91
+
92
+ end