neo4j-rails 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +8 -0
- data/History.txt +3 -0
- data/LICENSE.txt +23 -0
- data/README.markdown +76 -0
- data/Rakefile +40 -0
- data/lib/neo4j-rails.rb +2 -0
- data/lib/neo4j-rails/version.rb +3 -0
- data/lib/neo4j/delayed_save.rb +67 -0
- data/lib/neo4j/model.rb +100 -0
- data/lib/neo4j/rails.rb +2 -0
- data/lib/neo4j/railtie.rb +21 -0
- data/lib/neo4j/transaction_management.rb +15 -0
- data/neo4j-rails.gemspec +33 -0
- data/spec/neo4j/model_spec.rb +156 -0
- data/spec/spec_helper.rb +75 -0
- metadata +109 -0
data/Gemfile
ADDED
data/History.txt
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
#--
|
2
|
+
# The MIT License
|
3
|
+
#
|
4
|
+
# Copyright (c) 2010 Engine Yard, Inc.
|
5
|
+
#
|
6
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
7
|
+
# of this software and associated documentation files (the "Software"), to deal
|
8
|
+
# in the Software without restriction, including without limitation the rights
|
9
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
10
|
+
# copies of the Software, and to permit persons to whom the Software is
|
11
|
+
# furnished to do so, subject to the following conditions:
|
12
|
+
#
|
13
|
+
# The above copyright notice and this permission notice shall be included in
|
14
|
+
# all copies or substantial portions of the Software.
|
15
|
+
#
|
16
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
17
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
18
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
19
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
20
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
21
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
22
|
+
# THE SOFTWARE.
|
23
|
+
#++
|
data/README.markdown
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
# Neo4j-Rails
|
2
|
+
|
3
|
+
This is an experimental library for playing with an
|
4
|
+
ActiveModel-charged version of the [Neo4j.rb][neo4j] Ruby library. The
|
5
|
+
intent is to use it as a full replacement for ActiveRecord inside a
|
6
|
+
Rails 3 application.
|
7
|
+
|
8
|
+
Of course you can use Neo4j.rb as is in a Rails application, but this
|
9
|
+
library uses ActiveModel to make the API and usage even closer to
|
10
|
+
ActiveRecord. One example of this is the way `Model.new` works.
|
11
|
+
|
12
|
+
In Neo4j.rb, `Node.new` requires a transaction and immediately stores
|
13
|
+
the node in the database.In Neo4j-Rails, object initialization matches
|
14
|
+
ActiveRecord-style two-step `Model.new` + `Model#save` creation. This
|
15
|
+
makes it easier to create forms that don't touch the database if
|
16
|
+
validation fails.
|
17
|
+
|
18
|
+
# Usage
|
19
|
+
|
20
|
+
Include the 'neo4j-rails' library in your Gemfile to use in your
|
21
|
+
project.
|
22
|
+
|
23
|
+
gem "neo4j-rails"
|
24
|
+
|
25
|
+
Extend Neo4j::Model to create your model node classes.
|
26
|
+
|
27
|
+
class IceCream < Neo4j::Model
|
28
|
+
property :flavour
|
29
|
+
validates_presence_of :flavour
|
30
|
+
end
|
31
|
+
|
32
|
+
IceCream.new.valid? # => false
|
33
|
+
IceCream.new(:flavour => "vanilla").valid? # => true
|
34
|
+
|
35
|
+
Configure the location of the Neo4j database and Lucene index files on
|
36
|
+
disk. The Lucene search index will normally be created in memory, so
|
37
|
+
set `store_on_file = true` to save it to disk. Usually these settings
|
38
|
+
will go in `config/application.rb` or `config/environments/*.rb`.
|
39
|
+
|
40
|
+
Rails.application.configure do
|
41
|
+
config.neo4j.storage_path = "/var/neo4j"
|
42
|
+
config.lucene.storage_path = "/var/lucene"
|
43
|
+
config.lucene.store_on_file = true
|
44
|
+
end
|
45
|
+
|
46
|
+
# API
|
47
|
+
|
48
|
+
Many of the familiar API methods from ActiveRecord are duplicated in
|
49
|
+
Neo4j::Model. Neo4j::Model includes ActiveModel::Validations,
|
50
|
+
ActiveModel::Conversions, and ActiveModel::Callbacks.
|
51
|
+
|
52
|
+
class Neo4j::Model
|
53
|
+
def valid?; end
|
54
|
+
def save; end
|
55
|
+
def save!; end
|
56
|
+
def update_attributes(attributes); end
|
57
|
+
def update_attributes!(attributes); end
|
58
|
+
def destroy; end
|
59
|
+
def attributes=(attrs); end
|
60
|
+
def reload; end
|
61
|
+
def self.all; end
|
62
|
+
def self.find(*); end
|
63
|
+
def self.create(attributes); end
|
64
|
+
def self.create!(attributes); end
|
65
|
+
end
|
66
|
+
|
67
|
+
# License
|
68
|
+
|
69
|
+
Neo4j-Rails is available under the terms of the MIT license (see
|
70
|
+
LICENSE.txt for details).
|
71
|
+
|
72
|
+
However, Neo4j-Rails also depends on the [Neo4j.rb library][neo4j], and the MIT
|
73
|
+
license does not replace or cover the licensing terms of its own
|
74
|
+
library or its components.
|
75
|
+
|
76
|
+
[neo4j]: http://github.com/andreasronge/neo4j
|
data/Rakefile
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'date'
|
3
|
+
|
4
|
+
require './lib/neo4j-rails/version'
|
5
|
+
gemspec = Gem::Specification.new do |s|
|
6
|
+
s.name = %q{neo4j-rails}
|
7
|
+
s.version = Neo4jRails::VERSION
|
8
|
+
s.authors = ["Nick Sieger"]
|
9
|
+
s.date = Date.today.to_s
|
10
|
+
s.description = %{Adapts Neo4j for Rails 3 apps using ActiveModel}
|
11
|
+
s.summary = %q{Neo4j adapter for Rails 3}
|
12
|
+
s.email = ["nick@nicksieger.com"]
|
13
|
+
s.files = FileList["lib/**/*", "spec/**/*",
|
14
|
+
*%w(Gemfile neo4j-rails.gemspec History.txt LICENSE.txt Rakefile README.markdown)
|
15
|
+
].select {|f| File.file?(f) }
|
16
|
+
s.homepage = %q{http://jruby.org}
|
17
|
+
s.has_rdoc = false
|
18
|
+
s.add_dependency('rails', ">= 3.0.0.beta2")
|
19
|
+
s.add_dependency('neo4j', ">= 0.4.3")
|
20
|
+
end
|
21
|
+
|
22
|
+
task :gemspec do
|
23
|
+
File.open("neo4j-rails.gemspec", "w") {|f| f << gemspec.to_ruby }
|
24
|
+
end
|
25
|
+
|
26
|
+
require 'rake/gempackagetask'
|
27
|
+
Rake::GemPackageTask.new(gemspec) do |pkg|
|
28
|
+
end
|
29
|
+
|
30
|
+
task :release => :package do
|
31
|
+
if Neo4jRails::VERSION != ENV['VERSION']
|
32
|
+
abort "Versions do not match: #{Neo4jRails::VERSION.inspect} != #{ENV['VERSION'].inspect}"
|
33
|
+
end
|
34
|
+
sh "gem push pkg/neo4j-rails-#{Neo4jRails::VERSION}.gem"
|
35
|
+
end
|
36
|
+
|
37
|
+
require 'spec/rake/spectask'
|
38
|
+
Spec::Rake::SpecTask.new
|
39
|
+
|
40
|
+
task :default => :spec
|
data/lib/neo4j-rails.rb
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
# Extension to Neo4j::NodeMixin to delay creating/updating properties
|
2
|
+
# until #save is called.
|
3
|
+
module Neo4j::DelayedSave
|
4
|
+
def id
|
5
|
+
persisted? ? neo_id : nil
|
6
|
+
end
|
7
|
+
|
8
|
+
# Override NodeMixin#init_without_node to save the properties for
|
9
|
+
# when #save is called.
|
10
|
+
def init_without_node(props) # :nodoc:
|
11
|
+
raise "Can't use Neo4j::Model with anonymous classes" if self.class.name == ""
|
12
|
+
props[:_classname] = self.class.name
|
13
|
+
@_unsaved_props = props || {}
|
14
|
+
@persisted = false
|
15
|
+
end
|
16
|
+
|
17
|
+
# Ensure nodes loaded from the database are marked as persisted.
|
18
|
+
def init_with_node(node)
|
19
|
+
super
|
20
|
+
@persisted = true
|
21
|
+
@_unsaved_props = {}
|
22
|
+
end
|
23
|
+
|
24
|
+
# Delegate property access to temporary properties first
|
25
|
+
def [](key)
|
26
|
+
if @_unsaved_props.has_key?(key)
|
27
|
+
@_unsaved_props[key]
|
28
|
+
elsif @_java_node
|
29
|
+
@_java_node[key]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# Delegate property write to temporary properties
|
34
|
+
def []=(key, value)
|
35
|
+
@_unsaved_props[key] = value
|
36
|
+
end
|
37
|
+
|
38
|
+
def reload(*)
|
39
|
+
@_unsaved_props.clear
|
40
|
+
self
|
41
|
+
end
|
42
|
+
alias_method :reset, :reload
|
43
|
+
|
44
|
+
def save
|
45
|
+
if valid?
|
46
|
+
_run_save_callbacks do
|
47
|
+
if @persisted
|
48
|
+
_run_update_callbacks do
|
49
|
+
@_unsaved_props.each {|k,v| @_java_node[k] = v }
|
50
|
+
@_unsaved_props.clear
|
51
|
+
end
|
52
|
+
else
|
53
|
+
_run_create_callbacks do
|
54
|
+
@_java_node = Neo4j.create_node
|
55
|
+
@_java_node._wrapper = self
|
56
|
+
@_unsaved_props.each {|k,v| @_java_node[k] = v }
|
57
|
+
@_unsaved_props.clear
|
58
|
+
update_index
|
59
|
+
Neo4j.event_handler.node_created(self)
|
60
|
+
@persisted = true
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
true
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
data/lib/neo4j/model.rb
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
require 'neo4j'
|
2
|
+
require 'neo4j/extensions/reindexer'
|
3
|
+
require 'active_model'
|
4
|
+
require 'neo4j/delayed_save'
|
5
|
+
|
6
|
+
class Neo4j::Model
|
7
|
+
include Neo4j::NodeMixin
|
8
|
+
include Neo4j::DelayedSave
|
9
|
+
include ActiveModel::Conversion
|
10
|
+
include ActiveModel::Validations
|
11
|
+
extend ActiveModel::Callbacks
|
12
|
+
define_model_callbacks :create, :save, :update, :destroy
|
13
|
+
|
14
|
+
class RecordInvalidError < RuntimeError
|
15
|
+
attr_reader :record
|
16
|
+
def initialize(record)
|
17
|
+
@record = record
|
18
|
+
super(@record.errors.full_messages.join(", "))
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def persisted?
|
23
|
+
@persisted
|
24
|
+
end
|
25
|
+
|
26
|
+
def read_attribute_for_validation(key)
|
27
|
+
self[key]
|
28
|
+
end
|
29
|
+
|
30
|
+
def attributes=(attrs)
|
31
|
+
attrs.each do |k,v|
|
32
|
+
if respond_to?("#{k}=")
|
33
|
+
send("#{k}=", v)
|
34
|
+
else
|
35
|
+
self[k] = v
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def update_attributes(attributes)
|
41
|
+
self.attributes = attributes
|
42
|
+
save
|
43
|
+
end
|
44
|
+
|
45
|
+
def update_attributes!(attributes)
|
46
|
+
self.attributes = attributes
|
47
|
+
save!
|
48
|
+
end
|
49
|
+
|
50
|
+
def destroy
|
51
|
+
_run_destroy_callbacks do
|
52
|
+
del
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def save!
|
57
|
+
unless save
|
58
|
+
raise RecordInvalidError.new(self)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.load(*ids)
|
63
|
+
result = ids.map {|id| Neo4j.load_node(id) }
|
64
|
+
if ids.length == 1
|
65
|
+
result.first
|
66
|
+
else
|
67
|
+
result
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def self.all
|
72
|
+
super.nodes
|
73
|
+
end
|
74
|
+
|
75
|
+
# Handle Model.find(params[:id])
|
76
|
+
def self.find(*args)
|
77
|
+
if args.length == 1 && String === args[0] && args[0].to_i != 0
|
78
|
+
load(*args)
|
79
|
+
else
|
80
|
+
super
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def self.create(*args)
|
85
|
+
new(*args).tap {|model| model.save }
|
86
|
+
end
|
87
|
+
|
88
|
+
def self.create!(*args)
|
89
|
+
new(*args).tap {|model| model.save! }
|
90
|
+
end
|
91
|
+
|
92
|
+
def self.inherited(subc) # :nodoc:
|
93
|
+
# Make subclasses of Neo4j::Model each have their own root class/indexer
|
94
|
+
subc.instance_eval do
|
95
|
+
def root_class
|
96
|
+
self
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
data/lib/neo4j/rails.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'rails/railtie'
|
2
|
+
require 'neo4j/transaction_management'
|
3
|
+
|
4
|
+
module Neo4j
|
5
|
+
class Railtie < Rails::Railtie
|
6
|
+
config.neo4j = ActiveSupport::OrderedOptions.new
|
7
|
+
config.lucene = ActiveSupport::OrderedOptions.new
|
8
|
+
|
9
|
+
initializer "neo4j.tx" do |app|
|
10
|
+
app.config.middleware.use Neo4j::TransactionManagement
|
11
|
+
end
|
12
|
+
|
13
|
+
# Starting Neo after :load_config_initializers allows apps to
|
14
|
+
# register migrations in config/initializers
|
15
|
+
initializer "neo4j.start", :after => :load_config_initializers do |app|
|
16
|
+
Neo4j::Config.setup.merge!(app.config.neo4j.to_hash)
|
17
|
+
Lucene::Config.setup.merge!(app.config.lucene.to_hash)
|
18
|
+
Neo4j.start
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/neo4j-rails.gemspec
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{neo4j-rails}
|
5
|
+
s.version = "0.5"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Nick Sieger"]
|
9
|
+
s.date = %q{2010-06-06}
|
10
|
+
s.description = %q{Adapts Neo4j for Rails 3 apps using ActiveModel}
|
11
|
+
s.email = ["nick@nicksieger.com"]
|
12
|
+
s.files = ["lib/neo4j-rails.rb", "lib/neo4j/delayed_save.rb", "lib/neo4j/model.rb", "lib/neo4j/rails.rb", "lib/neo4j/railtie.rb", "lib/neo4j/transaction_management.rb", "lib/neo4j-rails/version.rb", "spec/spec_helper.rb", "spec/neo4j/model_spec.rb", "Gemfile", "neo4j-rails.gemspec", "History.txt", "LICENSE.txt", "Rakefile", "README.markdown"]
|
13
|
+
s.homepage = %q{http://jruby.org}
|
14
|
+
s.require_paths = ["lib"]
|
15
|
+
s.rubygems_version = %q{1.3.7}
|
16
|
+
s.summary = %q{Neo4j adapter for Rails 3}
|
17
|
+
|
18
|
+
if s.respond_to? :specification_version then
|
19
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
20
|
+
s.specification_version = 3
|
21
|
+
|
22
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
23
|
+
s.add_runtime_dependency(%q<rails>, [">= 3.0.0.beta2"])
|
24
|
+
s.add_runtime_dependency(%q<neo4j>, [">= 0.4.3"])
|
25
|
+
else
|
26
|
+
s.add_dependency(%q<rails>, [">= 3.0.0.beta2"])
|
27
|
+
s.add_dependency(%q<neo4j>, [">= 0.4.3"])
|
28
|
+
end
|
29
|
+
else
|
30
|
+
s.add_dependency(%q<rails>, [">= 3.0.0.beta2"])
|
31
|
+
s.add_dependency(%q<neo4j>, [">= 0.4.3"])
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,156 @@
|
|
1
|
+
require File.expand_path('../../spec_helper', __FILE__)
|
2
|
+
require 'neo4j/model'
|
3
|
+
|
4
|
+
class IceCream < Neo4j::Model
|
5
|
+
property :flavour
|
6
|
+
index :flavour
|
7
|
+
validates_presence_of :flavour
|
8
|
+
end
|
9
|
+
|
10
|
+
describe Neo4j::Model, "new" do
|
11
|
+
before :each do
|
12
|
+
@model = Neo4j::Model.new
|
13
|
+
end
|
14
|
+
subject { @model }
|
15
|
+
|
16
|
+
it { should_not be_persisted }
|
17
|
+
|
18
|
+
it "should allow access to properties before it is saved" do
|
19
|
+
@model["fur"] = "none"
|
20
|
+
@model["fur"].should == "none"
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should fail to save new model without a transaction" do
|
24
|
+
lambda { @model.save }.should raise_error
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe Neo4j::Model, "load" do
|
29
|
+
before :each do
|
30
|
+
txn do
|
31
|
+
@model = fixture(Neo4j::Model.new)
|
32
|
+
@model.save
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should load a previously stored node" do
|
37
|
+
result = Neo4j::Model.load(@model.id)
|
38
|
+
result.should == @model
|
39
|
+
result.should be_persisted
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe Neo4j::Model, "save" do
|
44
|
+
use_transactions
|
45
|
+
before :each do
|
46
|
+
@model = fixture(IceCream.new)
|
47
|
+
@model.flavour = "vanilla"
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should store the model in the database" do
|
51
|
+
@model.save
|
52
|
+
@model.should be_persisted
|
53
|
+
IceCream.load(@model.id).should == @model
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should not save the model if it is invalid" do
|
57
|
+
@model = IceCream.new
|
58
|
+
@model.save.should_not be_true
|
59
|
+
@model.should_not be_valid
|
60
|
+
@model.should_not be_persisted
|
61
|
+
@model.id.should be_nil
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe Neo4j::Model, "find" do
|
66
|
+
before :each do
|
67
|
+
txn do
|
68
|
+
@model = fixture(IceCream.new)
|
69
|
+
@model.flavour = "vanilla"
|
70
|
+
@model.save
|
71
|
+
end
|
72
|
+
end
|
73
|
+
use_transactions
|
74
|
+
|
75
|
+
it "should load all nodes of that type from the database" do
|
76
|
+
IceCream.all.should include(@model)
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should find a model by one of its attributes" do
|
80
|
+
IceCream.find(:flavour => "vanilla").to_a.should include(@model)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
describe Neo4j::Model, "lint" do
|
85
|
+
before :each do
|
86
|
+
@model = Neo4j::Model.new
|
87
|
+
end
|
88
|
+
|
89
|
+
include_tests ActiveModel::Lint::Tests
|
90
|
+
end
|
91
|
+
|
92
|
+
describe Neo4j::Model, "destroy" do
|
93
|
+
insert_dummy_model
|
94
|
+
|
95
|
+
it "should remove the model from the database" do
|
96
|
+
txn { @model.destroy }
|
97
|
+
txn { Neo4j::Model.load(@model.id).should be_nil }
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
describe Neo4j::Model, "create" do
|
102
|
+
use_transactions
|
103
|
+
|
104
|
+
it "should save the model and return it" do
|
105
|
+
model = Neo4j::Model.create
|
106
|
+
model.should be_persisted
|
107
|
+
end
|
108
|
+
|
109
|
+
it "should accept attributes to be set" do
|
110
|
+
model = Neo4j::Model.create :name => "Nick"
|
111
|
+
model[:name].should == "Nick"
|
112
|
+
end
|
113
|
+
|
114
|
+
it "bang version should raise an exception if save returns false" do
|
115
|
+
lambda { IceCream.create! }.should raise_error(Neo4j::Model::RecordInvalidError)
|
116
|
+
end
|
117
|
+
|
118
|
+
it "should run before and after create callbacks" do
|
119
|
+
klass = model_subclass do
|
120
|
+
property :created, :type => DateTime
|
121
|
+
before_create :timestamp
|
122
|
+
def timestamp
|
123
|
+
self.created = DateTime.now
|
124
|
+
end
|
125
|
+
after_create :mark_saved
|
126
|
+
attr_reader :saved
|
127
|
+
def mark_saved
|
128
|
+
@saved = true
|
129
|
+
end
|
130
|
+
end
|
131
|
+
klass.marshal?(:created).should be_true
|
132
|
+
model = klass.create!
|
133
|
+
model.created.should_not be_nil
|
134
|
+
model.saved.should_not be_nil
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
describe Neo4j::Model, "update_attributes" do
|
139
|
+
insert_dummy_model
|
140
|
+
|
141
|
+
it "should save the attributes" do
|
142
|
+
txn { @model.update_attributes(:a => 1, :b => 2).should be_true }
|
143
|
+
txn { @model[:a].should == 1; @model[:b].should == 2 }
|
144
|
+
end
|
145
|
+
|
146
|
+
it "should not update the model if it is invalid" do
|
147
|
+
klass = model_subclass do
|
148
|
+
property :name
|
149
|
+
validates_presence_of :name
|
150
|
+
end
|
151
|
+
model = nil
|
152
|
+
txn { model = fixture(klass.create!(:name => "vanilla")) }
|
153
|
+
txn { model.update_attributes(:name => nil).should be_false }
|
154
|
+
txn { model.reload.name.should == "vanilla" }
|
155
|
+
end
|
156
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
begin
|
2
|
+
require File.expand_path('../../.bundle/environment', __FILE__)
|
3
|
+
rescue LoadError
|
4
|
+
require 'rubygems'
|
5
|
+
require 'bundler'
|
6
|
+
Bundler.setup
|
7
|
+
end
|
8
|
+
Bundler.require :default, :test
|
9
|
+
|
10
|
+
require 'spec'
|
11
|
+
require 'spec/interop/test'
|
12
|
+
|
13
|
+
# Since we're using spec/interop/test, we might as well add our
|
14
|
+
# helpers to T::U::TC
|
15
|
+
class Test::Unit::TestCase
|
16
|
+
def self.use_transactions
|
17
|
+
before :each do
|
18
|
+
Neo4j::Transaction.new
|
19
|
+
end
|
20
|
+
|
21
|
+
after :each do
|
22
|
+
Neo4j::Transaction.failure
|
23
|
+
Neo4j::Transaction.finish
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def txn(&block)
|
28
|
+
Neo4j::Transaction.run(&block)
|
29
|
+
end
|
30
|
+
|
31
|
+
# HAX: including a module of test_ methods doesn't seem to get them
|
32
|
+
# registered, so I'm registering them manually
|
33
|
+
def self.include_tests(mod)
|
34
|
+
include mod
|
35
|
+
mod.instance_methods(false).each do |m|
|
36
|
+
example(m, {}) {__send__ m}
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
after :each do
|
41
|
+
txn { fixtures.each { |obj| obj.del rescue nil } }
|
42
|
+
end
|
43
|
+
|
44
|
+
def fixtures
|
45
|
+
@fixtures ||= []
|
46
|
+
end
|
47
|
+
|
48
|
+
def fixture(obj)
|
49
|
+
self.fixtures << obj
|
50
|
+
obj
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.insert_dummy_model
|
54
|
+
before :each do
|
55
|
+
txn do
|
56
|
+
@model = fixture(Neo4j::Model.new)
|
57
|
+
@model.save
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
module TempModel
|
63
|
+
@@_counter = 1
|
64
|
+
def self.set(klass)
|
65
|
+
name = "Model_#{@@_counter}"
|
66
|
+
@@_counter += 1
|
67
|
+
const_set(name,klass)
|
68
|
+
klass
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def model_subclass(&block)
|
73
|
+
TempModel.set(Class.new(Neo4j::Model, &block))
|
74
|
+
end
|
75
|
+
end
|
metadata
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: neo4j-rails
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 5
|
8
|
+
- 1
|
9
|
+
version: 0.5.1
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Nick Sieger
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-06-06 00:00:00 -05:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: rails
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
segments:
|
29
|
+
- 3
|
30
|
+
- 0
|
31
|
+
- 0
|
32
|
+
- beta2
|
33
|
+
version: 3.0.0.beta2
|
34
|
+
type: :runtime
|
35
|
+
version_requirements: *id001
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: neo4j
|
38
|
+
prerelease: false
|
39
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ">="
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
segments:
|
45
|
+
- 0
|
46
|
+
- 4
|
47
|
+
- 3
|
48
|
+
version: 0.4.3
|
49
|
+
type: :runtime
|
50
|
+
version_requirements: *id002
|
51
|
+
description: Adapts Neo4j for Rails 3 apps using ActiveModel
|
52
|
+
email:
|
53
|
+
- nick@nicksieger.com
|
54
|
+
executables: []
|
55
|
+
|
56
|
+
extensions: []
|
57
|
+
|
58
|
+
extra_rdoc_files: []
|
59
|
+
|
60
|
+
files:
|
61
|
+
- lib/neo4j-rails.rb
|
62
|
+
- lib/neo4j/delayed_save.rb
|
63
|
+
- lib/neo4j/model.rb
|
64
|
+
- lib/neo4j/rails.rb
|
65
|
+
- lib/neo4j/railtie.rb
|
66
|
+
- lib/neo4j/transaction_management.rb
|
67
|
+
- lib/neo4j-rails/version.rb
|
68
|
+
- spec/spec_helper.rb
|
69
|
+
- spec/neo4j/model_spec.rb
|
70
|
+
- Gemfile
|
71
|
+
- neo4j-rails.gemspec
|
72
|
+
- History.txt
|
73
|
+
- LICENSE.txt
|
74
|
+
- Rakefile
|
75
|
+
- README.markdown
|
76
|
+
has_rdoc: true
|
77
|
+
homepage: http://jruby.org
|
78
|
+
licenses: []
|
79
|
+
|
80
|
+
post_install_message:
|
81
|
+
rdoc_options: []
|
82
|
+
|
83
|
+
require_paths:
|
84
|
+
- lib
|
85
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
86
|
+
none: false
|
87
|
+
requirements:
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
segments:
|
91
|
+
- 0
|
92
|
+
version: "0"
|
93
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
94
|
+
none: false
|
95
|
+
requirements:
|
96
|
+
- - ">="
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
segments:
|
99
|
+
- 0
|
100
|
+
version: "0"
|
101
|
+
requirements: []
|
102
|
+
|
103
|
+
rubyforge_project:
|
104
|
+
rubygems_version: 1.3.7
|
105
|
+
signing_key:
|
106
|
+
specification_version: 3
|
107
|
+
summary: Neo4j adapter for Rails 3
|
108
|
+
test_files: []
|
109
|
+
|