Array Properties accept hash with ordered keys and raise error for anything else
This commit is contained in:
parent
dd55466764
commit
1b89f1e1df
7 changed files with 82 additions and 10 deletions
|
@ -12,6 +12,8 @@
|
|||
* Refactoring of properties, added read_attribute and write_attribute methods.
|
||||
* Now possible to send anything to update_attribtues method. Invalid or readonly attributes will be ignored.
|
||||
* Attributes with arrays are *always* instantiated as a CastedArray.
|
||||
* Setting a property of type Array (or keyed hash) must be an array or an error will be raised.
|
||||
* Now possible to set Array attribute from hash where keys determine order.
|
||||
|
||||
* Major enhancements
|
||||
* Added support for anonymous CastedModels defined in Documents
|
||||
|
|
|
@ -75,6 +75,9 @@ module CouchRest
|
|||
#
|
||||
# Addtional options match those of the the belongs_to method.
|
||||
#
|
||||
# NOTE: This method is *not* recommended for large collections or collections that change
|
||||
# frequently! Use with prudence.
|
||||
#
|
||||
def collection_of(attrib, *options)
|
||||
opts = {
|
||||
:foreign_key => attrib.to_s.singularize + '_ids',
|
||||
|
@ -153,7 +156,6 @@ module CouchRest
|
|||
EOS
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -168,9 +170,9 @@ module CouchRest
|
|||
def initialize(array, casted_by, property)
|
||||
self.property = property
|
||||
self.casted_by = casted_by
|
||||
array ||= []
|
||||
(array ||= []).compact!
|
||||
casted_by[property.to_s] = [] # replace the original array!
|
||||
array.each do |obj|
|
||||
array.compact.each do |obj|
|
||||
casted_by[property.to_s] << obj.id
|
||||
end
|
||||
super(array)
|
||||
|
|
|
@ -28,8 +28,18 @@ module CouchRest
|
|||
def cast(parent, value)
|
||||
return value unless casted
|
||||
if type.is_a?(Array)
|
||||
# Convert to array if it is not already
|
||||
value = [value].compact unless value.is_a?(Array)
|
||||
if value.nil?
|
||||
value = []
|
||||
elsif [Hash, HashWithIndifferentAccess].include?(value.class)
|
||||
# Assume provided as a Hash where key is index!
|
||||
data = value
|
||||
value = [ ]
|
||||
data.keys.sort.each do |k|
|
||||
value << data[k]
|
||||
end
|
||||
elsif value.class != Array
|
||||
raise "Expecting an array or keyed hash for property #{parent.class.name}##{self.name}"
|
||||
end
|
||||
arr = value.collect { |data| cast_value(parent, data) }
|
||||
# allow casted_by calls to be passed up chain by wrapping in CastedArray
|
||||
value = type_class != String ? ::CouchRest::CastedArray.new(arr, self) : arr
|
||||
|
|
|
@ -146,6 +146,12 @@ describe "Assocations" do
|
|||
@invoice.entries.should be_empty
|
||||
end
|
||||
|
||||
it "should ignore nil entries" do
|
||||
@invoice.entries = [ nil ]
|
||||
@invoice.entry_ids.should be_empty
|
||||
@invoice.entries.should be_empty
|
||||
end
|
||||
|
||||
describe "proxy" do
|
||||
|
||||
it "should ensure new entries to proxy are matched" do
|
||||
|
|
|
@ -348,7 +348,7 @@ describe CouchRest::CastedModel do
|
|||
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')
|
||||
@professor = Person.new(:name => ['Professor', 'Plum'])
|
||||
@cat = Cat.new(:name => 'Scratchy')
|
||||
@toy1 = CatToy.new
|
||||
@toy2 = CatToy.new
|
||||
|
|
|
@ -42,13 +42,14 @@ describe "ExtendedDocument properties" do
|
|||
end
|
||||
|
||||
it "should let you use an alias for a casted attribute" do
|
||||
@card.cast_alias = Person.new(:name => "Aimonetti")
|
||||
@card.cast_alias = Person.new(:name => ["Aimonetti"])
|
||||
@card.cast_alias.name.should == ["Aimonetti"]
|
||||
@card.calias.name.should == ["Aimonetti"]
|
||||
card = Card.new(:first_name => "matt", :cast_alias => {:name => "Aimonetti"})
|
||||
card = Card.new(:first_name => "matt", :cast_alias => {:name => ["Aimonetti"]})
|
||||
card.cast_alias.name.should == ["Aimonetti"]
|
||||
card.calias.name.should == ["Aimonetti"]
|
||||
end
|
||||
|
||||
|
||||
it "should be auto timestamped" do
|
||||
@card.created_at.should be_nil
|
||||
|
@ -660,6 +661,57 @@ describe "ExtendedDocument properties" do
|
|||
end
|
||||
end
|
||||
|
||||
describe "properties of array of casted models" do
|
||||
|
||||
before(:each) do
|
||||
@course = Course.new :title => 'Test Course'
|
||||
end
|
||||
|
||||
it "should allow attribute to be set from an array of objects" do
|
||||
@course.questions = [Question.new(:q => "works?"), Question.new(:q => "Meaning of Life?")]
|
||||
@course.questions.length.should eql(2)
|
||||
end
|
||||
|
||||
it "should allow attribute to be set from an array of hashes" do
|
||||
@course.questions = [{:q => "works?"}, {:q => "Meaning of Life?"}]
|
||||
@course.questions.length.should eql(2)
|
||||
@course.questions.last.q.should eql("Meaning of Life?")
|
||||
@course.questions.last.class.should eql(Question) # typecasting
|
||||
end
|
||||
|
||||
it "should allow attribute to be set from hash with ordered keys and objects" do
|
||||
@course.questions = { '0' => Question.new(:q => "Test1"), '1' => Question.new(:q => 'Test2') }
|
||||
@course.questions.length.should eql(2)
|
||||
@course.questions.last.q.should eql('Test2')
|
||||
@course.questions.last.class.should eql(Question)
|
||||
end
|
||||
|
||||
it "should allow attribute to be set from hash with ordered keys and sub-hashes" do
|
||||
@course.questions = { '0' => {:q => "Test1"}, '1' => {:q => 'Test2'} }
|
||||
@course.questions.length.should eql(2)
|
||||
@course.questions.last.q.should eql('Test2')
|
||||
@course.questions.last.class.should eql(Question)
|
||||
end
|
||||
|
||||
it "should allow attribute to be set from hash with ordered keys and HashWithIndifferentAccess" do
|
||||
# This is similar to what you'd find in an HTML POST parameters
|
||||
hash = HashWithIndifferentAccess.new({ '0' => {:q => "Test1"}, '1' => {:q => 'Test2'} })
|
||||
@course.questions = hash
|
||||
@course.questions.length.should eql(2)
|
||||
@course.questions.last.q.should eql('Test2')
|
||||
@course.questions.last.class.should eql(Question)
|
||||
end
|
||||
|
||||
|
||||
it "should raise an error if attempting to set single value for array type" do
|
||||
lambda {
|
||||
@course.questions = Question.new(:q => 'test1')
|
||||
}.should raise_error
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
describe "a casted model retrieved from the database" do
|
||||
before(:each) do
|
||||
reset_test_db!
|
||||
|
|
4
spec/fixtures/more/person.rb
vendored
4
spec/fixtures/more/person.rb
vendored
|
@ -1,9 +1,9 @@
|
|||
class Person < Hash
|
||||
include ::CouchRest::CastedModel
|
||||
property :pet, :cast_as => 'Cat'
|
||||
property :name, :type => ['String']
|
||||
property :name, [String]
|
||||
|
||||
def last_name
|
||||
name.last
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue