Skip to content
Open
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
20 changes: 15 additions & 5 deletions lib/dolly/document.rb
Original file line number Diff line number Diff line change
Expand Up @@ -138,14 +138,19 @@ def self.create options = {}
obj
end

def self.property *ary
def self.property *ary, &block
self.properties ||= {}
options = ary.pop if ary.last.kind_of? Hash
options ||= {}

ary.each do |name|
self.properties[name] = Property.new options.merge(name: name)
self.write_methods name
if options[:class_name] == Hash && block_given?
ary.each do |name|
init_property name, options
property = self.properties[name]
property.instance_exec(property, &block)
end
else
ary.each { |name| init_property name, options }
end
end

Expand Down Expand Up @@ -185,9 +190,14 @@ def init_properties options = {}
init_doc options
end

def self.init_property name, opts={}
self.properties[name] = Property.new opts.merge(name: name)
self.write_methods name
end

def initialize_default_properties options
_properties.reject { |property| options.keys.include? property.name }.each do |property|
property_value = property.default.clone unless Dolly::Property::CANT_CLONE.any? { |klass| property.default.is_a? klass }
property_value = property.value.clone unless Dolly::Property::CANT_CLONE.any? { |klass| property.default.is_a? klass }
property_value ||= property.default
self.doc[property.name] ||= property_value
end
Expand Down
44 changes: 34 additions & 10 deletions lib/dolly/property.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ module Dolly
class Property
attr_writer :value
attr_accessor :name
attr_reader :class_name, :default
attr_reader :class_name, :default, :subproperties

CANT_CLONE = [NilClass, TrueClass, FalseClass, Fixnum].freeze

Expand All @@ -11,20 +11,29 @@ def initialize opts = {}
@name = opts.delete(:name).to_s
@default = opts.delete(:default)
@default = @default.clone if @default && CANT_CLONE.none? { |klass| @default.is_a? klass }
@value = @default if @default
@subproperties = {}
warn 'There are some unprocessed options!' if opts.present?
end

def value
#TODO: tets if this actually sets `doc[ "name" ]`
return @default if @value.nil?
return @value unless self_klass

klass_sym = :"#{self_klass.name.underscore}_#{__method__}"

return self_klass.new @value unless self.respond_to?(klass_sym)
return value_if_subproperties if subproperties.any?
standard_value
end

self.send klass_sym
def subproperty *ary, &block
options = ary.pop if ary.last.kind_of? Hash
options ||= {}

if options[:class_name] == Hash && block_given?
ary.each do |name|
@subproperties[name] = SubProperty.new options.merge(name: name)
self.subproperties[name].instance_exec self.subproperties[name], &block
end
else
ary.each do |name|
@subproperties[name] = SubProperty.new options.merge(name: name)
end
end
end

def array_value
Expand Down Expand Up @@ -81,5 +90,20 @@ def self_klass
@class_name.is_a?(Class)? @class_name : @class_name.constantize
end

def value_if_subproperties
@value ||= self_klass.new.tap do |v|
subproperties.each { |name, subproperty| v[name.to_s] = subproperty.value }
end
end

def standard_value
return @default if @value.nil?
klass_sym = :"#{self_klass.name.underscore}_#{__method__}"
return self_klass.new @value unless self.respond_to?(klass_sym)
self.send klass_sym
end

end

class SubProperty < Property; end
end
26 changes: 25 additions & 1 deletion test/document_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,12 @@ class FooBar < BaseDolly
class Baz < Dolly::Document; end

class FooBaz < Dolly::Document
property :foo, class_name: Hash, default: {}
property :foo, class_name: Hash, default: {} do
subproperty :bar, class_name: Array, default: []
subproperty :baz, class_name: Hash, default: Hash.new do
subproperty :far, class_name: Hash, default: Hash.new
end
end

def add_to_foo key, value
foo[key] ||= value
Expand Down Expand Up @@ -53,6 +58,12 @@ class Bar < FooBar
property :a, :b
end

class SubPropertyDocument < Dolly::Document
property :foo, :bar, class_name: Hash, default: {} do
subproperty :baz, class_name: Hash, default: Hash.new
end
end

class DocumentTest < ActiveSupport::TestCase
DB_BASE_PATH = "http://localhost:5984/test".freeze

Expand Down Expand Up @@ -498,6 +509,19 @@ def setup
assert_equal 1, bar.a
end

test 'subproperties and children subprops are populated on initialize' do
instance = FooBaz.new
expected = {"bar"=>[], "baz"=>{"far"=>{}}}
assert_equal expected, instance.foo
end

test 'subproperties may be defined for multiple properties at once' do
instance = SubPropertyDocument.new
expected = {"baz"=>{}}
assert_equal expected, instance.foo
assert_equal expected, instance.bar
end

private
def generic_response rows, count = 1
{total_rows: count, offset:0, rows: rows}
Expand Down