From 7cb3d109d7f4331a149c709d82696cf0dc1b2d27 Mon Sep 17 00:00:00 2001 From: Ian White Date: Wed, 25 Aug 2010 17:34:39 +0100 Subject: [PATCH] implementing attribute conversion (not yet feature-complete, some missing specs) --- lib/pickle/session/conversion.rb | 42 ++++++++++++- spec/pickle/session/conversion_spec.rb | 84 +++++++++++++++++++++++--- 2 files changed, 117 insertions(+), 9 deletions(-) diff --git a/lib/pickle/session/conversion.rb b/lib/pickle/session/conversion.rb index f83ad9c5..cd79ec71 100644 --- a/lib/pickle/session/conversion.rb +++ b/lib/pickle/session/conversion.rb @@ -1,6 +1,9 @@ module Pickle module Session + # included into Pickle::Session module Conversion + include Pickle::Parser::Matchers + # convert a string, hash, or ref into a Pickle::Ref, using config def ref(pickle_ref) case pickle_ref @@ -9,10 +12,45 @@ def ref(pickle_ref) else Pickle::Ref.new(pickle_ref, :config => config) end end - + # convert a pickle fields string, or hash, into a hash that is suitable for adapters def attributes(fields) - fields + if fields.blank? + {} + elsif fields.is_a?(Hash) + fields.each do |key, value| + begin + fields[key] = retrieve(value) + rescue Pickle::UnknownModelError, Pickle::InvalidPickleRefError + end + end + elsif fields.is_a?(String) + attrs = {} + fields.scan(match_field) do |field| + key, value = field.split(':', 2) + value.strip! + + model = begin + retrieve(value) + rescue Pickle::UnknownModelError, Pickle::InvalidPickleRefError + end + + if model + value = model + else + value = case value + when /^"(.*)"$/ then $1 + when /^'(.*)'$/ then $1 + when /^(#{match_value})$/ then eval($1) + else + raise UnknownFieldsFormatError, "#{field.inspect} is in an unknown format" + end + end + + attrs[key] = value + end + attrs + end end end end diff --git a/spec/pickle/session/conversion_spec.rb b/spec/pickle/session/conversion_spec.rb index 877ae31b..69658491 100644 --- a/spec/pickle/session/conversion_spec.rb +++ b/spec/pickle/session/conversion_spec.rb @@ -2,23 +2,93 @@ describe Pickle::Session::Conversion do include Pickle::Session::Conversion - + describe "#ref" do - it " creates a new pickle ref using the hash, and my config" do + it "() creates a new pickle ref using the hash, and my config" do stub!(:config).and_return(mock) Pickle::Ref.should_receive(:new).with({:foo => :bar, :config => config}).and_return(pickle_ref = mock) ref({:foo => :bar}).should == pickle_ref end - - it " creates a new pickle ref using the string, and my config" do + + it "() creates a new pickle ref using the string, and my config" do stub!(:config).and_return(mock) Pickle::Ref.should_receive(:new).with('foo bar', {:config => config}).and_return(pickle_ref = mock) ref('foo bar').should == pickle_ref end - - it " just returns the pickle_ref" do + + it "() just returns the pickle_ref" do pickle_ref = Pickle::Ref.new('factory') ref(pickle_ref).should == pickle_ref end end -end + + describe "#attributes" do + before do + stub!(:config).and_return(Pickle::Config.new) + end + + describe "given blank? argument" do + ['', [], {}, nil, false].each do |arg| + it "(#{arg.inspect}) should return {}" do + attributes(arg).should == {} + end + end + end + + describe "given a hash" do + describe "containing a pickle_ref as a value" do + let(:do_attributes) { attributes(:name => "Foo", :user => 'a user')} + let(:model) { mock } + + it "should return a hash containing the retrieved object in place of the pickle ref, and leave other values alone" do + should_receive(:retrieve).with('a user').and_return(model) + should_receive(:retrieve).with(anything).and_raise(Pickle::UnknownModelError) + do_attributes.should == {:name => "Foo", :user => model} + end + end + end + + describe "given a string" do + describe "for example: 'name: \"Fred\", age: 23, married: false, address: nil'" do + before(:each) do + stub!(:retrieve).and_raise(Pickle::UnknownModelError) + end + let(:do_attributes) { attributes(%q{name: "Fred", description: ' Fred: a great man. He is what? He is: great ', age: 23, height: 1.95, married: false, address: nil}) } + subject { do_attributes } + + it { should include('name' => "Fred") } + it { should include('description' => ' Fred: a great man. He is what? He is: great ')} + it { should include('age' => 23) } + it { should include('height' => 1.95) } + it { should include('married' => false) } + it { should include('address' => nil) } + end + + specify "when field is a pickle-ref which refers attributes should contain it" do + fred = mock + should_receive(:retrieve).with('the user "Fred"').and_return fred + attributes(%q(user: the user "Fred")).should == {'user' => fred} + end + + # describe "and a user Fred has been stored in pickle" do + # describe 'the user "Fred"' do + # it {should == fred} + # end + # + # describe '"Fred"' do + # it {should == fred} + # end + # end + # + # describe "and a user Fred has not been stored in pickle" do + # describe 'the user "Fred"' do + # it {should == fred} + # end + # + # describe '"Fred"' do + # it {should == "Fred"} + # end + # end + end + end +end \ No newline at end of file