resync 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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7788451959096dfbc4797cbf223b4817f2058ed4
4
- data.tar.gz: e50c9e4839b2a595cb8cb1685f3bbd1b7a4a06c4
3
+ metadata.gz: aeaccafe9b78c6c1b73438dbc3615691e55acf37
4
+ data.tar.gz: 20ca197220dff4f8ac252d1fd3060446fad6e5e4
5
5
  SHA512:
6
- metadata.gz: f138fb16a10639f60575f198db8d320b8b17e411fb2d8dc5a78b9a75742cfcfd55991c6dee6367e3d13b7c3e7c090ccc9ac8cd85bca9049b0aa5330d65ce57ee
7
- data.tar.gz: 7b916f07c91848b65cfd3c390bdb321eec05a86dcd4e49745ca4f32d49a8913b1343242a635cb3dc75b69f4c6900ddde3dffde6f0e99ff322a9efbc94e97c032
6
+ metadata.gz: b82cd0986b56ea9aed5f12abc1532ead2bb942128938fed721b68fee918987acbc8fdb8683074d0669c5999cd9036d6b28c72b184ab39d44ed2f8928c48f2d85
7
+ data.tar.gz: eb88c946de862ab36cf3be1f9c01ff94f1f5ebe01d586ae6424bc729c004f0c6c80fd8b8a779415502c550faed3b350ee0f56b3e6c53e3d2e6273bd3934d10a9
data/CHANGES.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## 0.2.0
2
+
3
+ - `BaseResourceList#resources` now returns an `IndexableLazy` instead of a plain array.
4
+ - Added `BaseResourcesList#resources_in` to filter resource lists by time.
5
+ - All `Augmented` objects now expose the complete set of time attribtues, so as to avoid having to fish around in the metadata.
6
+
1
7
  ## 0.1.3
2
8
 
3
9
  - Fix issue making it difficult to extend CapabilityList
@@ -10,6 +10,5 @@ module Resync
10
10
 
11
11
  # The capability provided by this type.
12
12
  CAPABILITY = 'resourcelist'
13
-
14
13
  end
15
14
  end
@@ -72,5 +72,22 @@ module Resync
72
72
  def link_for(rel:)
73
73
  links.find { |l| l.rel == rel }
74
74
  end
75
+
76
+ def at_time
77
+ metadata.at_time if metadata
78
+ end
79
+
80
+ def from_time
81
+ metadata.from_time if metadata
82
+ end
83
+
84
+ def until_time
85
+ metadata.until_time if metadata
86
+ end
87
+
88
+ def completed_time
89
+ metadata.completed_time if metadata
90
+ end
91
+
75
92
  end
76
93
  end
@@ -8,8 +8,8 @@ module Resync
8
8
  # must define a +CAPABILITY+ constant identifying the capability
9
9
  # they represent (e.g. +resourcelist+, +changelist+).
10
10
  #
11
- # @!attribute [rw] resources
12
- # @return [Array<Resource>] the +<url>+ or +<sitemap>+ elements contained in this list.
11
+ # @!attribute [r] resources
12
+ # @return [Util::IndexableLazy<Resource>] the +<url>+ or +<sitemap>+ elements contained in this list.
13
13
  class BaseResourceList < Augmented
14
14
  include ::XML::Mapping
15
15
 
@@ -40,7 +40,7 @@ module Resync
40
40
 
41
41
  # Sets the +resources+ list. +nil+ is treated as an empty list.
42
42
  def resources=(value)
43
- @resources = value || []
43
+ @resources = Util::IndexableLazy.new(value || [])
44
44
  end
45
45
 
46
46
  # Sets the metadata.
@@ -61,9 +61,9 @@ module Resync
61
61
 
62
62
  # Finds resources with the specified capability.
63
63
  # @param capability [String] the capability.
64
- # @return [Array<Resource>] those resources having that capability, or an empty array if none exist.
64
+ # @return [Enumerator::Lazy<Resource>] those resources having that capability, or an empty array if none exist.
65
65
  def resources_for(capability:)
66
- resources.select { |l| l.capability == capability }
66
+ resources.select { |r| r.capability == capability }
67
67
  end
68
68
 
