Added helper for accessing the top level document. And more rails compatibility.

This commit is contained in:
Peter Gumeson 2009-05-28 22:42:30 -07:00
parent 936ce54449
commit d012380b67
5 changed files with 80 additions and 0 deletions

View file

@ -27,6 +27,13 @@ module CouchRest
super(key.to_s)
end
# Gets a reference to the top level extended
# document that a model is saved inside of
def base_doc
raise "Cannot call base_doc on a model that is not yet casted by a document" unless @casted_by
@casted_by.base_doc
end
# False if the casted model has already
# been saved in the containing document
def new_model?

View file

@ -110,6 +110,19 @@ module CouchRest
self.class.properties
end
# Gets a reference to the actual document in the DB
# Calls up to the next document if there is one,
# Otherwise we're at the top and we return self
def base_doc
return self if base_doc?
@casted_by.base_doc
end
# Checks if we're the top document
def base_doc?
!@casted_by
end
# Takes a hash as argument, and applies the values by using writer methods
# for each key. It doesn't save the document at the end. Raises a NoMethodError if the corresponding methods are
# missing. In case of error, no attributes are changed.

View file

@ -21,8 +21,17 @@ CouchRest::Document.class_eval do
super
end
alias_method :kind_of?, :is_a?
alias_method :to_param, :id
end
CouchRest::CastedModel.class_eval do
# The to_param method is needed for rails to generate resourceful routes.
# In your controller, remember that it's actually the id of the document.
def id
base_doc.id
end
alias_method :to_param, :id
end
require Pathname.new(File.dirname(__FILE__)).join('..', 'validation', 'validation_errors')

View file

@ -5,6 +5,7 @@ require File.join(FIXTURE_PATH, 'more', 'card')
require File.join(FIXTURE_PATH, 'more', 'cat')
require File.join(FIXTURE_PATH, 'more', 'person')
require File.join(FIXTURE_PATH, 'more', 'question')
require File.join(FIXTURE_PATH, 'more', 'course')
class WithCastedModelMixin < Hash
@ -299,4 +300,53 @@ describe CouchRest::CastedModel do
@cat.toys.first.new_model?.should be_true
end
end
describe "calling base_doc from a nested casted model" do
before :each do
@course = Course.new(:title => 'Science 101')
@professor = Person.new(:name => 'Professor Plum')
@cat = Cat.new(:name => 'Scratchy')
@toy1 = CatToy.new
@toy2 = CatToy.new
@course.professor = @professor
@professor.pet = @cat
@cat.favorite_toy = @toy1
@cat.toys << @toy2
end
it "should reference the top document for" do
@course.base_doc.should === @course
@professor.base_doc.should === @course
@cat.base_doc.should === @course
@toy1.base_doc.should === @course
@toy2.base_doc.should === @course
end
it "should call setter on top document" do
@toy1.base_doc.title = 'Tom Foolery'
@course.title.should == 'Tom Foolery'
end
end
describe "calling base_doc.save from a nested casted model" do
before :each do
reset_test_db!
@cat = Cat.new(:name => 'Snowball')
@toy = CatToy.new
@cat.favorite_toy = @toy
end
it "should not save parent document when casted model is invalid" do
@toy.should_not be_valid
@toy.base_doc.save.should be_false
lambda{@toy.base_doc.save!}.should raise_error
end
it "should save parent document when nested casted model is valid" do
@toy.name = "Mr Squeaks"
@toy.should be_valid
@toy.base_doc.save.should be_true
lambda{@toy.base_doc.save!}.should_not raise_error
end
end
end

View file

@ -1,6 +1,7 @@
class Person < Hash
include ::CouchRest::CastedModel
property :name
property :pet, :cast_as => 'Cat'
def last_name
name.last