Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Changes

## 1.22.2

- fix instantiating properties that include CouchPotato::Persistence (call .json_create instead of .new)

## 1.22.1

Expand Down
6 changes: 3 additions & 3 deletions lib/couch_potato/persistence/simple_property.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ def load_attribute_from_document(name)
end
end

def assign_attribute(name, value)
def assign_attribute(name, value, from_json: false)
property = self.class.properties.find_property(name)
typecasted_value = type_caster.cast(value, property.type)
typecasted_value = type_caster.cast(value, property.type, from_json:)
send("#{name}_will_change!") unless @skip_dirty_tracking || typecasted_value == send(name)
instance_variable_set("@#{name}", typecasted_value)
end
Expand All @@ -35,7 +35,7 @@ def initialize(owner_clazz, name, options = {})
end

def build(object, json)
object.send(:assign_attribute, name, json[name])
object.send(:assign_attribute, name, json[name], from_json: true)
end

def serialize(json, object)
Expand Down
10 changes: 5 additions & 5 deletions lib/couch_potato/persistence/type_caster.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ module Persistence
class TypeCaster #:nodoc:
NUMBER_REGEX = /-?\d*\.?\d*/.freeze

def cast(value, type)
def cast(value, type, from_json: false)
if type == :boolean
cast_boolean(value)
elsif type.instance_of?(Array)
nested_type = type.first
value&.map { |val| cast_native(val, nested_type) }
value&.map { |val| cast_native(val, nested_type, from_json:) }
else
cast_native(value, type)
cast_native(value, type, from_json:)
end
end

Expand All @@ -29,7 +29,7 @@ def cast_boolean(value)
end
end

def cast_native(value, type)
def cast_native(value, type, from_json:)
if type && !value.is_a?(type)

if %w[Integer Bignum].include?(type.to_s)
Expand All @@ -40,7 +40,7 @@ def cast_native(value, type)
value.to_d unless value.blank?
elsif type == Hash
value.to_hash unless value.blank?
elsif type.ancestors.include?(CouchPotato::Persistence)
elsif type.ancestors.include?(CouchPotato::Persistence) && !from_json
type.new value unless value.blank?
else
type.json_create value unless value.blank?
Expand Down
2 changes: 1 addition & 1 deletion lib/couch_potato/version.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module CouchPotato
VERSION = '1.22.1'.freeze
VERSION = '1.22.2'.freeze
RSPEC_VERSION = '4.4.0'.freeze
end
30 changes: 28 additions & 2 deletions spec/property_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,8 @@ class SportsWatch < Watch
expect(w.custom_address[0]).to be_an_instance_of Address2
end

it 'initializes an typed array property from an array of hashes' do
w = Watch.new(custom_address: [{id: 'a1', city: 'Berlin'}])
it 'initializes a typed array property from an array of hashes' do
w = Watch.new(custom_address: [{_id: 'a1', city: 'Berlin'}])

expect(w.custom_address.map(&:class)).to eq([Address])
expect(w.custom_address.map(&:id)).to eq(['a1'])
Expand Down Expand Up @@ -198,6 +198,32 @@ def it_should_persist value
expect(p.ship_address).to be_nil
end

it "persists a nested object with non-couch potato attributes delegating to properties" do
class PersonWithName
include CouchPotato::Persistence

property :first_name
property :last_name

def name=(value)
self.first_name = value.split(' ').first
self.last_name = value.split(' ').last
end
end
class PersonContainer
include CouchPotato::Persistence

property :person, type: PersonWithName
end

container = PersonContainer.new(person: {name: 'John Doe'})
CouchPotato.database.save_document!(container)
container = CouchPotato.database.load_document(container.id)

expect(container.person.first_name).to eq('John')
expect(container.person.last_name).to eq('Doe')
end

it "should actually pass the null value down in the JSON document " do
p = Person.new
p.ship_address = nil
Expand Down
Loading