From: Michal Fojtik <[email protected]> This addition will make possible to specify the 'required => true' option for all attributes in CIMI models, like:
class Machine < Base text :name, :required => true end To run a check if the instance of Machine is valid or not you can do following: Machine.from_xml(xml_body).validate! This method will raise the CIMI::Model::ValidationError exception if attribute marked as 'required' have no value set. Signed-off-by: Michal fojtik <[email protected]> --- server/lib/cimi/models/base.rb | 26 ++++++++++++++++++++++++++ server/lib/cimi/models/resource.rb | 4 ++++ server/lib/cimi/models/schema.rb | 22 ++++++++++++++++++++-- 3 files changed, 50 insertions(+), 2 deletions(-) diff --git a/server/lib/cimi/models/base.rb b/server/lib/cimi/models/base.rb index a96909f..1f519dc 100644 --- a/server/lib/cimi/models/base.rb +++ b/server/lib/cimi/models/base.rb @@ -78,6 +78,24 @@ require_relative '../helpers/database_helper' module CIMI::Model + class ValidationError < StandardError + + def initialize(attribute) + @attr_name = attribute + super("Required attribute '#{@attr_name}' must be set.") + end + + # Report the ValidationError as HTTP 400 - Bad Request + def code + 400 + end + + def name + @attr_name + end + + end + class Base < Resource # Extend the base model with database methods @@ -123,6 +141,14 @@ module CIMI::Model self end + def validate!(format=:xml) + self.class.required_attributes.each do |attr| + unless attr.valid?(send(attr.name)) + raise CIMI::Model::ValidationError.new(attr.send("#{format}_name")) + end + end + end + # FIXME: Kludge around the fact that we do not have proper *Create # objects that deserialize properties by themselves def extract_properties!(data) diff --git a/server/lib/cimi/models/resource.rb b/server/lib/cimi/models/resource.rb index 3271c5e..d7eceec 100644 --- a/server/lib/cimi/models/resource.rb +++ b/server/lib/cimi/models/resource.rb @@ -145,6 +145,10 @@ module CIMI xml["resourceURI"] = resource_uri XmlSimple.xml_out(xml, :root_name => xml_tag_name) end + + def required_attributes + @schema.required_attributes + end end # END of class methods diff --git a/server/lib/cimi/models/schema.rb b/server/lib/cimi/models/schema.rb index 5a5d2c9..7260b81 100644 --- a/server/lib/cimi/models/schema.rb +++ b/server/lib/cimi/models/schema.rb @@ -24,11 +24,13 @@ class CIMI::Model::Schema # class Attribute attr_reader :name, :xml_name, :json_name + attr_reader :required def initialize(name, opts = {}) @name = name @xml_name = opts[:xml_name] || name.to_s.camelize(true) @json_name = opts[:json_name] || name.to_s.camelize(true) + @required = opts[:required] || false end def from_xml(xml, model) @@ -50,6 +52,14 @@ class CIMI::Model::Schema def convert(value) value end + + def required? + @required + end + + def valid?(value) + !value.nil? and !value.empty? + end end class Scalar < Attribute @@ -122,7 +132,7 @@ class CIMI::Model::Schema else @schema = CIMI::Model::Schema.new @schema.instance_eval(&block) if block_given? - @schema.scalar(content, :text => :direct) if content + @schema.scalar(content, :text => :direct, :required => opts[:required]) if content end end @@ -178,6 +188,10 @@ class CIMI::Model::Schema end end + def valid?(value) + @schema.required_attributes.any? { |a| a.valid?(value.send(a.name) )} + end + private def struct if @klass @@ -369,6 +383,10 @@ class CIMI::Model::Schema @attributes.map { |a| a.name } end + def required_attributes + @attributes.select { |a| a.required? } + end + # # The DSL # @@ -387,7 +405,7 @@ class CIMI::Model::Schema def href(*args) opts = args.extract_opts! - args.each { |arg| struct(arg, opts) { scalar :href } } + args.each { |arg| struct(arg, opts) { scalar :href, :required => opts[:required] } } end def text(*args) -- 1.8.1.2