69
69
  # Shortcut to find the first resource with the specified capability (in ResourceSync there often
@@ -71,7 +71,18 @@ module Resync
71
71
  # @param capability [String] the capability.
72
72
  # @return [Resource] the first resource having that capability, or nil if none exists.
73
73
  def resource_for(capability:)
74
- resources.find { |l| l.capability == capability }
74
+ resources.find { |r| r.capability == capability }
75
+ end
76
+
77
+ # Finds only those resources falling within the specified time range. Any of the time
78
+ # attributes (+:modified_time+, +:at_time+, +:completed_time+, +:from_time+, +:until_time+)
79
+ # can be used for filtering.
80
+ # @param time_range [Range[Time]] the range of acceptable times (inclusive or exclusive)
81
+ # @param time_attr [Symbol] the time type to filter on: +:modified_time+, +:at_time+,
82
+ # +:completed_time+, +:from_time+ or +:until_time+
83
+ # @return [Enumerator::Lazy<Resource>] a lazy enumeration of the resources within the specified range.
84
+ def resources_in(time_range:, time_attr:)
85
+ resources.select { |r| time_range.cover?(r.send(time_attr)) }
75
86
  end
76
87
 
77
88
  # ------------------------------------------------------------
@@ -109,7 +120,7 @@ module Resync
109
120
  capability = self.class::CAPABILITY
110
121
  fail ArgumentError, "Missing constant #{self.class}::CAPABILITY" unless capability
111
122
  return Metadata.new(capability: capability) unless metadata
112
- fail ArgumentError, "#{metadata} does not appear to be metadata" unless metadata.respond_to?('capability')
123
+ fail ArgumentError, ":metadata argument <#{metadata}> does not appear to be metadata" unless metadata.respond_to?(:capability)
113
124
  fail ArgumentError, "Wrong capability for #{self.class.name} metadata; expected '#{capability}', was '#{metadata.capability}'" unless metadata.capability == capability
114
125
  metadata
115
126
  end
@@ -48,12 +48,21 @@ module Resync
48
48
  def sorted(value)
49
49
  return [] unless value
50
50
  value.sort do |left, right|
51
- if left.modified_time && right.modified_time
52
- left.modified_time <=> right.modified_time
53
- else
54
- right.modified_time ? 1 : -1
51
+ compare(left, right)
52
+ end
53
+ end
54
+
55
+ def compare(left, right)
56
+ [:modified_time, :from_time, :at_time, :until_time, :completed_time].each do |time_reader|
57
+ left_time = left.send(time_reader)
58
+ right_time = right.send(time_reader)
59
+ if left_time && right_time
60
+ return left_time <=> right_time
61
+ elsif left_time || right_time
62
+ return left_time ? -1 : 1
55
63
  end
56
64
  end
65
+ 0
57
66
  end
58
67
 
59
68
  def by_uri(resources)
@@ -0,0 +1,18 @@
1
+ require 'delegate'
2
+
3
+ module Resync
4
+ module Util
5
+ class IndexableLazy < SimpleDelegator
6
+
7
+ def initialize(array)
8
+ super(array.lazy)
9
+ @array = array
10
+ end
11
+
12
+ def [](key)
13
+ @array[key]
14
+ end
15
+
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,6 @@
1
+ module Resync
2
+ # Miscellaneous utilities
3
+ module Types
4
+ Dir.glob(File.expand_path('../util/*.rb', __FILE__), &method(:require))
5
+ end
6
+ end
@@ -1,4 +1,4 @@
1
1
  module Resync
2
2
  # The version of this gem.
3
- VERSION = '0.1.3'
3
+ VERSION = '0.2.0'
4
4
  end
@@ -80,10 +80,10 @@ module Resync
80
80
  it 'maps resources by capability' do
81
81
  resources = valid_resources
82
82
  capability_list = CapabilityList.new(resources: resources, links: [Link.new(rel: 'up', uri: 'http://example.org/')])
