require File.expand_path(File.dirname(__FILE__) + '/spec_helper') describe "A class that includes JsonAttributes::Mixin" do context "(readers)" do it "should allow the ability to specify attr_readers that are included in the json report" do reader_test_class = Class.new do include JsonAttributes::Mixin json_reader :foo, :bar def initialize @foo = "food" @bar = "bard" end end test = reader_test_class.new test.foo.should == "food" test.bar.should == "bard" test.report_to_json.should == JSON.unparse({:foo => "food", :bar => "bard"}) end end context "(writers)" do it "should allow the ability to specify attr_writers that can be updated from json" do writer_test_class = Class.new do include JsonAttributes::Mixin json_writer :foo, :bar attr_reader :foo, :bar def initialize @foo = "food" @bar = "bard" end end test = writer_test_class.new test.foo.should == "food" test.bar.should == "bard" test.update_from_json(JSON.unparse({:foo => "foof", :bar => "barf"})) test.foo.should == "foof" test.bar.should == "barf" test.update_from_json(JSON.unparse({:foo => "fool"})) test.foo.should == "fool" test.bar.should == "barf" lambda{test.foo = "foo"}.should_not raise_error lambda{test.bar = "bar"}.should_not raise_error end it "should ignore irrelevant items when updating" do writer_test_class = Class.new do include JsonAttributes::Mixin json_writer :foo def initialize @foo = "food" end end test = writer_test_class.new lambda{test.update_from_json(JSON.unparse({:foo => "foof", :bar => "barf"}))}.should_not raise_error end it "should not allow readers to be updated" do writer_test_class = Class.new do include JsonAttributes::Mixin json_reader :foo def initialize @foo = "food" end end test = writer_test_class.new test.update_from_json(JSON.unparse({:foo => "foof"})) test.foo.should == "food" end it "should complain about a non hash-like top-level node when updating" do test_class = Class.new do include JsonAttributes::Mixin end test = test_class.new lambda{test.update_from_json(JSON.unparse([:foo, "foof"]))}.should raise_error end end context "(accessors)" do it "should allow the ability to specify readable and writable accessors" do accessor_test_class = Class.new do include JsonAttributes::Mixin json_accessor :foo, :bar def initialize @foo = "food" @bar = "bard" end end test = accessor_test_class.new test.foo = "fool" test.foo.should == "fool" test.update_from_json(JSON.unparse({:foo => "foof"})) test.report_to_json.should == JSON.unparse({:foo => "foof", :bar => "bard"}) end end context "(creator)" do it "should provide a create_from_json method that expects ALL of the give json writers" do creator_test_class = Class.new do include JsonAttributes::Mixin json_writer :foo, :bar attr_reader :foo, :bar def initialize @foo = "food" @bar = "bard" end end test = creator_test_class.new lambda{test.create_from_json(JSON.unparse({:foo => "foof"}))}.should raise_error test.foo.should == "food" test.create_from_json(JSON.unparse({:foo => "foof", :bar => "barf"})) test.foo.should == "foof" test.bar.should == "barf" end end context "(conditioning parsed json)" do before(:each) do @conditioning_test_class = Class.new do include JsonAttributes::Mixin json_writer :foo attr_reader :foo json_conditioner :call_me_first, :call_me_after def initialize @foo = "food" end end end context "during update" do it "should allow the parsed json to be conditioned in a controller way" do test = @conditioning_test_class.new test.should_receive(:call_me_first).with({:foo => "foof"}).and_return({:foo => "fool"}) test.should_receive(:call_me_after).with({:foo => "fool"}).and_return({:foo => "foot"}) test.update_from_json(JSON.unparse({:foo => "foof"})) test.foo.should == "foot" end end context "during create" do it "should allow the parsed json to be conditioned in a controller way" do test = @conditioning_test_class.new test.should_receive(:call_me_first).with({:foo => "foof"}).and_return({:foo => "fool"}) test.should_receive(:call_me_after).with({:foo => "fool"}).and_return({:foo => "foot"}) test.create_from_json(JSON.unparse({:foo => "foof"})) test.foo.should == "foot" end end end context "(validating parsed json)" do before(:each) do @validating_test_class = Class.new do include JsonAttributes::Mixin json_writer :foo attr_reader :foo json_conditioner :condition json_validator :validator_1, :validator_2 def initialize @foo = "food" end end end context "during update" do it "should not update the object if a validator rasies an error" do test = @validating_test_class.new test.should_receive(:condition).and_return({:foo => "fool"}) test.should_receive(:validator_1).with({:foo => "fool"}) test.should_receive(:validator_2).with({:foo => "fool"}).and_raise("Something did not validate") lambda{test.update_from_json(JSON.unparse({:foo => "foof"}))}.should raise_error("Something did not validate") test.foo.should == "food" test.should_receive(:condition).and_return({:foo => "fool"}) test.should_receive(:validator_1).with({:foo => "fool"}) test.should_receive(:validator_2).with({:foo => "fool"}) test.update_from_json(JSON.unparse({:foo => "foof"})) test.foo.should == "fool" end end context "during create" do it "should not update the object if a validator rasies an error" do test = @validating_test_class.new test.should_receive(:condition).and_return({:foo => "fool"}) test.should_receive(:validator_1).with({:foo => "fool"}) test.should_receive(:validator_2).with({:foo => "fool"}).and_raise("Something did not validate") lambda{test.create_from_json(JSON.unparse({:foo => "foof"}))}.should raise_error("Something did not validate") test.foo.should == "food" test.should_receive(:condition).and_return({:foo => "fool"}) test.should_receive(:validator_1).with({:foo => "fool"}) test.should_receive(:validator_2).with({:foo => "fool"}) test.create_from_json(JSON.unparse({:foo => "foof"})) test.foo.should == "fool" end end end end