From: David Lutterkort <lut...@redhat.com> It's now possible to say
array :things, :ref => CIMI::Model::Target to have an array things where each entry is a TargetRef Fixes https://issues.apache.org/jira/browse/DTACLOUD-499 --- server/lib/cimi/models/base.rb | 19 +++++++++++++---- server/lib/cimi/models/schema.rb | 9 ++++++++- server/tests/cimi/model/schema_spec.rb | 37 ++++++++++++++++++++++++++++++++++ 3 files changed, 60 insertions(+), 5 deletions(-) diff --git a/server/lib/cimi/models/base.rb b/server/lib/cimi/models/base.rb index 12105f2..e8c1104 100644 --- a/server/lib/cimi/models/base.rb +++ b/server/lib/cimi/models/base.rb @@ -28,12 +28,22 @@ require_relative '../helpers/database_helper' # # class Machine < CIMI::Model::Base # text :status -# href :meter +# collection :meters # array :volumes do # scalar :href, :initial_location # end +# ref :latest_snapshot, CIMI::Model::MachineImage # end # +# class SystemTemplate < CIMI::Model::Base +# array component_descriptors do +# text :name +# ... +# end +# array :meter_templates, :ref => CIMI::Model::MeterTemplate +# end +# +# # The DSL automatically takes care of converting identifiers from their # underscored form to the camel-cased form used by CIMI. The above class # can be used in the following way: @@ -69,9 +79,10 @@ require_relative '../helpers/database_helper' # A structured subobject; the block defines the schema of the # subobject. The +:content+ option can be used to specify the attribute # that should receive the content of the corresponding XML element -# [array(name, opts, &block)] -# An array of structured subobjects; the block defines the schema of -# the subobjects. +# [array(name, opts, &block)] An array of structured subobjects; the +# block defines the schema of the subobjects. If the entries are +# references to other resources, instead of passing a block, pass the +# class of the target of the references with the +:ref+ option # [collection(name, opts)] # A collection of associated objects; use the +:class+ option to # specify the type of the collection entries diff --git a/server/lib/cimi/models/schema.rb b/server/lib/cimi/models/schema.rb index 53868a7..4ce16b9 100644 --- a/server/lib/cimi/models/schema.rb +++ b/server/lib/cimi/models/schema.rb @@ -233,8 +233,15 @@ class CIMI::Model::Schema unless opts[:xml_name] opts[:xml_name] = name.to_s.singularize.camelize.uncapitalize end + if opts[:ref] && block_given? + raise "Provide only one of :ref or a block" + end super(name, opts) - @struct = Struct.new(name, opts, &block) + if opts[:ref] + @struct = Ref.new(name, :class=> opts[:ref]) + else + @struct = Struct.new(name, opts, &block) + end end def from_xml(xml, model) diff --git a/server/tests/cimi/model/schema_spec.rb b/server/tests/cimi/model/schema_spec.rb index 97b1cee..0be5d01 100644 --- a/server/tests/cimi/model/schema_spec.rb +++ b/server/tests/cimi/model/schema_spec.rb @@ -232,6 +232,43 @@ describe "Schema" do @schema.to_xml(obj).must_equal sample_xml end + describe "of references" do + class RefTarget < CIMI::Model::Base + text :name + end + + class RefArray < CIMI::Model::Base + array :things, :ref => RefTarget + end + + before do + @json = { "things" => + [ { "name" => "first", "href" => "/things/1" }, + { "name" => "second", "href" => "/things/2" }, + { "href" => "/things/3" } ]}.to_json + end + + it "should convert from JSON" do + model = RefArray.from_json(@json) + check_model(model) + end + + it "should convert from XML" do + xml = RefArray.from_json(@json).to_xml + model = RefArray.from_xml(xml) + check_model(model) + end + + def check_model(model) + model.things.size.must_equal 3 + model.things.first.must_respond_to :name + model.things.first.href.must_equal "/things/1" + model.things.first.name.must_equal "first" + model.things.last.name.must_be_nil + model.things.last.href.must_equal "/things/3" + end + end + def check_structs(obj) obj.wont_be_nil obj[:structs].size.must_equal 2 -- 1.8.1.2