83
- expect(capability_list.resources_for(capability: 'resourcelist')).to eq([resources[0]])
84
- expect(capability_list.resources_for(capability: 'resourcedump')).to eq([resources[1]])
85
- expect(capability_list.resources_for(capability: 'changelist')).to eq([resources[2]])
86
- expect(capability_list.resources_for(capability: 'changedump')).to eq([resources[3]])
83
+ expect(capability_list.resources_for(capability: 'resourcelist').to_a).to eq([resources[0]])
84
+ expect(capability_list.resources_for(capability: 'resourcedump').to_a).to eq([resources[1]])
85
+ expect(capability_list.resources_for(capability: 'changelist').to_a).to eq([resources[2]])
86
+ expect(capability_list.resources_for(capability: 'changedump').to_a).to eq([resources[3]])
87
87
  end
88
88
  end
89
89
 
@@ -3,10 +3,7 @@ require_relative 'shared/base_resource_list_examples'
3
3
  module Resync
4
4
  describe ResourceListIndex do
5
5
  it_behaves_like BaseResourceList
6
-
7
- describe 'links' do
8
- it_behaves_like Augmented
9
- end
6
+ it_behaves_like Augmented
10
7
 
11
8
  describe 'XML conversion' do
12
9
  describe '#from_xml' do
@@ -3,10 +3,7 @@ require_relative 'shared/base_resource_list_examples'
3
3
  module Resync
4
4
  describe ResourceDumpManifest do
5
5
  it_behaves_like BaseResourceList
6
-
7
- describe 'links' do
8
- it_behaves_like Augmented
9
- end
6
+ it_behaves_like Augmented
10
7
 
11
8
  describe 'XML conversion' do
12
9
  describe '#from_xml' do
@@ -3,10 +3,7 @@ require_relative 'shared/base_resource_list_examples'
3
3
  module Resync
4
4
  describe ResourceDump do
5
5
  it_behaves_like BaseResourceList
6
-
7
- describe 'links' do
8
- it_behaves_like Augmented
9
- end
6
+ it_behaves_like Augmented
10
7
 
11
8
  describe 'XML conversion' do
12
9
  describe '#from_xml' do
@@ -3,10 +3,7 @@ require_relative 'shared/base_resource_list_examples'
3
3
  module Resync
4
4
  describe ResourceListIndex do
5
5
  it_behaves_like BaseResourceList
6
-
7
- describe 'links' do
8
- it_behaves_like Augmented
9
- end
6
+ it_behaves_like Augmented
10
7
 
11
8
  describe 'XML conversion' do
12
9
  describe '#from_xml' do
@@ -3,10 +3,7 @@ require_relative 'shared/base_resource_list_examples'
3
3
  module Resync
4
4
  describe ResourceList do
5
5
  it_behaves_like BaseResourceList
6
-
7
- describe 'links' do
8
- it_behaves_like Augmented
9
- end
6
+ it_behaves_like Augmented
10
7
 
11
8
  describe 'XML conversion' do
12
9
  describe '#from_xml' do
@@ -4,6 +4,13 @@ require_relative 'shared/augmented_examples'
4
4
 
5
5
  module Resync
6
6
  describe Resource do
7
+
8
+ def required_arguments
9
+ { uri: 'http://example.org' }
10
+ end
11
+
12
+ it_behaves_like Augmented
13
+
7
14
  describe '#new' do
8
15
 
9
16
  describe 'uri' do
@@ -23,13 +30,6 @@ module Resync
23
30
  end
24
31
  end
25
32
 
26
- describe 'links' do
27
- def required_arguments
28
- { uri: 'http://example.org' }
29
- end
30
- it_behaves_like Augmented
31
- end
32
-
33
33
  describe 'metadata' do
34
34
  it 'accepts metadata' do
35
35
  md = Metadata.new
@@ -13,15 +13,14 @@ module Resync
13
13
  describe 'links' do
14
14
  it 'accepts a list of links' do
15
15
  links = [Link.new(rel: 'describedby', uri: 'http://example.org/'), Link.new(rel: 'duplicate', uri: 'http://example.com/')]
16
- list = new_instance(links: links)
17
- expect(list.links).to eq(links)
16
+ augmented = new_instance(links: links)
17
+ expect(augmented.links).to eq(links)
18
18
  end
19
19
 
20
- it 'defaults to an empty list if no links are specified' do
21
- list = new_instance
22
- expect(list.links).to eq([])
20
+ it 'defaults to an empty augmented if no links are specified' do
21
+ augmented = new_instance
22
+ expect(augmented.links).to eq([])
23
23
  end
