Permalink
Browse files

Better support form orm_adapter #212

  • Loading branch information...
1 parent fb25b11 commit c6c1922106704c69fca43b4e871dd890478d0fe6 @andreasronge andreasronge committed Aug 14, 2012
Showing with 191 additions and 59 deletions.
  1. +52 −5 lib/orm_adapter/adapters/neo4j.rb
  2. +6 −10 spec/orm_adapter/adapters/neo4j_spec.rb
  3. +133 −44 spec/orm_adapter/example_app_shared.rb
@@ -32,19 +32,66 @@ def get(id)
end
# Find the first instance matching conditions
- def find_first(conditions)
- klass.first(conditions)
+ def find_first(options = {})
+ conditions, order = extract_conditions!(options)
+ if !order.empty?
+ find_with_order(conditions, order).first
+ else
+ klass.first(conditions)
+ end
end
+
# Find all models matching conditions
- def find_all(conditions)
- klass.all(conditions)
+ def find_all(options = {})
+ conditions, order, limit, offset = extract_conditions!(options)
+ result = if !order.empty?
+ find_with_order(conditions, order)
+ else
+ klass.all(conditions)
+ end
+
+ if limit && offset
+ result.drop(offset).first(limit)
+ elsif limit
+ result.first(limit)
+ else
+ result.to_a
+ end
+
end
# Create a model using attributes
- def create!(attributes)
+ def create!(attributes = {})
klass.create!(attributes)
end
+
+ # @see OrmAdapter::Base#destroy
+ def destroy(object)
+ object.destroy && true if valid_object?(object)
+ end
+
+ private
+
+ def find_with_order(conditions, order)
+ conditions = wild_card_condition if conditions.nil? || conditions.empty?
+
+ result = klass.all(conditions)
+ order.inject(result) do |r,spec|
+ if spec.is_a?(Array)
+ spec[1]==:desc ? r.desc(spec[0]) : r.asc(spec[0])
+ else
+ r.asc(spec)
+ end
+ end
+ end
+
+ def wild_card_condition
+ index_key = klass._decl_props.keys.find{|k| klass.index?(k) }
+ raise "Can't perform a order query when there is no lucene index (try cypher or declare an index) on #{klass}" unless index_key
+ "#{index_key}: *"
+ end
+
end
end
end
@@ -3,21 +3,17 @@
module Neo4j
module OrmSpec
- class Note < Neo4j::Rails::Model
- end
-
class User < Neo4j::Rails::Model
- index :name
- property :name
-
- has_n(:notes).to(Note)
+ property :name, :index => :exact
+ property :rating, :type => Fixnum, :index => :exact
+ has_n(:notes).to('Neo4j::OrmSpec::Note')
end
class Note < Neo4j::Rails::Model
- index :body
- property :body
+ property :body, :index => :exact
- has_one(:owner).from(User, :notes)
+ has_one(:owner).from('Neo4j::OrmSpec::User', :notes)
+
end
# here be the specs!
@@ -19,18 +19,18 @@
# end
#
shared_examples_for "example app with orm_adapter" do
-
+
def create_model(klass, attrs = {})
klass.create!(attrs)
end
-
+
def reload_model(model)
model.class.find(model.id)
end
-
+
describe "an ORM class" do
subject { note_class }
-
+
it "#to_adapter should return an adapter instance" do
subject.to_adapter.should be_a(OrmAdapter::Base)
end
@@ -43,12 +43,12 @@ def reload_model(model)
subject.to_adapter.object_id.should == subject.to_adapter.object_id
end
end
-
+
describe "adapter instance" do
let(:note_adapter) { note_class.to_adapter }
let(:user_adapter) { user_class.to_adapter }
let(:non_existent_id) { "99999999" }
-
+
describe "#get!(id)" do
it "should return the instance with id if it exists" do
user = create_model(user_class)
@@ -80,43 +80,120 @@ def reload_model(model)
user_adapter.get(non_existent_id).should be_nil
end
end
-
- describe "#find_first(conditions)" do
- it "should return first model matching conditions, if it exists" do
- user = create_model(user_class, :name => "Fred")
- user_adapter.find_first(:name => "Fred").should == user
+
+ describe "#find_first" do
+ describe "(conditions)" do
+ it "should return first model matching conditions, if it exists" do
+ user = create_model(user_class, :name => "Fred")
+ user_adapter.find_first(:name => "Fred").should == user
+ end
+
+ it "should return nil if no conditions match" do
+ user_adapter.find_first(:name => "Betty").should == nil
+ end
+
+ it 'should return the first model if no conditions passed' do
+ user = create_model(user_class)
+ create_model(user_class)
+ user_adapter.find_first.should == user
+ end
+
+ it "when conditions contain associated object, should return first model if it exists" do
+ user = create_model(user_class)
+ note = create_model(note_class, :owner => user)
+ note_adapter.find_first(:owner => user).should == note
+ end
+
+ it "understands :id as a primary key condition (allowing scoped finding)" do
+ create_model(user_class, :name => "Fred")
+ user = create_model(user_class, :name => "Fred")
+ user_adapter.find_first(:id => user.id, :name => "Fred").should == user
+ user_adapter.find_first(:id => user.id, :name => "Not Fred").should be_nil
+ end
end
- it "should return nil if no conditions match" do
- user_adapter.find_first(:name => "Betty").should == nil
+ describe "(:order => <order array>)" do
+ it "should return first model in specified order" do
+ user1 = create_model(user_class, :name => "Fred", :rating => 1)
+ user2 = create_model(user_class, :name => "Fred", :rating => 2)
+ user_adapter.find_first(:order => [:name, [:rating, :desc]]).should == user2
+ end
end
-
- pending "when conditions contain associated object, should return first model if it exists" do
- user = create_model(user_class)
- note = create_model(note_class, :owner => user)
- note_adapter.find_first(:owner => user).should == note
+
+ describe "(:conditions => <conditions hash>, :order => <order array>)" do
+ it "should return first model matching conditions, in specified order" do
+ user1 = create_model(user_class, :name => "Fred", :rating => 1)
+ user2 = create_model(user_class, :name => "Fred", :rating => 2)
+ user_adapter.find_first(:conditions => {:name => "Fred"}, :order => [:rating, :desc]).should == user2
+ end
end
end
-
- # changed to convert the end result to an array for the test to work
- describe "#find_all(conditions)" do
- it "should return only models matching conditions" do
- user1 = create_model(user_class, :name => "Fred")
- user2 = create_model(user_class, :name => "Fred")
- user3 = create_model(user_class, :name => "Betty")
- user_adapter.find_all(:name => "Fred").to_a.should == [user1, user2]
- end
-
- # changed to convert the end result to an array for the test to work
- it "should return empty array if no conditions match" do
- user_adapter.find_all(:name => "Fred").to_a.should == []
- end
-
- pending "when conditions contain associated object, should return first model if it exists" do
- user1, user2 = create_model(user_class), create_model(user_class)
- note1 = create_model(note_class, :owner => user1)
- note2 = create_model(note_class, :owner => user2)
- note_adapter.find_all(:owner => user2).should == [note2]
+
+ describe "#find_all" do
+ describe "(conditions)" do
+ it "should return only models matching conditions" do
+ user1 = create_model(user_class, :name => "Fred")
+ user2 = create_model(user_class, :name => "Fred")
+ user3 = create_model(user_class, :name => "Betty")
+ user_adapter.find_all(:name => "Fred").should == [user1, user2]
+ end
+
+ it "should return all models if no conditions passed" do
+ user1 = create_model(user_class, :name => "Fred")
+ user2 = create_model(user_class, :name => "Fred")
+ user3 = create_model(user_class, :name => "Betty")
+ user_adapter.find_all.should == [user1, user2, user3]
+ end
+
+ it "should return empty array if no conditions match" do
+ user_adapter.find_all(:name => "Fred").should == []
+ end
+
+ it "when conditions contain associated object, should return first model if it exists" do
+ user1, user2 = create_model(user_class), create_model(user_class)
+ note1 = create_model(note_class, :owner => user1)
+ note2 = create_model(note_class, :owner => user2)
+ note_adapter.find_all(:owner => user2).should == [note2]
+ end
+ end
+
+ describe "(:order => <order array>)" do
+ it "should return all models in specified order" do
+ user1 = create_model(user_class, :name => "Fred", :rating => 1, :foo => 'user1')
+ user2 = create_model(user_class, :name => "Fred", :rating => 2, :foo => 'user2')
+ user3 = create_model(user_class, :name => "Betty", :rating => 1, :foo => 'user3')
+ user_adapter.find_all(:order => [:name, [:rating, :desc]]).to_a.should == [user3, user2, user1]
+ end
+ end
+
+ describe "(:conditions => <conditions hash>, :order => <order array>)" do
+ it "should return only models matching conditions, in specified order" do
+ user1 = create_model(user_class, :name => "Fred", :rating => 1)
+ user2 = create_model(user_class, :name => "Fred", :rating => 2)
+ user3 = create_model(user_class, :name => "Betty", :rating => 1)
+ user_adapter.find_all(:conditions => {:name => "Fred"}, :order => [:rating, :desc]).should == [user2, user1]
+ end
+ end
+
+ describe "(:limit => <number of items>)" do
+ it "should return a limited set of matching models" do
+ user1 = create_model(user_class, :name => "Fred", :rating => 1)
+ user2 = create_model(user_class, :name => "Fred", :rating => 2)
+ user3 = create_model(user_class, :name => "Betty", :rating => 1)
+ user_adapter.find_all(:limit => 1).should == [user1]
+ user_adapter.find_all(:limit => 2).should == [user1, user2]
+ end
+ end
+
+ describe "(:offset => <offset number>) with limit (as DataMapper doesn't allow offset on its own)" do
+ it "should return an offset set of matching models" do
+ user1 = create_model(user_class, :name => "Fred", :rating => 1)
+ user2 = create_model(user_class, :name => "Fred", :rating => 2)
+ user3 = create_model(user_class, :name => "Betty", :rating => 1)
+ user_adapter.find_all(:limit => 3, :offset => 0).should == [user1, user2, user3]
+ user_adapter.find_all(:limit => 3, :offset => 1).should == [user2, user3]
+ user_adapter.find_all(:limit => 1, :offset => 1).should == [user2]
+ end
end
end
@@ -129,24 +206,36 @@ def reload_model(model)
it "should raise error when create fails" do
lambda { user_adapter.create!(:user => create_model(note_class)) }.should raise_error
end
-
+
it "when attributes contain an associated object, should create a model with the attributes" do
user = create_model(user_class)
note = note_adapter.create!(:owner => user)
reload_model(note).owner.should == user
end
-
+
it "when attributes contain an has_many assoc, should create a model with the attributes" do
notes = [create_model(note_class), create_model(note_class)]
user = user_adapter.create!(:notes => notes)
reload_model(user).notes.to_a.should == notes
end
end
- describe "#column_names" do
- it "should include declared property names" do
- user_adapter.column_names.should include(:name)
+ describe "#destroy(instance)" do
+ it "should destroy the instance if it exists" do
+ user = create_model(user_class)
+ user_adapter.destroy(user).should == true
+ user_adapter.get(user.id).should be_nil
+ end
+
+ it "should return nil if passed with an invalid instance" do
+ user_adapter.destroy("nonexistent instance").should be_nil
+ end
+
+ it "should not destroy the instance if it doesn't match the model class" do
+ user = create_model(user_class)
+ note_adapter.destroy(user).should be_nil
+ user_adapter.get(user.id).should == user
end
end
end
-end
+end

0 comments on commit c6c1922

Please sign in to comment.