Class: VersionOne::Asset

Inherits:
Object
  • Object
show all
Defined in:
lib/version-one/asset.rb

Direct Known Subclasses

Conversation, Defect, Expression, Request, Scope, Story, Task, Test

Constant Summary collapse

ASSET_TYPE_MAP =
{
    date:     Time,
    text:     String,
    numeric:  Float,
    rank:     Integer
}.freeze
ASSET_FORM_MAP =
{
    'Scope' => 'Project'
}

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ Asset

Returns a new instance of Asset.

Raises:

  • (ArgumentError)


23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# 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

Instance Attribute Details

#attributesObject (readonly)

Returns the value of attribute attributes.



18
19
20
# File 'lib/version-one/asset.rb', line 18

def attributes
  @attributes
end

#hrefObject (readonly)

Returns the value of attribute href.



18
19
20
# File 'lib/version-one/asset.rb', line 18

def href
  @href
end

#metaObject (readonly)

Returns the value of attribute meta.



18
19
20
# File 'lib/version-one/asset.rb', line 18

def meta
  @meta
end

#typeObject (readonly)

Returns the value of attribute type.



18
19
20
# File 'lib/version-one/asset.rb', line 18

def type
  @type
end

Class Method Details

.from_xml(xml) ⇒ Object



237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
# 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) ⇒ Object



253
254
255
256
257
258
259
260
261
# 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

.reply_to(asset, msg) ⇒ Object

Raises:

  • (ArgumentError)


167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
# 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

Instance Method Details

#add_comment(msg) ⇒ Object



147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# 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 = {}) ⇒ Object



187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
# 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 = {}) ⇒ Object



139
140
141
# File 'lib/version-one/asset.rb', line 139

def delete(options={})
  delete! rescue false
end

#delete!(options = {}) ⇒ Object



135
136
137
# File 'lib/version-one/asset.rb', line 135

def delete!(options={})
  exec('Delete', options) unless new_record?
end

#display_urlObject



103
104
105
106
107
108
109
110
111
# 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 = {}) ⇒ Object



226
227
228
229
# 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) ⇒ Object



231
232
233
234
235
# 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

#idObject



90
91
92
# File 'lib/version-one/asset.rb', line 90

def id
  @id
end

#inspectObject



117
118
119
# File 'lib/version-one/asset.rb', line 117

def inspect
  "<Asset:#{@id || @type || '???'}>"
end

#new_record?Boolean



143
144
145
# File 'lib/version-one/asset.rb', line 143

def new_record?
  @href.nil?
end

#refObject



113
114
115
# File 'lib/version-one/asset.rb', line 113

def ref
  AssertRef.for(self)
end

#reload(*fields) ⇒ Object



263
264
265
# File 'lib/version-one/asset.rb', line 263

def reload(*fields)
  Asset.get(self.href, *fields)
end

#reply(msg) ⇒ Object



163
164
165
# File 'lib/version-one/asset.rb', line 163

def reply(msg)
  self.class.reply_to(self, msg)
end

#save(options = {}) ⇒ Object



121
122
123
# File 'lib/version-one/asset.rb', line 121

def save(options={})
  save!(options) rescue false
end

#save!(options = {}) ⇒ Object



125
126
127
128
129
130
131
132
133
# 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

#urlObject



94
95
96
97
98
99
100
101
# 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