24
-
25
24
  end
26
25
 
27
26
  describe '#links_for' do
@@ -32,10 +31,10 @@ module Resync
32
31
  Link.new(rel: 'describedby', uri: 'http://example.org/desc2'),
33
32
  Link.new(rel: 'duplicate', uri: 'http://example.com/dup2')
34
33
  ]
35
- list = new_instance(links: links)
36
- expect(list.links_for(rel: 'describedby')).to eq([links[0], links[2]])
37
- expect(list.links_for(rel: 'duplicate')).to eq([links[1], links[3]])
38
- expect(list.links_for(rel: 'elvis')).to eq([])
34
+ augmented = new_instance(links: links)
35
+ expect(augmented.links_for(rel: 'describedby')).to eq([links[0], links[2]])
36
+ expect(augmented.links_for(rel: 'duplicate')).to eq([links[1], links[3]])
37
+ expect(augmented.links_for(rel: 'elvis')).to eq([])
39
38
  end
40
39
  end
41
40
 
@@ -47,10 +46,27 @@ module Resync
47
46
  Link.new(rel: 'describedby', uri: 'http://example.org/desc2'),
48
47
  Link.new(rel: 'duplicate', uri: 'http://example.com/dup2')
49
48
  ]
50
- list = new_instance(links: links)
51
- expect(list.link_for(rel: 'describedby')).to eq(links[0])
52
- expect(list.link_for(rel: 'duplicate')).to eq(links[1])
53
- expect(list.link_for(rel: 'elvis')).to eq(nil)
49
+ augmented = new_instance(links: links)
50
+ expect(augmented.link_for(rel: 'describedby')).to eq(links[0])
51
+ expect(augmented.link_for(rel: 'duplicate')).to eq(links[1])
52
+ expect(augmented.link_for(rel: 'elvis')).to eq(nil)
53
+ end
54
+ end
55
+
56
+ describe 'additional time attributes' do
57
+ it 'extracts the at_time, from_time, until_time, and completed_time from the metadata' do
58
+ capability = described_class::CAPABILITY if defined?(described_class::CAPABILITY)
59
+ md = Metadata.new(
60
+ at_time: Time.utc(1999, 1, 1),
61
+ from_time: Time.utc(2001, 1, 1),
62
+ until_time: Time.utc(2003, 1, 1),
63
+ completed_time: Time.utc(2005, 1, 1),
64
+ capability: capability
65
+ )
66
+ augmented = new_instance(metadata: md)
67
+ [:at_time, :from_time, :until_time, :completed_time].each do |t|
68
+ expect(augmented.send(t)).to be_time(md.send(t))
69
+ end
54
70
  end
55
71
  end
56
72
 
@@ -9,7 +9,12 @@ module Resync
9
9
 
10
10
  # TODO: Find a better way to express this
11
11
  def resource_list
12
- (defined? valid_resources) ? valid_resources : [Resource.new(uri: 'http://example.org/'), Resource.new(uri: 'http://example.com/')]
12
+ (defined? valid_resources) ? valid_resources : [
13
+ Resource.new(uri: 'http://example.com/res1'),
14
+ Resource.new(uri: 'http://example.com/res2'),
15
+ Resource.new(uri: 'http://example.com/res3'),
16
+ Resource.new(uri: 'http://example.com/res4')
17
+ ]
13
18
  end
14
19
 
15
20
  # TODO: Find a better way to express this
@@ -25,15 +30,34 @@ module Resync
25
30
  describe '#new' do
26
31
  describe 'resources' do
27
32
  it 'accepts a list of resources' do
28
- puts defined? valid_resources
29
33
  resources = resource_list
30
34
  list = new_instance(resources: resources)
31
- expect(list.resources).to eq(resources)
35
+ expect(list.resources.to_a).to eq(resources)
36
+ end
37
+
38
+ it 'is lazy' do
39
+ resources = resource_list
40
+ list = new_instance(resources: resources)
41
+
42
+ half = resources.size / 2
43
+ (0...resources.size).each do |i|
44
+ if i < half
45
+ expect(resources[i]).to receive(:priority).and_return(i)
46
+ else
47
+ expect(resources[i]).not_to receive(:priority)
48
+ end
49
+ end
50
+
51
+ count = 0
52
+ list.resources.take(half).each do |r|
53
+ expect(r.priority).to eq(count)
54
+ count += 1
55
+ end
32
56
  end
