subobject casting

This commit is contained in:
Chris Anderson 2008-10-02 17:13:59 -07:00
parent 03f4169350
commit 9858f85c19
2 changed files with 50 additions and 2 deletions

View file

@ -54,6 +54,7 @@ module CouchRest
keys.each do |k,v|
self[k.to_s] = v
end
cast_keys
unless self['_id'] && self['_rev']
self['couchrest-type'] = self.class.to_s
end
@ -81,11 +82,20 @@ module CouchRest
new(doc)
end
# Cast a field as another class. The class must be happy to have the
# field's primitive type as the argument to it's constucture. Classes
# which inherit from CouchRest::Model are happy to act as sub-objects
# for any fields that are stored in JSON as object (and therefore are
# parsed from the JSON as Ruby Hashes).
def cast field, opts = {}
@casts ||= {}
@casts[field.to_s] = opts
end
def casts
@casts
end
# Defines methods for reading and writing from fields in the document.
# Uses key_writer and key_reader internally.
def key_accessor *keys
@ -396,6 +406,23 @@ module CouchRest
end
end
def cast_keys
return unless self.class.casts
self.class.casts.each do |k,v|
next unless self[k]
target = v[:as]
if target.is_a?(Array) && target[0].is_a?(Class)
self[k] = self[k].collect do |value|
target[0].new(value)
end
elsif target.is_a?(Class)
self[k] = target.new(self[k])
else
raise ArgumentError, ":as => MyClass, :as => [MyClass]"
end
end
end
include ::Extlib::Hook
register_instance_hooks :save, :create, :update, :destroy

View file

@ -18,9 +18,17 @@ class Question < CouchRest::Model
key_accessor :q, :a
end
class Person < CouchRest::Model
key_accessor :name
def last_name
name.last
end
end
class Course < CouchRest::Model
key_accessor :title
cast :questions, :as => [Question]
cast :professor, :as => Person
end
class Article < CouchRest::Model
@ -170,8 +178,21 @@ describe CouchRest::Model do
end
describe "getting a model with a subobject field" do
it "should instantiate it as such" do
before(:all) do
course_doc = {
"title" => "Metaphysics 410",
"professor" => {
"name" => ["Mark", "Hinchliff"]
}
}
r = Course.database.save course_doc
@course = Course.get r['id']
end
it "should load the course" do
@course["professor"]["name"][1].should == "Hinchliff"
end
it "should instantiate the professor as a person" do
@course['professor'].last_name.should == "Hinchliff"
end
end