From ecc097687606a1c4ef323ca9344c24f09a1bcc2c Mon Sep 17 00:00:00 2001 From: seancookr Date: Fri, 28 Jul 2017 09:40:26 -0700 Subject: [PATCH 1/4] add default proc options for hashes --- lib/dolly/document.rb | 1 + lib/dolly/property.rb | 11 +++++++++-- test/document_test.rb | 10 ++++++++++ 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/lib/dolly/document.rb b/lib/dolly/document.rb index 6ad2641..d9f837b 100644 --- a/lib/dolly/document.rb +++ b/lib/dolly/document.rb @@ -189,6 +189,7 @@ 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.default + property_value.default_proc = property.default_proc if property.default_proc? && property.default.is_a?(Hash) self.doc[property.name] ||= property_value end end diff --git a/lib/dolly/property.rb b/lib/dolly/property.rb index 27c89a5..ac41394 100644 --- a/lib/dolly/property.rb +++ b/lib/dolly/property.rb @@ -2,7 +2,7 @@ module Dolly class Property attr_writer :value attr_accessor :name - attr_reader :class_name, :default + attr_reader :class_name, :default, :default_proc CANT_CLONE = [NilClass, TrueClass, FalseClass, Fixnum].freeze @@ -10,6 +10,7 @@ def initialize opts = {} @class_name = opts.delete(:class_name) if opts.present? @name = opts.delete(:name).to_s @default = opts.delete(:default) + @default_proc = opts.delete(:default_proc) @default = @default.clone if @default && CANT_CLONE.none? { |klass| @default.is_a? klass } @value = @default if @default warn 'There are some unprocessed options!' if opts.present? @@ -32,7 +33,9 @@ def array_value end def hash_value - @value.to_h + @value.to_h.tap do |h| + h.default_proc = @default_proc if @default_proc + end end def string_value @@ -71,6 +74,10 @@ def boolean? self_klass == TrueClass || self_klass == FalseClass end + def default_proc? + @default_proc.present? + end + private def truthy_value? @value =~ /true/ || @value === true diff --git a/test/document_test.rb b/test/document_test.rb index f1c9cfe..be4134e 100644 --- a/test/document_test.rb +++ b/test/document_test.rb @@ -53,6 +53,10 @@ class Bar < FooBar property :a, :b end +class DefaultProcDoc < Dolly::Document + property :foo, class_name: Hash, default: {}, default_proc: Proc.new { |h,k| h[k] = Hash.new &h.default_proc } +end + class DocumentTest < ActiveSupport::TestCase DB_BASE_PATH = "http://localhost:5984/test".freeze @@ -498,6 +502,12 @@ def setup assert_equal 1, bar.a end + test "hash properties can have a default proc" do + doc = DefaultProcDoc.new + doc.foo['a']['b']['c'] = 'd' + assert_equal 'd', doc.foo['a']['b']['c'] + end + private def generic_response rows, count = 1 {total_rows: count, offset:0, rows: rows} From fc2a0d35a2475fe43650a10e0efffe4c0f847669 Mon Sep 17 00:00:00 2001 From: seancookr Date: Fri, 28 Jul 2017 09:50:17 -0700 Subject: [PATCH 2/4] add procable method --- lib/dolly/document.rb | 2 +- lib/dolly/property.rb | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/dolly/document.rb b/lib/dolly/document.rb index d9f837b..f3eb66d 100644 --- a/lib/dolly/document.rb +++ b/lib/dolly/document.rb @@ -189,7 +189,7 @@ 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.default - property_value.default_proc = property.default_proc if property.default_proc? && property.default.is_a?(Hash) + property_value.default_proc = property.default_proc if property.procable? self.doc[property.name] ||= property_value end end diff --git a/lib/dolly/property.rb b/lib/dolly/property.rb index ac41394..6083b50 100644 --- a/lib/dolly/property.rb +++ b/lib/dolly/property.rb @@ -74,11 +74,16 @@ def boolean? self_klass == TrueClass || self_klass == FalseClass end + def procable? + default_proc? && default.is_a?(Hash) + end + + private + def default_proc? @default_proc.present? end - private def truthy_value? @value =~ /true/ || @value === true end From 0c27368f7813310d177a9ba188b6b7e861670785 Mon Sep 17 00:00:00 2001 From: seancookr Date: Fri, 28 Jul 2017 10:28:19 -0700 Subject: [PATCH 3/4] check class name --- lib/dolly/property.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/dolly/property.rb b/lib/dolly/property.rb index 6083b50..bf6fa58 100644 --- a/lib/dolly/property.rb +++ b/lib/dolly/property.rb @@ -75,7 +75,7 @@ def boolean? end def procable? - default_proc? && default.is_a?(Hash) + default_proc? && (default.is_a?(Hash) || class_name == Hash) end private From 8c87acca11850eb6071fa6c5d12ffcf0e004f600 Mon Sep 17 00:00:00 2001 From: seancookr Date: Fri, 28 Jul 2017 11:12:45 -0700 Subject: [PATCH 4/4] test for save --- test/document_test.rb | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/test/document_test.rb b/test/document_test.rb index be4134e..c6e6e3c 100644 --- a/test/document_test.rb +++ b/test/document_test.rb @@ -508,6 +508,23 @@ def setup assert_equal 'd', doc.foo['a']['b']['c'] end + test "hash properties have their default proc reappliced after a query" do + assert _doc_id = "default_proc_doc/5623c56d-1c12-4f75-9202-93da5925177a" + assert save_response = {ok: true, id: _doc_id, rev: "1"} + assert FakeWeb.register_uri :put, /http:\/\/localhost:5984\/test\/default_proc_doc%2F.+/, body: save_response.to_json + assert doc = DefaultProcDoc.new + assert doc.doc['_id'] = _doc_id + assert doc.foo['a']['b']['c'] = 'd' + assert doc.save + expected_doc = doc.doc + assert FakeWeb.register_uri :get, "#{query_base_path}?keys=%5B%22default_proc_doc%2F5623c56d-1c12-4f75-9202-93da5925177a%22%5D&include_docs=true", + body: build_view_response([expected_doc]).to_json + assert doc.reload + assert_equal 'd', doc.foo['a']['b']['c'] + assert doc.foo['a']['b']['d']['e'] = 'f' + assert_equal 'f', doc.foo['a']['b']['d']['e'] + end + private def generic_response rows, count = 1 {total_rows: count, offset:0, rows: rows}