33
57
 
34
58
  it 'defaults to an empty list if no resources are specified' do
35
59
  list = new_instance
36
- expect(list.resources).to eq([])
60
+ expect(list.resources.to_a).to eq([])
37
61
  end
38
62
  end
39
63
 
@@ -67,9 +91,9 @@ module Resync
67
91
  Resource.new(uri: 'http://example.com/dataset1/changelist2.xml', metadata: Metadata.new(capability: 'changelist'))
68
92
  ]
69
93
  list = new_instance(resources: resources)
70
- expect(list.resources_for(capability: 'resourcedump')).to eq([resources[0], resources[2]])
71
- expect(list.resources_for(capability: 'changelist')).to eq([resources[1], resources[3]])
72
- expect(list.resources_for(capability: 'changedump')).to eq([])
94
+ expect(list.resources_for(capability: 'resourcedump').to_a).to eq([resources[0], resources[2]])
95
+ expect(list.resources_for(capability: 'changelist').to_a).to eq([resources[1], resources[3]])
96
+ expect(list.resources_for(capability: 'changedump').to_a).to eq([])
73
97
  end
74
98
  end
75
99
  end
@@ -91,7 +115,7 @@ module Resync
91
115
  end
92
116
  end
93
117
 
94
- describe 'capability' do
118
+ describe '#capability' do
95
119
  it 'extracts the capability' do
96
120
  metadata = Metadata.new(capability: described_class::CAPABILITY)
97
121
  list = new_instance(metadata: metadata)
@@ -99,5 +123,48 @@ module Resync
99
123
  end
100
124
  end
101
125
 
126
+ describe '#resources_in' do
127
+ [:at_time, :completed_time, :from_time, :until_time, :modified_time].each do |reader|
128
+ it "allows filtering by #{reader}" do
129
+ before_time = Time.utc(1969, 1, 1)
130
+ start_time = Time.utc(1970, 1, 1)
131
+ end_time = Time.utc(1980, 1, 1)
132
+ after_time = Time.utc(1981, 1, 1)
133
+ times = [before_time, start_time, end_time, after_time]
134
+
135
+ writer = "#{reader}=".to_sym
136
+ resources = resource_list
137
+ resources.each_with_index do |r, i|
138
+ if writer == :modified_time=
139
+ r.send(writer, times[i])
140
+ else
141
+ md = r.metadata || (r.metadata = Metadata.new)
142
+ md.send(writer, times[i])
143
+ end
144
+ expect(r.send(reader)).to be_time(times[i]) # just to be sure
145
+ end
146
+
147
+ list = new_instance(resources: resources, metadata: Metadata.new(capability: described_class::CAPABILITY))
148
+
149
+ range_inclusive = start_time..end_time
150
+
151
+ filtered = list.resources_in(time_range: range_inclusive, time_attr: reader).to_a
152
+ expect(filtered.size).to eq(2)
153
+ expect(filtered).not_to include(resources[0])
154
+ expect(filtered).to include(resources[1])
155
+ expect(filtered).to include(resources[2])
156
+ expect(filtered).not_to include(resources[3])
157
+
158
+ range_exclusive = start_time...end_time
159
+ filtered = list.resources_in(time_range: range_exclusive, time_attr: reader).to_a
160
+ expect(filtered.size).to eq(1)
161
+ expect(filtered).not_to include(resources[0])
162
+ expect(filtered).to include(resources[1])
163
+ expect(filtered).not_to include(resources[2])
164
+ expect(filtered).not_to include(resources[3])
165
+ end
166
+ end
167
+ end
168
+
102
169
  end
103
170
  end
@@ -24,7 +24,20 @@ module Resync
24
24
  resource0 = Resource.new(uri: 'http://example.org', modified_time: Time.utc(1997, 7, 16, 19, 20, 30.45))
25
25
  resource1 = Resource.new(uri: 'http://example.org', modified_time: Time.utc(1998, 7, 16, 19, 20, 30.45))
