neoid 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,5 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ .DS_Store
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
@@ -0,0 +1,3 @@
1
+ ## v0.0.1
2
+
3
+ * initial release
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in neoid.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2012 Elad Ossadon
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
@@ -0,0 +1,271 @@
1
+ # DRAFT ONLY - GEM IS NOT HOSTED YET.
2
+
3
+ # Neoid
4
+
5
+ Make your ActiveRecords stored and searchable on Neo4j graph database, in order to make fast graph queries that MySQL would crawl while doing them.
6
+
7
+ Neoid to Neo4j is like Sunspot to Solr. You get the benefits of Neo4j speed while keeping your schema on your plain old RDBMS.
8
+
9
+ Neoid doesn't require JRuby. It's based on the great [Neography](https://github.com/maxdemarzi/neography) gem which uses Neo4j's REST API.
10
+
11
+ Neoid offers querying Neo4j for IDs of objects and then fetch them from your RDBMS, or storing all desired data on Neo4j.
12
+
13
+
14
+
15
+ ## Installation
16
+
17
+ Add to your Gemfile and run the `bundle` command to install it.
18
+
19
+ gem 'neoid'
20
+
21
+
22
+ **Requires Ruby 1.9.2 or later.**
23
+
24
+ ## Usage
25
+
26
+ ### First app configuration:
27
+
28
+ In an initializer, such as `config/initializers/01_neo4j.rb`:
29
+
30
+ ENV["NEO4J_URL"] ||= "http://localhost:7474"
31
+
32
+ uri = URI.parse(ENV["NEO4J_URL"])
33
+
34
+ $neo = Neography::Rest.new(neo4j_uri.to_s)
35
+
36
+ Neography::Config.tap do |c|
37
+ c.server = uri.host
38
+ c.port = uri.port
39
+
40
+ if uri.user && uri.password
41
+ c.authentication = 'basic'
42
+ c.username = uri.user
43
+ c.password = uri.password
44
+ end
45
+ end
46
+
47
+ Neoid.db = $neo
48
+
49
+
50
+ `01_` in the file name is in order to get this file loaded first, before the models (files are loaded alphabetically).
51
+
52
+ If you have a better idea (I bet you do!) please let me know.
53
+
54
+
55
+ ### ActiveRecord configuration
56
+
57
+ #### Nodes
58
+
59
+ For nodes, first include the `Neoid::Node` module in your model:
60
+
61
+
62
+ class User < ActiveRecord::Base
63
+ include Neoid::Node
64
+ end
65
+
66
+
67
+ This will help to create a corresponding node on Neo4j when a user is created, delete it when a user is destroyed, and update it if needed.
68
+
69
+ Then, you can customize what fields will be saved on the node in Neo4j, by implementing `to_neo` method:
70
+
71
+
72
+ class User < ActiveRecord::Base
73
+ include Neoid::Node
74
+
75
+ def to_neo
76
+ {
77
+ slug: slug,
78
+ display_name: display_name
79
+ }
80
+ end
81
+ end
82
+
83
+ You can use `neo_properties_to_hash`, a helper method to make things shorter:
84
+
85
+
86
+ def to_neo
87
+ neo_properties_to_hash(%w(slug display_name))
88
+ end
89
+
90
+
91
+ #### Relationships
92
+
93
+ Let's assume that a `User` can `Like` `Movie`s:
94
+
95
+
96
+ # user.rb
97
+
98
+ class User < ActiveRecord::Base
99
+ include Neoid::Node
100
+
101
+ has_many :likes
102
+ has_many :movies, through: :likes
103
+
104
+ def to_neo
105
+ neo_properties_to_hash(%w(slug display_name))
106
+ end
107
+ end
108
+
109
+
110
+ # movie.rb
111
+
112
+ class Movie < ActiveRecord::Base
113
+ include Neoid::Node
114
+
115
+ has_many :likes
116
+ has_many :users, through: :likes
117
+
118
+ def to_neo
119
+ neo_properties_to_hash(%w(slug name))
120
+ end
121
+ end
122
+
123
+
124
+ # like.rb
125
+
126
+ class Like < ActiveRecord::Base
127
+ belongs_to :user
128
+ belongs_to :movie
129
+ end
130
+
131
+
132
+
133
+ Now let's make the `Like` model a Neoid, by including the `Neoid::Relationship` module, and define the relationship (start & end nodes and relationship type) options with `neoidable` method:
134
+
135
+
136
+ class Like < ActiveRecord::Base
137
+ belongs_to :user
138
+ belongs_to :movie
139
+
140
+ include Neoid::Relationship
141
+ neoidable start_node: :user, end_node: :movie, type: :likes
142
+ end
143
+
144
+
145
+ Neoid adds `neo_node` and `neo_relationships` to nodes and relationships, respectively.
146
+
147
+ So you could do:
148
+
149
+ user = User.create!(display_name: "elado")
150
+ user.movies << Movie.create("Memento")
151
+ user.movies << Movie.create("Inception")
152
+
153
+ user.neo_node # => #<Neography::Node…>
154
+ user.neo_node.display_name # => "elado"
155
+
156
+ rel = user.likes.first.neo_relationship
157
+ rel.start_node # user.neo_node
158
+ rel.end_node # user.movies.first.neo_node
159
+ rel.rel_type # 'likes'
160
+
161
+
162
+ ## Querying
163
+
164
+ You can query with all [Neography](https://github.com/maxdemarzi/neography)'s API: `traverse`, `execute_query` for Cypher, and `execute_script` for Gremlin.
165
+
166
+ ### Gremlin Example:
167
+
168
+ These examples query Neo4j using Gremlin for IDs of objects, and then fetches them from ActiveRecord with an `in` query.
169
+
170
+ Of course, you can store using the `to_neo` all the data you need in Neo4j and avoid querying ActiveRecord.
171
+
172
+
173
+ **Most popular categories**
174
+
175
+ gremlin_query = <<-GREMLIN
176
+ m = [:]
177
+
178
+ g.v(0)
179
+ .out('movies_subref').out
180
+ .inE('likes')
181
+ .inV
182
+ .groupCount(m).iterate()
183
+
184
+ m.sort{-it.value}.collect{it.key.ar_id}
185
+ GREMLIN
186
+
187
+ movie_ids = Neoid.db.execute_script(gremlin_query)
188
+
189
+ Movie.where(id: movie_ids)
190
+
191
+
192
+ Assuming we have another `Friendship` model which is a relationship with start/end nodes of `user` and type of `friends`,
193
+
194
+ **Movies of user friends that the user doesn't have**
195
+
196
+ user = User.find(1)
197
+
198
+ gremlin_query = <<-GREMLIN
199
+ u = g.idx('users_index')[[ar_id:'#{user.id}']][0].toList()[0]
200
+ movies = []
201
+
202
+ u
203
+ .out('likes').aggregate(movies).back(2)
204
+ .out('friends').out('likes')
205
+ .dedup
206
+ .except(movies).collect{it.ar_id}
207
+ GREMLIN
208
+
209
+ movie_ids = Neoid.db.execute_script(gremlin_query)
210
+
211
+ Movie.where(id: movie_ids)
212
+
213
+
214
+ `[0].toList()[0]` is in order to get a pipeline object which we can actually query on.
215
+
216
+
217
+ ## Behind The Scenes
218
+
219
+ Whenever the `neo_node` on nodes or `neo_relationship` on relationships is called, Neoid checks if there's a corresponding node/relationship in Neo4j. If not, it does the following:
220
+
221
+ ### For Nodes:
222
+
223
+ 1. Ensures there's a sub reference node (read [here](http://docs.neo4j.org/chunked/stable/tutorials-java-embedded-index.html) about sub reference nodes)
224
+ 2. Creates a node based on the ActiveRecord, with the `id` attribute and all other attributes from `to_neo`
225
+ 3. Creates a relationship between the sub reference node and the newly created node
226
+ 4. Adds the ActiveRecord `id` to a node index, pointing to the Neo4j node id, for fast lookup in the future
227
+
228
+ Then, when it needs to find it again, it just seeks the node index with that ActiveRecord id for its neo node id.
229
+
230
+ ### For Relationships:
231
+
232
+ Like Nodes, it uses an index (relationship index) to look up a relationship by ActiveRecord id
233
+
234
+ 1. With the options passed in the `neoidable`, it fetches the `start_node` and `end_node`
235
+ 2. Then, it calls `neo_node` on both, in order to create the Neo4j nodes if they're not created yet, and creates the relationship with the type from the options.
236
+ 3. Add the relationship to the relationship index.
237
+
238
+ ## Testing
239
+
240
+ Neoid tests run on a regular Neo4j database, on port 7574. You probably want to have it running on a different instance than your development one.
241
+
242
+ In order to do that:
243
+
244
+ Copy the Neo4j folder to a different location,
245
+
246
+ **or**
247
+
248
+ symlink `bin`, `lib`, `plugins`, `system`, copy `conf` and create an empty `data` folder.
249
+
250
+ Then, edit `conf/neo4j-server.properties` and set the port (`org.neo4j.server.webserver.port`) from 7474 to 7574 and run the server with `bin/neo4j start`
251
+
252
+
253
+ Download, install and configure [neo4j-clean-remote-db-addon](https://github.com/jexp/neo4j-clean-remote-db-addon). For the test database, leave the default `secret-key` key.
254
+
255
+
256
+ ## Contributing
257
+
258
+ Please create a [new issue](https://github.com/elado/neoid/issues) if you run into any bugs. Contribute patches via pull requests. Write tests and make sure all tests pass.
259
+
260
+
261
+
262
+ ## To Do
263
+
264
+ * Auto create node when creating an AR, instead of lazily-creating it
265
+ * `after_update` to update a node/relationship.
266
+ * Allow to disable sub reference nodes through options
267
+ * Execute queries/scripts from model and not Neography (e.g. `Movie.neo_gremlin(gremlin_query)` with query that outputs IDs, returns a list of `Movie`s)
268
+
269
+ ---
270
+
271
+ developed by [@elado](http://twitter.com/elado) | named by [@ekampf](http://twitter.com/ekampf)
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task default: :spec
@@ -0,0 +1,22 @@
1
+ require "neoid/version"
2
+ require "neoid/model_config"
3
+ require "neoid/model_additions"
4
+ require "neoid/node"
5
+ require "neoid/relationship"
6
+ require "neoid/railtie" if defined? Rails
7
+
8
+ module Neoid
9
+ class << self
10
+ attr_accessor :db
11
+ attr_accessor :ref_node
12
+
13
+ def db
14
+ raise "Neoid.db wasn't supplied" unless @db
15
+ @db
16
+ end
17
+
18
+ def ref_node
19
+ @ref_node ||= Neography::Node.load(Neoid.db.get_root['self'])
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,46 @@
1
+ module Neoid
2
+ module ModelAdditions
3
+ module ClassMethods
4
+ def neoidable(options)
5
+ @config = Neoid::ModelConfig.new
6
+ yield(@config) if block_given?
7
+ @neoidable_options = options
8
+ end
9
+
10
+ def neoidable_options
11
+ @neoidable_options
12
+ end
13
+ end
14
+
15
+ module InstanceMethods
16
+ def to_neo
17
+ {}
18
+ end
19
+
20
+ def neo_index_name
21
+ @index_name ||= "#{self.class.name.tableize}_index"
22
+ end
23
+
24
+ protected
25
+ def neo_properties_to_hash(*property_list)
26
+ property_list.flatten.inject({}) { |all, property|
27
+ all[property] = self.send(property)
28
+ all
29
+ }
30
+ end
31
+
32
+ private
33
+ def _neo_representation
34
+ @_neo_representation ||= begin
35
+ results = neo_find_by_id
36
+ if results
37
+ neo_load(results.first['self'])
38
+ else
39
+ node = neo_create
40
+ node
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,11 @@
1
+ module Neoid
2
+ class ModelConfig
3
+ @properties = []
4
+
5
+ attr_accessor :properties
6
+
7
+ def property(name)
8
+ @properties << name
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,85 @@
1
+ module Neoid
2
+ module Node
3
+ module ClassMethods
4
+ def neo_subref_rel_type
5
+ @_neo_subref_rel_type ||= "#{self.name.tableize}_subref"
6
+ end
7
+ def neo_subref_node_rel_type
8
+ @_neo_subref_node_rel_type ||= self.name.tableize
9
+ end
10
+
11
+ def neo_subref_node
12
+ @_neo_subref_node ||= begin
13
+ subref_node_query = Neoid.ref_node.outgoing(neo_subref_rel_type)
14
+
15
+ if subref_node_query.to_a.blank?
16
+ node = Neography::Node.create(type: self.name, name: neo_subref_rel_type)
17
+ Neography::Relationship.create(
18
+ neo_subref_rel_type,
19
+ Neoid.ref_node,
20
+ node
21
+ )
22
+ else
23
+ node = subref_node_query.first
24
+ end
25
+
26
+ node
27
+ end
28
+ end
29
+ end
30
+
31
+ module InstanceMethods
32
+ def neo_find_by_id
33
+ Neoid.db.get_node_index(neo_index_name, :ar_id, self.id)
34
+ end
35
+
36
+ def neo_create
37
+ data = self.to_neo.merge(ar_type: self.class.name, ar_id: self.id)
38
+ data.reject! { |k, v| v.nil? }
39
+
40
+ node = Neography::Node.create(data)
41
+
42
+ begin
43
+ Neography::Relationship.create(
44
+ self.class.neo_subref_node_rel_type,
45
+ self.class.neo_subref_node,
46
+ node
47
+ )
48
+ rescue Exception => e
49
+ puts [$!.message] + $!.backtrace
50
+ raise e
51
+ end
52
+
53
+ Neoid.db.add_node_to_index(neo_index_name, :ar_id, self.id, node)
54
+ node
55
+ end
56
+
57
+ def neo_load(node)
58
+ Neography::Node.load(node)
59
+ end
60
+
61
+ def neo_node
62
+ _neo_representation
63
+ end
64
+
65
+ def neo_destroy
66
+ return unless neo_node
67
+ Neoid.db.remove_node_from_index(neo_index_name, neo_node)
68
+ neo_node.del
69
+ end
70
+ end
71
+
72
+ def self.included(receiver)
73
+ Neoid.db.create_node_index(receiver.name.tableize)
74
+
75
+ receiver.extend Neoid::ModelAdditions::ClassMethods
76
+ receiver.send :include, Neoid::ModelAdditions::InstanceMethods
77
+ receiver.extend ClassMethods
78
+ receiver.send :include, InstanceMethods
79
+
80
+ receiver.neo_subref_node # ensure
81
+
82
+ receiver.after_destroy :neo_destroy
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,53 @@
1
+ module Neoid
2
+ module Relationship
3
+ module InstanceMethods
4
+ def neo_find_by_id
5
+ Neoid.db.get_relationship_index(neo_index_name, :ar_id, self.id)
6
+ end
7
+
8
+ def neo_create
9
+ options = self.class.neoidable_options
10
+
11
+ start_node = self.send(options[:start_node])
12
+ end_node = self.send(options[:end_node])
13
+
14
+ return unless start_node && end_node
15
+
16
+ relationship = Neography::Relationship.create(
17
+ options[:type],
18
+ start_node.neo_node,
19
+ end_node.neo_node
20
+ )
21
+
22
+ Neoid.db.add_relationship_to_index(neo_index_name, :ar_id, self.id, relationship)
23
+
24
+ relationship
25
+ end
26
+
27
+ def neo_load(relationship)
28
+ Neography::Relationship.load(relationship)
29
+ end
30
+
31
+ def neo_destroy
32
+ return unless neo_relationship
33
+ Neoid.db.remove_relationship_from_index(neo_index_name, neo_relationship)
34
+ puts neo_relationship.del
35
+ end
36
+
37
+ def neo_relationship
38
+ _neo_representation
39
+ end
40
+ end
41
+
42
+ def self.included(receiver)
43
+ Neoid.db.create_relationship_index(receiver.name.tableize)
44
+
45
+ receiver.extend Neoid::ModelAdditions::ClassMethods
46
+ receiver.send :include, Neoid::ModelAdditions::InstanceMethods
47
+ receiver.send :include, InstanceMethods
48
+
49
+ receiver.after_create :neo_create
50
+ receiver.after_destroy :neo_destroy
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,3 @@
1
+ module Neoid
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,25 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "neoid/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "neoid"
7
+ s.version = Neoid::VERSION
8
+ s.authors = ["Elad Ossadon"]
9
+ s.email = ["elad@ossadon.com"]
10
+ s.homepage = ""
11
+ s.summary = %q{Neo4j for ActiveRecord}
12
+ s.description = %q{Extend Ruby on Rails ActiveRecord with Neo4j nodes. Keep RDBMS and utilize the power of Neo4j queries}
13
+
14
+ s.rubyforge_project = "neoid"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ s.add_development_dependency "rspec"
22
+ s.add_development_dependency "rest-client"
23
+ s.add_runtime_dependency "neography"
24
+ s.add_runtime_dependency "supermodel"
25
+ end
@@ -0,0 +1,150 @@
1
+ require 'spec_helper'
2
+
3
+ class User < SuperModel::Base
4
+ include ActiveModel::Validations::Callbacks
5
+
6
+ has_many :likes
7
+ has_many :movies, through: :likes
8
+
9
+
10
+ # _test_movies is here because SuperModel doesn't handle has_many queries
11
+ # it simulates the database. see comments in each method to see a regular AR implementation
12
+ def _test_movies
13
+ @_test_movies ||= []
14
+ end
15
+
16
+ def likes?(movie)
17
+ # likes.where(movie_id: movie.id).exists?
18
+ _test_movies.any? { |it| it.movie_id == movie.id }
19
+ end
20
+
21
+ def like!(movie)
22
+ # movies << movie unless likes?(movie)
23
+ _test_movies << Like.create(user_id: self.id, movie_id: movie.id) unless likes?(movie)
24
+ end
25
+
26
+ def unlike!(movie)
27
+ # likes.where(movie_id: movie.id, user_id: self.id).destroy_all
28
+ _test_movies.delete_if { |it| it.destroy if it.movie_id == movie.id }
29
+ end
30
+
31
+ include Neoid::Node
32
+
33
+ def to_neo
34
+ neo_properties_to_hash(%w( name slug ))
35
+ end
36
+ end
37
+
38
+ class Movie < SuperModel::Base
39
+ include ActiveModel::Validations::Callbacks
40
+
41
+ has_many :likes
42
+ has_many :users, through: :likes
43
+
44
+ include Neoid::Node
45
+
46
+ def to_neo
47
+ neo_properties_to_hash(%w( name slug year ))
48
+ end
49
+ end
50
+
51
+ class Like < SuperModel::Base
52
+ include ActiveModel::Validations::Callbacks
53
+
54
+ belongs_to :user
55
+ belongs_to :movie
56
+
57
+ include Neoid::Relationship
58
+
59
+ neoidable start_node: :user, end_node: :movie, type: :likes
60
+
61
+ def to_neo
62
+ neo_properties_to_hash(%w( rate ))
63
+ end
64
+ end
65
+
66
+ require 'spec_helper'
67
+ require 'fileutils'
68
+
69
+ describe Neoid::ModelAdditions do
70
+ before(:each) do
71
+ [ User, Movie ].each { |klass|
72
+ klass.instance_variable_set(:@_neo_subref_node, nil)
73
+ }
74
+ Neoid.ref_node = nil
75
+ end
76
+
77
+ context "nodes" do
78
+ context "create graph nodes" do
79
+ it "should call neo_create on a neo_node for user" do
80
+ user = User.create(name: "Elad Ossadon")
81
+
82
+ user.neo_find_by_id.should be_nil
83
+
84
+ user.should_receive(:neo_create)
85
+ user.neo_node
86
+ end
87
+
88
+ it "should create a neo_node for user" do
89
+ user = User.create(name: "Elad Ossadon", slug: "elado")
90
+
91
+ user.neo_node.should_not be_nil
92
+
93
+ user.neo_node.ar_id.should == user.id
94
+ user.neo_node.name.should == user.name
95
+ user.neo_node.slug.should == user.slug
96
+ end
97
+
98
+ it "should create a neo_node for movie" do
99
+ movie = Movie.create(name: "Memento", slug: "memento-1999", year: 1999)
100
+
101
+ movie.neo_node.should_not be_nil
102
+
103
+ movie.neo_node.ar_id.should == movie.id
104
+ movie.neo_node.name.should == movie.name
105
+ movie.neo_node.year.should == movie.year
106
+ end
107
+ end
108
+
109
+ context "find by id" do
110
+ it "should find a neo_node for user" do
111
+ user = User.create(name: "Elad Ossadon", slug: "elado")
112
+
113
+ user.neo_find_by_id.should be_nil
114
+ user.neo_node.should_not be_nil
115
+ user.neo_find_by_id.should_not be_nil
116
+ end
117
+ end
118
+ end
119
+
120
+ context "relationships" do
121
+ let(:user) { User.create(name: "Elad Ossadon", slug: "elado") }
122
+ let(:movie) { Movie.create(name: "Memento", slug: "memento-1999", year: 1999) }
123
+
124
+ it "should create a relationship on neo4j" do
125
+ user.like! movie
126
+ like = user.likes.first
127
+
128
+ like.neo_find_by_id.should_not be_nil
129
+
130
+ like.neo_relationship.should_not be_nil
131
+
132
+ like.neo_relationship.start_node.should == user.neo_node
133
+ like.neo_relationship.end_node.should == movie.neo_node
134
+ like.neo_relationship.rel_type.should == 'likes'
135
+ end
136
+
137
+ it "should delete a relationship on deleting a record" do
138
+ user.like! movie
139
+ like = user.likes.first
140
+
141
+ relationship_neo_id = like.neo_relationship.neo_id
142
+
143
+ Neography::Relationship.load(relationship_neo_id).should_not be_nil
144
+
145
+ user.unlike! movie
146
+
147
+ Neography::Relationship.load(relationship_neo_id).should be_nil
148
+ end
149
+ end
150
+ end
@@ -0,0 +1,5 @@
1
+ require 'spec_helper'
2
+
3
+ describe Neoid do
4
+
5
+ end
@@ -0,0 +1,28 @@
1
+ require 'neoid'
2
+ require 'supermodel'
3
+ require 'neography'
4
+ require 'rest-client'
5
+
6
+ uri = URI.parse(ENV["NEO4J_URL"] || "http://localhost:7574")
7
+ $neo = Neography::Rest.new(uri.to_s)
8
+
9
+ Neography::Config.tap do |c|
10
+ c.server = uri.host
11
+ c.port = uri.port
12
+
13
+ if uri.user && uri.password
14
+ c.authentication = 'basic'
15
+ c.username = uri.user
16
+ c.password = uri.password
17
+ end
18
+ end
19
+
20
+ Neoid.db = $neo
21
+
22
+ RSpec.configure do |config|
23
+ config.mock_with :rspec
24
+
25
+ config.before(:all) do
26
+ RestClient.delete "#{uri}/cleandb/secret-key"
27
+ end
28
+ end
metadata ADDED
@@ -0,0 +1,116 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: neoid
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Elad Ossadon
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-01-18 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: &70350248004300 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: *70350248004300
25
+ - !ruby/object:Gem::Dependency
26
+ name: rest-client
27
+ requirement: &70350248003700 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *70350248003700
36
+ - !ruby/object:Gem::Dependency
37
+ name: neography
38
+ requirement: &70350248003040 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :runtime
45
+ prerelease: false
46
+ version_requirements: *70350248003040
47
+ - !ruby/object:Gem::Dependency
48
+ name: supermodel
49
+ requirement: &70350248002080 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :runtime
56
+ prerelease: false
57
+ version_requirements: *70350248002080
58
+ description: Extend Ruby on Rails ActiveRecord with Neo4j nodes. Keep RDBMS and utilize
59
+ the power of Neo4j queries
60
+ email:
61
+ - elad@ossadon.com
62
+ executables: []
63
+ extensions: []
64
+ extra_rdoc_files: []
65
+ files:
66
+ - .gitignore
67
+ - .rspec
68
+ - CHANGELOG.md
69
+ - Gemfile
70
+ - LICENSE
71
+ - README.md
72
+ - Rakefile
73
+ - lib/neoid.rb
74
+ - lib/neoid/model_additions.rb
75
+ - lib/neoid/model_config.rb
76
+ - lib/neoid/node.rb
77
+ - lib/neoid/relationship.rb
78
+ - lib/neoid/version.rb
79
+ - neoid.gemspec
80
+ - spec/neoid/model_additions_spec.rb
81
+ - spec/neoid_spec.rb
82
+ - spec/spec_helper.rb
83
+ homepage: ''
84
+ licenses: []
85
+ post_install_message:
86
+ rdoc_options: []
87
+ require_paths:
88
+ - lib
89
+ required_ruby_version: !ruby/object:Gem::Requirement
90
+ none: false
91
+ requirements:
92
+ - - ! '>='
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
95
+ segments:
96
+ - 0
97
+ hash: -1013384318664591928
98
+ required_rubygems_version: !ruby/object:Gem::Requirement
99
+ none: false
100
+ requirements:
101
+ - - ! '>='
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ segments:
105
+ - 0
106
+ hash: -1013384318664591928
107
+ requirements: []
108
+ rubyforge_project: neoid
109
+ rubygems_version: 1.8.10
110
+ signing_key:
111
+ specification_version: 3
112
+ summary: Neo4j for ActiveRecord
113
+ test_files:
114
+ - spec/neoid/model_additions_spec.rb
115
+ - spec/neoid_spec.rb
116
+ - spec/spec_helper.rb