class VersionOne::Asset
Constants
- ASSET_FORM_MAP
- ASSET_TYPE_MAP
Attributes
attributes[R]
href[R]
meta[R]
type[R]
Public Class Methods
from_xml(xml)
click to toggle source
# File lib/version-one/asset.rb, line 237 def self.from_xml(xml) meta = nil case xml.name when 'Asset' Asset.new(xml: xml) when 'Assets', 'History' xml.find('Asset').map do |el| a = Asset.new(xml: el, meta: meta) meta ||= a.meta a end else raise "XML element #{xml.name} cannot be converted to an asset" end end
get(id_or_href, *fields)
click to toggle source
# File lib/version-one/asset.rb, line 253 def self.get(id_or_href, *fields) client = VersionOne::Client.new if id_or_href =~ /^[A-Za-z]+:\d+$/ xml = client.get "/rest.v1/Data/#{id_or_href.sub(':', '/')}", *fields else xml = client.get id_or_href, *fields end Asset.from_xml(xml) end
new(options={})
click to toggle source
# File lib/version-one/asset.rb, line 23 def initialize(options={}) raise ArgumentError unless options.is_a?(Hash) xml = options.delete(:xml) @type = options.delete(:type) @initialized = false @href = nil if xml xml = xml.root if xml.is_a?(XML::Document) @id = normalized_id(xml.attributes['id']) @href = normalized_href(xml.attributes['href']) unless @type @type = xml.find_first('Attribute[@name="AssetType"]') @type = @type.content end else @id = normalized_id(options[:id]) if options[:id] end class_name = self.class.name.split('::').last if class_name != 'Asset' @type ||= class_name raise ArgumentError, "Incompatible class #{class_name} for asset type #{@type}" unless @type == class_name end case @type when String, Symbol @type = @type.to_s when NilClass raise ArgumentError, 'No asset type specified' unless @type else raise ArgumentError, "Invalid asset type argument: #{@type.inspect}" end @meta = options[:meta] @meta ||= options[:meta_cache][@type] if options.key?(:meta_cache) @meta ||= Meta.get(@type) @attributes = {} @changed_attributes = {} @setters = {} @meta.attributes.each do |a| simple_type = ASSET_TYPE_MAP[a.type] if simple_type add_simple_attribute(a, simple_type) elsif a.type == :relation add_relation_attribute(a) else add_simple_attribute(a, String) end end if xml xml.each {|el| init_attribute_value(el) } @changed_attributes.clear else options.each do |name,val| send("#{name}=", val) end end @initialized = true self end
reply_to(asset, msg)
click to toggle source
# File lib/version-one/asset.rb, line 167 def self.reply_to(asset, msg) asset_id = case asset when Asset asset.id when String asset else raise ArgumentError, 'Invalid asset argument' end raise ArgumentError, 'Cannot reply to this asset type' unless asset_id.match(/^Expression\:\d+$/) reply = VersionOne::Expression.new( content: msg, in_reply_to: AssetRef.new(id: asset_id) ) reply.save! end
Public Instance Methods
add_comment(msg)
click to toggle source
# File lib/version-one/asset.rb, line 147 def add_comment(msg) raise 'Cannot comment on an unsaved asset' if new_record? conversation = VersionOne::Asset.new(type: 'Conversation') conversation.save! expression = VersionOne::Asset.new(type: 'Expression') expression.content = msg expression.belongs_to = conversation expression.mentions = [self] expression.save! rescue conversation.delete if conversation raise end
comments(options={})
click to toggle source
# File lib/version-one/asset.rb, line 187 def comments(options={}) deep = options.key?(:deep) ? options[:deep] : true query = VersionOne::Query.new('Expression').select(*%w{Author.Name Author.Email AuthoredAt Mentions InReplyTo Replies Content}) where = "Mentions='#{self.id}'" if deep where = "(#{where})|(InReplyTo.Mentions='#{self.id}')" end results = query.where(where).all # Move reply information to the corresponding # parent conversation if deep comments_by_id = results.index_by(&:id) replies = results.select{|c| c.in_reply_to && comments_by_id.key?(c.in_reply_to.id)} replies_by_id = replies.index_by(&:id) results.map do |c| if replies_by_id.key?(c.id) nil elsif c.replies.nil? c else c.replies.each do |ref| reply = replies_by_id[ref.id] ref.set(reply) if reply end c end end results.compact! end results end
delete(options={})
click to toggle source
# File lib/version-one/asset.rb, line 139 def delete(options={}) delete! rescue false end
delete!(options={})
click to toggle source
# File lib/version-one/asset.rb, line 135 def delete!(options={}) exec('Delete', options) unless new_record? end
display_url()
click to toggle source
# File lib/version-one/asset.rb, line 103 def display_url unless @display_url uri = service_uri.dup uri.path = File.join(uri.path, "#{ASSET_FORM_MAP[@type] || @type}.mvc/Summary") uri.query = URI.encode_www_form('oidToken' => self.id) @display_url = uri.to_s end @display_url end
exec(op_name, options={})
click to toggle source
# File lib/version-one/asset.rb, line 226 def exec(op_name, options={}) client = options[:client] || VersionOne::Client.new client.post(href, {op: op_name}) end
get_history(fields=nil)
click to toggle source
# File lib/version-one/asset.rb, line 231 def get_history(fields=nil) path = href.sub(/\/[Dd]ata\//, '/Hist/') client = VersionOne::Client.new Asset.from_xml(client.get(path, fields)) end
id()
click to toggle source
# File lib/version-one/asset.rb, line 90 def id @id end
inspect()
click to toggle source
# File lib/version-one/asset.rb, line 117 def inspect "<Asset:#{@id || @type || '???'}>" end
new_record?()
click to toggle source
# File lib/version-one/asset.rb, line 143 def new_record? @href.nil? end
ref()
click to toggle source
# File lib/version-one/asset.rb, line 113 def ref AssertRef.for(self) end
reload(*fields)
click to toggle source
# File lib/version-one/asset.rb, line 263 def reload(*fields) Asset.get(self.href, *fields) end
reply(msg)
click to toggle source
# File lib/version-one/asset.rb, line 163 def reply(msg) self.class.reply_to(self, msg) end
save(options={})
click to toggle source
# File lib/version-one/asset.rb, line 121 def save(options={}) save!(options) rescue false end
save!(options={})
click to toggle source
# File lib/version-one/asset.rb, line 125 def save!(options={}) xml = change_xml client = options[:client] || VersionOne::Client.new response_xml = client.post_xml(save_url, xml) @href ||= normalized_href(response_xml.attributes['href']) @id ||= normalized_id(response_xml.attributes['id']) @changed_attributes.clear self end
url()
click to toggle source
# File lib/version-one/asset.rb, line 94 def url unless @url uri = service_uri.dup uri.path = href @url = uri.to_s end @url end
Private Instance Methods
add_generic_attribute(attr_name, options={})
click to toggle source
# File lib/version-one/asset.rb, line 309 def add_generic_attribute(attr_name, options={}) if attr_name.is_a?(VersionOne::AttributeDefinition) a = attr_name attr_name = a.name options = { readonly: a.readonly?, multivalue: a.multivalue? } end clean_name = attr_name.gsub(/:[^\.]+/, '').gsub('.', '_') ruby_name = clean_name.gsub(/([a-z])([A-Z])/){|m| $1 + '_' + $2 }.downcase readonly = !!options[:readonly] set_script = %{ def #{ruby_name}=(val) raise "Can't set read-only property" if #{readonly.to_s} && @initialized #{yield(attr_name, options)} @attributes['#{attr_name}'] = val @changed_attributes['#{attr_name}'] = true val end } get_script = %{ def #{ruby_name} @attributes['#{attr_name}'] end def #{ruby_name}? !!#{ruby_name} end def #{ruby_name}_definition @meta.attributes['#{attr_name}'] end } instance_eval(get_script) instance_eval(set_script) @setters[attr_name] = "#{ruby_name}=" end
add_relation_attribute(a, opts={})
click to toggle source
# File lib/version-one/asset.rb, line 385 def add_relation_attribute(a, opts={}) add_generic_attribute(a, opts) do |attr_name, options| script = %{ val = case val } if options[:multivalue] script << %{ when Asset, AssetRef, Array, NilClass rel = @attributes['#{attr_name}'] || RelationMultiValue.new rel.set(val) else raise ArgumentError, "Invalid argument type: %s" % [val.class.name] end } else script << %{ when NilClass val when Array raise ArgumentError.new("Too many values for single value attribute") if val.size > 1 val[0] when Asset, AssetRef val else raise ArgumentError, "Invalid argument type: %s" % [val.class.name] end val = AssetRef.for(val) if val } end script end end
add_simple_attribute(_attr_name, native_type, _options={})
click to toggle source
# File lib/version-one/asset.rb, line 354 def add_simple_attribute(_attr_name, native_type, _options={}) add_generic_attribute(_attr_name, _options) do |attr_name, options| convert = "convert_to_#{native_type}" if options[:multivalue] setter = %{ val = case val when NilClass val when Array val.map{|v| #{convert}('#{attr_name}',v) } else [#{convert}('#{attr_name}',val)] end } else setter = %{ val = case val when NilClass val else #{convert}('#{attr_name}',val) end } end setter end end
change_xml()
click to toggle source
# File lib/version-one/asset.rb, line 442 def change_xml asset = XML::Node.new('Asset') @changed_attributes.each_key do |a| attr_def = meta[a] child = nil val = @attributes[a] if attr_def.relation? child = XML::Node.new('Relation') case when val.nil? when attr_def.multivalue? val.added.each do |v| v = v.to_xml v.attributes['act'] = 'add' child << v end val.removed.each do |v| v = v.to_xml v.attributes['act'] = 'remove' child << v end else child << val.to_xml end else child = XML::Node.new('Attribute') case when val.nil? #noop when attr_def.multivalue? val.each do |v| child << XML::Node.new('Value', v.to_s) end else child.content = val.to_s end end child.attributes['name'] = a child.attributes['act'] = 'set' unless (attr_def.relation? && attr_def.multivalue?) asset << child end asset end
convert_to_Float(name, val)
click to toggle source
# File lib/version-one/asset.rb, line 430 def convert_to_Float(name, val) Float(val) end
convert_to_Integer(name, val)
click to toggle source
# File lib/version-one/asset.rb, line 418 def convert_to_Integer(name, val) val.to_i end
convert_to_String(name, val)
click to toggle source
# File lib/version-one/asset.rb, line 422 def convert_to_String(name, val) val.to_s end
convert_to_Time(name, val)
click to toggle source
# File lib/version-one/asset.rb, line 426 def convert_to_Time(name, val) VersionOne.s_to_time(val, utc: !!(name.match(/utc$/i))) end
init_attribute_value(el)
click to toggle source
# File lib/version-one/asset.rb, line 273 def init_attribute_value(el) attr_name = el.attributes['name'] # If no children (text or elements) then treat as nil value # If has Value or Asset children then default to multivalue array is_nil = el.children.size == 0 val = nil if is_nil children = is_nil ? [] : el.find('Value|Asset').to_a is_multivalue = children.size > 0 case el.name when 'Attribute' val = is_multivalue ? children.map(&:content) : el.content unless is_nil if @setters[attr_name] send(@setters[attr_name], val) else add_simple_attribute(attr_name, String, readonly: true, multivalue: is_multivalue) @attributes[attr_name] = val end when 'Relation' val = children.map{|v| AssetRef.new(v)} unless is_nil unless @setters[attr_name] add_relation_attribute(attr_name, readonly: true, multivalue: is_multivalue) end send(@setters[attr_name], val) @attributes[attr_name].unchanged! if @attributes[attr_name].respond_to?(:unchanged!) else # Ignore end end
normalized_href(s)
click to toggle source
Remove the moment from the href if any
# File lib/version-one/asset.rb, line 491 def normalized_href(s) if s =~ /(\/.+\/[A-Z][a-zA-Z]+\/\d+)(\/\d+)?$/ $1 else raise ArgumentError, "Invalid href '#{s}'" end end
normalized_id(s)
click to toggle source
Remove the moment from the ID if any
# File lib/version-one/asset.rb, line 500 def normalized_id(s) if s =~ /^([A-Z][a-zA-Z]+:\d+)(:\d+)?$/ $1 else raise ArgumentError, "Invalid ID '#{s}'" end end
save_url()
click to toggle source
# File lib/version-one/asset.rb, line 434 def save_url if @href @href else "rest-1.v1/Data/#{@type}" end end
service_uri()
click to toggle source
# File lib/version-one/asset.rb, line 269 def service_uri VersionOne::Client.service_uri end