26
26
  list = new_instance(resources: [resource1, resource0])
27
- expect(list.resources).to eq([resource0, resource1])
27
+ expect(list.resources.to_a).to eq([resource0, resource1])
28
+ end
29
+
30
+ it 'is non-destructive when sorting resources with identical times' do
31
+ resource0 = Resource.new(uri: 'http://example.org', modified_time: Time.utc(1997, 7, 16, 19, 20, 30.45))
32
+ resource1 = Resource.new(uri: 'http://example.org', modified_time: Time.utc(1998, 7, 16, 19, 20, 30.45))
33
+ resource2 = Resource.new(uri: 'http://example.org', modified_time: Time.utc(1998, 7, 16, 19, 20, 30.45))
34
+ resource4 = Resource.new(uri: 'http://example.org', modified_time: Time.utc(1998, 1, 16, 19, 20, 30.45))
35
+ list = new_instance(resources: [resource1, resource4, resource2, resource0])
36
+ resources = list.resources.to_a
37
+ expect(resources[0]).to be(resource0)
38
+ expect(resources[1]).to be(resource4)
39
+ expect(resources).to include(resource1)
40
+ expect(resources).to include(resource2)
28
41
  end
29
42
 
30
43
  it 'sorts resources with modified_time before resources without' do
@@ -32,7 +45,44 @@ module Resync
32
45
  resource1 = Resource.new(uri: 'http://example.org', modified_time: Time.utc(1998, 7, 16, 19, 20, 30.45))
33
46
  resource2 = Resource.new(uri: 'http://example.com')
34
47
  list = new_instance(resources: [resource1, resource2, resource0])
35
- expect(list.resources).to eq([resource0, resource1, resource2])
48
+ expect(list.resources.to_a).to eq([resource0, resource1, resource2])
49
+ end
50
+
51
+ it 'sorts resources by from_time' do
52
+ resource0 = Resource.new(uri: 'http://example.org', metadata: Metadata.new(from_time: Time.utc(1997, 7, 16, 19, 20, 30.45)))
53
+ resource1 = Resource.new(uri: 'http://example.org', metadata: Metadata.new(from_time: Time.utc(1998, 7, 16, 19, 20, 30.45)))
54
+ list = new_instance(resources: [resource1, resource0])
55
+ expect(list.resources.to_a).to eq([resource0, resource1])
56
+ end
57
+
58
+ it 'sorts resources by at_time' do
59
+ resource0 = Resource.new(uri: 'http://example.org', metadata: Metadata.new(at_time: Time.utc(1997, 7, 16, 19, 20, 30.45)))
60
+ resource1 = Resource.new(uri: 'http://example.org', metadata: Metadata.new(at_time: Time.utc(1998, 7, 16, 19, 20, 30.45)))
61
+ list = new_instance(resources: [resource1, resource0])
62
+ expect(list.resources.to_a).to eq([resource0, resource1])
63
+ end
64
+
65
+ it 'sorts resources by until_time' do
66
+ resource0 = Resource.new(uri: 'http://example.org', metadata: Metadata.new(until_time: Time.utc(1997, 7, 16, 19, 20, 30.45)))
67
+ resource1 = Resource.new(uri: 'http://example.org', metadata: Metadata.new(until_time: Time.utc(1998, 7, 16, 19, 20, 30.45)))
68
+ list = new_instance(resources: [resource1, resource0])
69
+ expect(list.resources.to_a).to eq([resource0, resource1])
70
+ end
71
+
72
+ it 'sorts resources by completed_time' do
73
+ resource0 = Resource.new(uri: 'http://example.org', metadata: Metadata.new(completed_time: Time.utc(1997, 7, 16, 19, 20, 30.45)))
74
+ resource1 = Resource.new(uri: 'http://example.org', metadata: Metadata.new(completed_time: Time.utc(1998, 7, 16, 19, 20, 30.45)))
75
+ list = new_instance(resources: [resource1, resource0])
76
+ expect(list.resources.to_a).to eq([resource0, resource1])
77
+ end
78
+
79
+ it 'preferentially sorts by modified_time' do
80
+ resource0 = Resource.new(uri: 'http://example.org', metadata: Metadata.new(at_time: Time.utc(1998, 7, 16, 19, 20, 30.45)))
81
+ resource1 = Resource.new(uri: 'http://example.org', metadata: Metadata.new(at_time: Time.utc(1997, 7, 16, 19, 20, 30.45)))
82
+ resource2 = Resource.new(uri: 'http://example.org', modified_time: Time.utc(2001, 7, 16, 19, 20, 30.45), metadata: Metadata.new(at_time: Time.utc(2003, 7, 16, 19, 20, 30.45)))
83
+ resource3 = Resource.new(uri: 'http://example.org', modified_time: Time.utc(2000, 1, 16, 19, 20, 30.45), metadata: Metadata.new(at_time: Time.utc(2005, 7, 16, 19, 20, 30.45)))
84
+ list = new_instance(resources: [resource0, resource1, resource2, resource3])
85
+ expect(list.resources.to_a).to eq([resource3, resource2, resource1, resource0])
36
86
  end
