directed-edge 0.1.3 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.3
1
+ 0.2.0
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{directed-edge}
8
- s.version = "0.1.3"
8
+ s.version = "0.2.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Directed Edge"]
12
- s.date = %q{2010-04-09}
12
+ s.date = %q{2010-04-25}
13
13
  s.description = %q{Bindings for the Directed Edge webservices API}
14
14
  s.email = %q{info@directededge.com}
15
15
  s.extra_rdoc_files = [
data/lib/directed_edge.rb CHANGED
@@ -55,6 +55,22 @@ module DirectedEdge
55
55
  end
56
56
  end
57
57
 
58
+ class CollectionHash < Hash
59
+ def initialize(type)
60
+ @type = type
61
+ end
62
+ def [](key)
63
+ self[key] = @type.new unless include? key
64
+ super(key)
65
+ end
66
+ def each
67
+ super { |key, value| yield(key, value) unless value.empty? }
68
+ end
69
+ def empty?
70
+ each { |key, value| return false } ; true
71
+ end
72
+ end
73
+
58
74
  # Base class used for Database and Item that has some basic resource
59
75
  # grabbing functionality.
60
76
 
@@ -92,26 +108,6 @@ module DirectedEdge
92
108
  values
93
109
  end
94
110
 
95
- # Returns a hash of the elements from the document matching the given
96
- # element name. If the specified attribute is present, its value will
97
- # be assigned to the hash, otherwise the default value given will be
98
- # used.
99
-
100
- def hash_from_document(document, element, attribute, default=0)
101
- values = {}
102
- document.elements.each("//#{element}") do |v|
103
- value = v.attribute(attribute).to_s || default
104
- if value.empty?
105
- values[v.text] = default
106
- elsif value.to_i.to_s == value.to_s
107
- values[v.text] = value.to_i
108
- else
109
- values[v.text] = value.to_s
110
- end
111
- end
112
- values
113
- end
114
-
115
111
  # Normalizes the parameters in an argument hash to a standard form
116
112
  # so that they can be passed off to the web services API -- e.g.
117
113
  # :foo_bar to 'fooBar'
@@ -328,13 +324,13 @@ module DirectedEdge
328
324
  @database = database
329
325
 
330
326
  @id = id
331
- @links = {}
327
+ @links = CollectionHash.new(Hash)
332
328
  @tags = Set.new
333
329
  @preselected = []
334
330
  @blacklisted = Set.new
335
331
  @properties = {}
336
332
 
337
- @links_to_remove = Set.new
333
+ @links_to_remove = CollectionHash.new(Set)
338
334
  @tags_to_remove = Set.new
339
335
  @preselected_to_remove = Set.new
340
336
  @blacklisted_to_remove = Set.new
@@ -363,9 +359,13 @@ module DirectedEdge
363
359
 
364
360
  # Creates an item if it does not already exist in the database or overwrites
365
361
  # an existing item if one does.
362
+ #
363
+ # This has been deprecated as it's not set up to properly support link types.
364
+ # use new / save instead.
366
365
 
367
366
  def create(links={}, tags=Set.new, properties={})
368
- @links = links
367
+ warn 'DirectedEdge::Item::create has been deprecated. Use new / save instead.'
368
+ @links[''] = links
369
369
  @tags = tags
370
370
  @properties = properties
371
371
 
@@ -390,6 +390,8 @@ module DirectedEdge
390
390
 
391
391
  put(complete_document, 'add')
392
392
 
393
+ ### CHECKING LINKS_TO_REMOVE.EMPTY? ISN'T CORRECT ANYMORE
394
+
393
395
  if !@links_to_remove.empty? ||
394
396
  !@tags_to_remove.empty? ||
395
397
  !@preselected_to_remove.empty? ||
@@ -410,13 +412,11 @@ module DirectedEdge
410
412
  # will be discarded.
411
413
 
412
414
  def reload
413
- document = read_document
414
-
415
- @links = hash_from_document(document, 'link', 'weight')
416
- @tags = Set.new(list_from_document(document, 'tag'))
417
- @preselected = list_from_document(document, 'preselected')
418
- @blacklisted = Set.new(list_from_document(document, 'blacklisted'))
419
- @properties = {}
415
+ @links.clear
416
+ @tags.clear
417
+ @preselected.clear
418
+ @blacklisted.clear
419
+ @properties.clear
420
420
 
421
421
  @links_to_remove.clear
422
422
  @tags_to_remove.clear
@@ -424,17 +424,15 @@ module DirectedEdge
424
424
  @blacklisted_to_remove.clear
425
425
  @properties_to_remove.clear
426
426
 
427
- document.elements.each('//property') do |element|
428
- @properties[element.attribute('name').value] = element.text
429
- end
430
- @cached = true
427
+ @cached = false
428
+ read
431
429
  end
432
430
 
433
431
  # Returns a set of items that are linked to from this item.
434
432
 
435
- def links
433
+ def links(type='')
436
434
  read
437
- @links
435
+ @links[type.to_s]
438
436
  end
439
437
 
440
438
  # Returns a set containing all of this item's tags.
@@ -515,27 +513,27 @@ module DirectedEdge
515
513
  # item is saved. Otherwise the link will be ignored as the engine tries
516
514
  # to detect 'broken' links that do not terminate at a valid item.
517
515
 
518
- def link_to(other, weight=0)
516
+ def link_to(other, weight=0, type='')
519
517
  raise RangeError if (weight < 0 || weight > 10)
520
- @links_to_remove.delete(other)
521
- @links[other.to_s] = weight
518
+ @links_to_remove[type.to_s].delete(other)
519
+ @links[type.to_s][other.to_s] = weight
522
520
  end
523
521
 
524
522
  # Deletes a link from this item to other.
525
523
  #
526
524
  # The changes will not be reflected in the database until save is called.
527
525
 
528
- def unlink_from(other)
529
- @links_to_remove.add(other.to_s) unless @cached
530
- @links.delete(other.to_s)
526
+ def unlink_from(other, type='')
527
+ @links_to_remove[type.to_s].add(other.to_s) unless @cached
528
+ @links[type.to_s].delete(other.to_s)
531
529
  end
532
530
 
533
531
  # If there is a link for "other" then it returns the weight for the given
534
532
  # item. Zero indicates that no weight is assigned.
535
533
 
536
- def weight_for(other)
534
+ def weight_for(other, type='')
537
535
  read
538
- @links[other.to_s]
536
+ @links[type.to_s][other.to_s]
539
537
  end
540
538
 
541
539
  # Adds a tag to this item.
@@ -639,10 +637,18 @@ module DirectedEdge
639
637
  # already cached.
640
638
 
641
639
  def read
642
- if !@cached
640
+ unless @cached
643
641
  begin
644
642
  document = read_document
645
- @links.merge!(hash_from_document(document, 'link', 'weight'))
643
+
644
+ document.elements.each('//link') do |link_element|
645
+ type = link_element.attribute('type')
646
+ type = type ? type.to_s : ''
647
+ weight = link_element.attribute('weight').to_s.to_i
648
+ target = link_element.text
649
+ @links[type][target] = weight unless @links[type][target]
650
+ end
651
+
646
652
  @tags.merge(list_from_document(document, 'tag'))
647
653
  @preselected.concat(list_from_document(document, 'preselected'))
648
654
  @blacklisted.merge(list_from_document(document, 'blacklisted'))
@@ -652,7 +658,10 @@ module DirectedEdge
652
658
  @properties[name] = element.text unless @properties.has_key?(name)
653
659
  end
654
660
 
655
- @links_to_remove.each { |link| @links.delete(link) }
661
+ @links_to_remove.each do |type, links|
662
+ links.each { |link, weight| @links[type].delete(link) }
663
+ end
664
+
656
665
  @tags_to_remove.each { |tag| @tags.delete(tag) }
657
666
  @preselected_to_remove.each { |p| @preselected.delete(p) }
658
667
  @blacklisted_to_remove.each { |b| @blacklisted.delete(b) }
@@ -665,8 +674,8 @@ module DirectedEdge
665
674
  @properties_to_remove.clear
666
675
 
667
676
  @cached = true
668
- rescue
669
- puts "Couldn't read \"#{@id}\" from the database."
677
+ rescue => ex
678
+ puts "Couldn't read \"#{@id}\" from the database, #{ex}"
670
679
  end
671
680
  end
672
681
  end
@@ -689,7 +698,15 @@ module DirectedEdge
689
698
 
690
699
  def removal_document
691
700
  item = setup_document(REXML::Document.new)
692
- @links_to_remove.each { |link| item.add_element('link').add_text(link.to_s) }
701
+
702
+ @links_to_remove.each do |type, links|
703
+ links.each do |link|
704
+ element = item.add_element('link')
705
+ element.add_attribute(type) unless type.empty?
706
+ element.add_text(link.to_s)
707
+ end
708
+ end
709
+
693
710
  @tags_to_remove.each { |tag| item.add_element('tag').add_text(tag.to_s) }
694
711
  @preselected_to_remove.each { |p| item.add_element('preselected').add_text(p.to_s) }
695
712
  @blacklisted_to_remove.each { |b| item.add_element('blacklisted').add_text(b.to_s) }
@@ -701,10 +718,13 @@ module DirectedEdge
701
718
 
702
719
  def insert_item(document)
703
720
  item = setup_document(document)
704
- @links.each do |link, weight|
705
- element = item.add_element('link')
706
- element.add_attribute('weight', weight.to_s) if weight != 0
707
- element.add_text(link.to_s)
721
+ @links.each do |type, links|
722
+ links.each do |link, weight|
723
+ element = item.add_element('link')
724
+ element.add_attribute('type', type) unless type.empty?
725
+ element.add_attribute('weight', weight.to_s) unless weight == 0
726
+ element.add_text(link.to_s)
727
+ end
708
728
  end
709
729
  @tags.each { |tag| item.add_element('tag').add_text(tag.to_s) }
710
730
  @preselected.each { |p| item.add_element('preselected').add_text(p.to_s) }
@@ -1,4 +1,5 @@
1
1
  require 'helper'
2
+ require 'pp'
2
3
 
3
4
  # Defines a multithreaded "each"
4
5
 
@@ -85,13 +86,17 @@ class TestDirectedEdge < Test::Unit::TestCase
85
86
 
86
87
  def test_items
87
88
  first_item = DirectedEdge::Item.new(@database, 'test_1')
88
- first_item.create
89
+ first_item.save
89
90
 
90
91
  second_item = DirectedEdge::Item.new(@database, 'test_2')
91
- second_item.create([first_item])
92
+ second_item.link_to(first_item)
93
+ second_item.save
92
94
 
93
95
  third_item = DirectedEdge::Item.new(@database, 'test_3')
94
- third_item.create([first_item, second_item], 'test_tag')
96
+ third_item.link_to(first_item)
97
+ third_item.link_to(second_item)
98
+ third_item.add_tag('test_tag')
99
+ third_item.save
95
100
 
96
101
  assert_equal('test_1', first_item.name)
97
102
 
@@ -115,8 +120,8 @@ class TestDirectedEdge < Test::Unit::TestCase
115
120
  # Make sure that the third item is linked to both the first and second items
116
121
 
117
122
  assert_equal(2, third_item.links.length)
118
- assert(third_item.links.include?(first_item))
119
- assert(third_item.links.include?(second_item))
123
+ assert(third_item.links.include?(first_item.to_s))
124
+ assert(third_item.links.include?(second_item.to_s))
120
125
 
121
126
  # Make sure that the first and second items show up in the related items for
122
127
  # the third item
@@ -230,13 +235,34 @@ class TestDirectedEdge < Test::Unit::TestCase
230
235
  assert(!item.properties.include?('test_property_1'))
231
236
  end
232
237
 
238
+ def test_link_types
239
+ first = DirectedEdge::Item.new(@database, 'item_1')
240
+ second = DirectedEdge::Item.new(@database, 'item_2')
241
+ first.save
242
+ second.save
243
+
244
+ first.link_to(second, 0, :test)
245
+ first.save
246
+
247
+ first = DirectedEdge::Item.new(@database, 'item_1')
248
+ second = DirectedEdge::Item.new(@database, 'item_2')
249
+
250
+ first.save
251
+ first.reload
252
+ second.reload
253
+
254
+ assert(first.links(:test).include?('item_2'))
255
+ assert(!first.links.include?('item_2'))
256
+ end
257
+
233
258
  def test_load
234
259
  return if ENV['NO_LOAD_TEST']
235
260
 
236
261
  def run_load_test(prefix, count)
237
262
  (1..count).concurrently do |i|
238
263
  item = DirectedEdge::Item.new(@database, "test_item_#{prefix}_#{i}")
239
- item.create([], ['test_tag'])
264
+ item.add_tag('test_tag')
265
+ item.save
240
266
  end
241
267
  (1..count).concurrently do |i|
242
268
  item = DirectedEdge::Item.new(@database, "test_item_#{prefix}_#{i}")
@@ -372,10 +398,10 @@ class TestDirectedEdge < Test::Unit::TestCase
372
398
 
373
399
  def test_blacklisted
374
400
  customer = DirectedEdge::Item.new(@database, 'customer1')
375
- first = customer.recommended.first
401
+ first = customer.recommended(['product']).first
376
402
  customer.add_blacklisted(first)
377
403
  customer.save
378
- assert_not_equal(customer.recommended.first, first)
404
+ assert(!customer.recommended(['product']).include?(first))
379
405
 
380
406
  assert(customer.blacklisted.include?(first))
381
407
  customer.reload
@@ -386,6 +412,6 @@ class TestDirectedEdge < Test::Unit::TestCase
386
412
  assert(!customer.blacklisted.include?(first))
387
413
  customer.reload
388
414
  assert(!customer.blacklisted.include?(first))
389
- assert_equal(customer.recommended.first, first)
415
+ assert(customer.recommended(['product']).include?(first))
390
416
  end
391
417
  end
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 1
8
- - 3
9
- version: 0.1.3
7
+ - 2
8
+ - 0
9
+ version: 0.2.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Directed Edge
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-04-09 00:00:00 +02:00
17
+ date: 2010-04-25 00:00:00 +02:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency