Casted Model now no longer depends on a Hash

This commit is contained in:
Sam Lown 2011-06-25 00:58:50 +02:00
parent 98772ae98a
commit 406d2bc791
8 changed files with 57 additions and 26 deletions

View file

@ -2,6 +2,9 @@
## 1.1.0 - 2011-06-XX
* Major Fixes
* CastedModel no longer requires a Hash. Automatically includes all required methods.
* Minor Fixes
* Validation callbacks now support context (thanks kostia)
* Document comparisons now performed using database and document ID (pointer by neocsr)

View file

@ -81,10 +81,6 @@ module CouchRest
super
end
def persisted?
!new?
end
def to_key
new? ? nil : [id]
end

View file

@ -1,9 +1,9 @@
module CouchRest::Model
module CastedModel
extend ActiveSupport::Concern
included do
include CouchRest::Attributes
include CouchRest::Model::Configuration
include CouchRest::Model::Properties
include CouchRest::Model::PropertyProtection
@ -19,23 +19,17 @@ module CouchRest::Model
def base_doc?
false # Can never be base doc!
end
# Initialize a new Casted Model. Accepts the same
# options as CouchRest::Model::Base for preparing and initializing
# attributes.
def initialize(keys = {}, options = {})
super()
prepare_all_attributes(keys, options)
end
end
end
def initialize(keys = {})
raise StandardError unless self.is_a? Hash
prepare_all_attributes(keys)
super()
end
def []= key, value
super(key.to_s, value)
end
def [] key
super(key.to_s)
end
# False if the casted model has already
# been saved in the containing document
def new?

View file

@ -28,7 +28,8 @@ module CouchRest
# Trigger the callbacks (before, after, around)
# only if the document isn't new
def update(options = {})
raise "Calling #{self.class.name}#update on document that has not been created!" if self.new?
raise "Cannot save a destroyed document!" if destroyed?
raise "Calling #{self.class.name}#update on document that has not been created!" if new?
return false unless perform_validations(options)
return true if !self.disable_dirty && !self.changed?
_run_update_callbacks do
@ -69,6 +70,10 @@ module CouchRest
!!@_destroyed
end
def persisted?
!new? && !destroyed?
end
# Update the document's attributes and save. For example:
#
# doc.update_attributes :name => "Fred"

View file

@ -168,7 +168,7 @@ module CouchRest
# check if this property is going to casted
type = options.delete(:type) || options.delete(:cast_as)
if block_given?
type = Class.new(Hash) do
type = Class.new do
include CastedModel
end
if block.arity == 1 # Traditional, with options

View file

@ -1,6 +1,6 @@
class CatToy < Hash
include ::CouchRest::Model::CastedModel
class CatToy
include CouchRest::Model::CastedModel
property :name

View file

@ -1,7 +1,7 @@
# encoding: utf-8
require "spec_helper"
class WithCastedModelMixin < Hash
class WithCastedModelMixin
include CouchRest::Model::CastedModel
property :name
property :no_value
@ -9,11 +9,17 @@ class WithCastedModelMixin < Hash
property :casted_attribute, WithCastedModelMixin
end
class OldFashionedMixin < Hash
include CouchRest::Model::CastedModel
property :name
end
class DummyModel < CouchRest::Model::Base
use_database TEST_SERVER.default_database
raise "Default DB not set" if TEST_SERVER.default_database.nil?
property :casted_attribute, WithCastedModelMixin
property :keywords, [String]
property :old_casted_attribute, OldFashionedMixin
property :sub_models do |child|
child.property :title
end
@ -22,7 +28,7 @@ class DummyModel < CouchRest::Model::Base
end
end
class WithCastedCallBackModel < Hash
class WithCastedCallBackModel
include CouchRest::Model::CastedModel
property :name
property :run_before_validation
@ -155,6 +161,33 @@ describe CouchRest::Model::CastedModel do
end
end
# Basic testing for an old fashioned casted hash
describe "old hash casted as attribute" do
before :each do
@obj = DummyModel.new(:old_casted_attribute => {:name => 'Testing'})
@casted_obj = @obj.old_casted_attribute
end
it "should be available from its parent" do
@casted_obj.should be_an_instance_of(OldFashionedMixin)
end
it "should have the getters defined" do
@casted_obj.name.should == 'Testing'
end
it "should know who casted it" do
@casted_obj.casted_by.should == @obj
end
it "should know which property casted it" do
@casted_obj.casted_by_property.should == @obj.properties.detect{|p| p.to_s == 'old_casted_attribute'}
end
it "should return nil for the unknown attribute" do
@casted_obj["unknown"].should be_nil
end
end
describe "casted as an array of a different type" do
before(:each) do
@obj = DummyModel.new(:keywords => ['couch', 'sofa', 'relax', 'canapé'])

View file

@ -1,6 +1,6 @@
require "spec_helper"
class WithCastedModelMixin < Hash
class WithCastedModelMixin
include CouchRest::Model::CastedModel
property :name
property :details, Object, :default => {}