37
87
  end
38
88
  end
@@ -5,10 +5,7 @@ require_relative 'shared/augmented_examples'
5
5
  module Resync
6
6
  describe SourceDescription do
7
7
  it_behaves_like BaseResourceList
8
-
9
- describe 'links' do
10
- it_behaves_like Augmented
11
- end
8
+ it_behaves_like Augmented
12
9
 
13
10
  describe 'XML conversion' do
14
11
  describe '#from_xml' do
@@ -0,0 +1,133 @@
1
+ require 'spec_helper'
2
+
3
+ module Resync
4
+ module Util
5
+ describe IndexableLazy do
6
+
7
+ before(:each) do
8
+ @size = 3
9
+ @array = Array.new(@size) { instance_double(Object) }
10
+ @lazy = IndexableLazy.new(@array)
11
+ end
12
+
13
+ describe '#size' do
14
+ it 'returns the size of the underlying array' do
15
+ expect(@lazy.size).to eq(@size)
16
+ end
17
+ end
18
+
19
+ describe '#[]' do
20
+ it 'is lazy' do
21
+ expect(@array[0]).to receive(:to_s).and_return('0')
22
+ expect(@array[1]).to receive(:to_s).and_return('1')
23
+ expect(@array[2]).not_to receive(:to_s)
24
+
25
+ (0...@lazy.size).each do |i|
26
+ expect(@lazy[i]).to eq(@array[i])
27
+ break if @lazy[i].to_s == '1'
28
+ end
29
+ end
30
+ end
31
+
32
+ describe '#each' do
33
+ it 'is lazy' do
34
+ expect(@array[0]).to receive(:to_s).and_return('0')
35
+ expect(@array[1]).to receive(:to_s).and_return('1')
36
+ expect(@array[2]).not_to receive(:to_s)
37
+
38
+ @lazy.each do |v|
39
+ break if v.to_s == '1'
40
+ end
41
+ end
42
+ end
43
+
44
+ describe '#each_with_index' do
45
+ it 'is lazy' do
46
+ expect(@array[0]).to receive(:to_s).and_return('0')
47
+ expect(@array[1]).to receive(:to_s).and_return('1')
48
+ expect(@array[2]).not_to receive(:to_s)
49
+
50
+ @lazy.each_with_index do |v, i|
51
+ break if v.to_s == '1' || i > 1
52
+ end
53
+ end
54
+ end
55
+
56
+ describe '#each_with_object' do
57
+ it 'is lazy' do
58
+ expect(@array[0]).to receive(:to_s).and_return('0')
59
+ expect(@array[1]).to receive(:to_s).and_return('1')
60
+ expect(@array[2]).not_to receive(:to_s)
61
+
62
+ acc = []
63
+ @lazy.each_with_object(acc) do |v, obj|
64
+ obj << v.to_s
65
+ break if obj[-1] == '1'
66
+ end
67
+ expect(acc).to eq(%w(0 1))
68
+ end
69
+ end
70
+
71
+ describe '#find' do
72
+ it 'is lazy' do
73
+ expect(@array[0]).to receive(:to_s).and_return('0')
74
+ expect(@array[1]).to receive(:to_s).and_return('1')
75
+ expect(@array[2]).not_to receive(:to_s)
76
+
77
+ expect(@lazy.find { |v| v.to_s == '1' }).to be(@array[1])
78
+ end
79
+ end
80
+
81
+ describe '#find_index' do
82
+ it 'is lazy' do
83
+ expect(@array[0]).to receive(:to_s).and_return('0')
84
+ expect(@array[1]).to receive(:to_s).and_return('1')
85
+ expect(@array[2]).not_to receive(:to_s)
86
+
87
+ expect(@lazy.find_index { |v| v.to_s == '1' }).to eq(1)
88
+ end
89
+ end
90
+
91
+ describe '#take_while' do
92
+ it 'is lazy' do
93
+ expect(@array[0]).to receive(:to_s).and_return('0')
94
+ expect(@array[1]).to receive(:to_s).and_return('1')
95
+ expect(@array[2]).not_to receive(:to_s)
96
+
97
+ expect(@lazy.take_while { |v| v.to_s == '0' }.to_a).to eq([@array[0]])
98
+ end
99
+ end
100
+
101
+ describe '#map' do
102
+ it 'is lazy' do
103
+ expect(@array[0]).to receive(:to_s).and_return('0')
104
+ expect(@array[1]).to receive(:to_s).and_return('1')
105
+ expect(@array[2]).not_to receive(:to_s)
106
+
107
+ mapped = @lazy.map(&:to_s)
108
+ expect(mapped.take(2).to_a).to eq(%w(0 1))
109
+ end
110
+ end
111
+
112
+ describe '#take' do
113
+ it 'is lazy' do
114
+ expect(@array[0]).to receive(:to_s).and_return('0')
115
+ expect(@array[1]).to receive(:to_s).and_return('1')
116
+ expect(@array[2]).not_to receive(:to_s)
117
+
118
+ expect(@lazy.take(2).map(&:to_s).to_a).to eq(%w(0 1))
119
+ end
120
+ end
121
+
122
+ describe '#select' do
123
+ it 'is lazy' do
124
+ expect(@array[0]).not_to receive(:to_s)
125
+ expect(@array[1]).not_to receive(:to_s)
126
+ expect(@array[2]).not_to receive(:to_s)
127
+
128
+ @lazy.select(&:to_s)
129
+ end
130
+ end
131
+ end
132
+ end
133
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: resync
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Moles
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-06-05 00:00:00.000000000 Z
11
+ date: 2015-06-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: mime-types
@@ -191,6 +191,8 @@ files:
191
191
  - lib/resync/types.rb
192
192
  - lib/resync/types/change.rb
193
193
  - lib/resync/types/change_frequency.rb
194
+ - lib/resync/util.rb
195
+ - lib/resync/util/indexable_lazy.rb
194
196
  - lib/resync/version.rb
195
197
  - lib/resync/xml.rb
196
198
  - lib/resync/xml_parser.rb
@@ -256,6 +258,7 @@ files:
256
258
  - spec/unit/resync/shared/sorted_list_examples.rb
257
259
  - spec/unit/resync/shared/uri_field_examples.rb
258
260
  - spec/unit/resync/source_description_spec.rb
261
+ - spec/unit/resync/util/indexable_lazy_spec.rb
259
262
  - spec/unit/resync/xml/timenode_spec.rb
260
263
  - spec/unit/resync/xml/xml_spec.rb
261
264
  - spec/unit/resync/xml_parser_spec.rb
@@ -279,7 +282,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
279
282
  version: '0'
280
283
  requirements: []
281
284
  rubyforge_project:
282
- rubygems_version: 2.4.6
285
+ rubygems_version: 2.4.7
283
286
  signing_key:
284
287
  specification_version: 4
285
288
  summary: Utility library for ResourceSync
@@ -345,6 +348,7 @@ test_files:
345
348
  - spec/unit/resync/shared/sorted_list_examples.rb
346
349
  - spec/unit/resync/shared/uri_field_examples.rb
347
350
  - spec/unit/resync/source_description_spec.rb
351
+ - spec/unit/resync/util/indexable_lazy_spec.rb
348
352
  - spec/unit/resync/xml/timenode_spec.rb
349
353
  - spec/unit/resync/xml/xml_spec.rb
350
354
  - spec/unit/resync/xml_parser_spec.rb