mida 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/CHANGELOG.rdoc +5 -0
- data/README.rdoc +24 -1
- data/Rakefile +1 -1
- data/lib/mida.rb +3 -0
- data/lib/mida/document.rb +12 -7
- data/lib/mida/item.rb +75 -19
- data/lib/mida/{property.rb → itemprop.rb} +4 -1
- data/lib/mida/vocabulary.rb +26 -0
- data/lib/mida/vocabulary/generic.rb +15 -0
- data/lib/mida/vocabularydesc.rb +57 -0
- data/spec/document_spec.rb +85 -5
- data/spec/item_spec.rb +117 -2
- data/spec/{property_spec.rb → itemprop_spec.rb} +18 -18
- data/spec/vocabularydesc_spec.rb +106 -0
- metadata +8 -4
data/CHANGELOG.rdoc
CHANGED
@@ -1,3 +1,8 @@
|
|
1
|
+
== 0.2.0 (3rd May 2011)
|
2
|
+
* Add ability to describe and conform to vocabularies
|
3
|
+
* Rename Mida::Property to Mida::Itemprop to better reflect use
|
4
|
+
* Make some of the Mida::Itemprop class methods private
|
5
|
+
|
1
6
|
== 0.1.3 (18th April 2011)
|
2
7
|
* Ensure itemprops are parsed properly if containing non-microdata elements
|
3
8
|
* Support itemprops nested within other itemprops
|
data/README.rdoc
CHANGED
@@ -10,7 +10,7 @@ This is based on the latest Published version of the Microdata Specification
|
|
10
10
|
dated {5th April 2011}[http://www.w3.org/TR/2011/WD-microdata-20110405/].
|
11
11
|
|
12
12
|
== Installation
|
13
|
-
|
13
|
+
Mida keeps RubyGems[http://rubygems.org/gems/mida] up-to-date with its latest version, so installing is as easy as:
|
14
14
|
gem install mida
|
15
15
|
|
16
16
|
=== Requirements:
|
@@ -58,6 +58,29 @@ values will be an array of either +String+ or <tt>Mida::Item</tt> instances.
|
|
58
58
|
To see the +properties+ of the +Item+:
|
59
59
|
puts doc.items.first.properties
|
60
60
|
|
61
|
+
=== Working with Vocabularies
|
62
|
+
Mida allows you to define vocabularies, so that input data can be constrained to match
|
63
|
+
expected patterns. By default a generic vocabulary (<tt>Mida::Vocabulary::Generic</tt>)
|
64
|
+
is registered which will match against any +itemtype+ with any number of properties.
|
65
|
+
|
66
|
+
If you want to specify a vocabulary you create a class derived from <tt>Mida::VocabularyDesc</tt>
|
67
|
+
and use +itemtype+, +has_one+, +has_many+ and +types+ to describe the vocabulary.
|
68
|
+
|
69
|
+
As an example the following describes a subset of Google's Review vocabulary:
|
70
|
+
class Review < Mida::VocabularyDesc
|
71
|
+
itemtype %r{http://data-vocabulary.org/review}
|
72
|
+
has_one 'itemreviewed'
|
73
|
+
has_one 'rating'
|
74
|
+
end
|
75
|
+
|
76
|
+
To register the above Vocabulary use:
|
77
|
+
Mida::Vocabulary.register(Review)
|
78
|
+
|
79
|
+
Now if Mida is parsing some input and manages to match against the +Review+ +itemtype+, it
|
80
|
+
will only allow the specified properties and will reject any that don't have the correct number. It
|
81
|
+
will also set <tt>Item#vocabulary</tt> accordingly, e.g.
|
82
|
+
doc.items.first.vocabulary # => Review
|
83
|
+
|
61
84
|
== Bugs/Feature Requests
|
62
85
|
If you find a bug or want to make a feature request, please report it at the
|
63
86
|
Mida project's {issues tracker}[https://github.com/LawrenceWoodman/mida/issues]
|
data/Rakefile
CHANGED
@@ -6,7 +6,7 @@ spec = Gem::Specification.new do |s|
|
|
6
6
|
s.name = "mida"
|
7
7
|
s.summary = "A Microdata parser/extractor library"
|
8
8
|
s.description = "A Microdata parser and extractor library, based on the latest published version of the Microdata Specification, dated 5th April 2011."
|
9
|
-
s.version = "0.
|
9
|
+
s.version = "0.2.0"
|
10
10
|
s.author = "Lawrence Woodman"
|
11
11
|
s.email = "lwoodman@vlifesystems.com"
|
12
12
|
s.homepage = %q{http://github.com/LawrenceWoodman/mida}
|
data/lib/mida.rb
CHANGED
data/lib/mida/document.rb
CHANGED
@@ -11,7 +11,7 @@ module Mida
|
|
11
11
|
|
12
12
|
# Create a new Microdata object
|
13
13
|
#
|
14
|
-
# [target] The string containing the html that you want to parse
|
14
|
+
# [target] The string containing the html that you want to parse.
|
15
15
|
# [page_url] The url of target used for form absolute urls. This must
|
16
16
|
# include the filename, e.g. index.html.
|
17
17
|
def initialize(target, page_url=nil)
|
@@ -23,26 +23,31 @@ module Mida
|
|
23
23
|
# Returns an array of matching Mida::Item objects
|
24
24
|
#
|
25
25
|
# [vocabulary] A regexp to match the item types against
|
26
|
+
# or a Class derived from Mida::VocabularyDesc
|
27
|
+
# to match against
|
26
28
|
def search(vocabulary, items=@items)
|
27
29
|
found_items = []
|
30
|
+
regexp_passed = vocabulary.kind_of?(Regexp)
|
31
|
+
regexp = if regexp_passed then vocabulary else vocabulary.itemtype end
|
32
|
+
|
28
33
|
items.each do |item|
|
29
34
|
# Allows matching against empty string, otherwise couldn't match
|
30
35
|
# as item.type can be nil
|
31
|
-
if (item.type.nil? && "" =~
|
36
|
+
if (item.type.nil? && "" =~ regexp) || (item.type =~ regexp)
|
32
37
|
found_items << item
|
33
38
|
end
|
34
|
-
found_items += search_values(item.properties.values,
|
39
|
+
found_items += search_values(item.properties.values, regexp)
|
35
40
|
end
|
36
41
|
found_items
|
37
42
|
end
|
38
43
|
|
39
44
|
private
|
40
45
|
def extract_items
|
41
|
-
|
42
|
-
return nil unless
|
46
|
+
itemscopes = @doc.search('//*[@itemscope and not(@itemprop)]')
|
47
|
+
return nil unless itemscopes
|
43
48
|
|
44
|
-
|
45
|
-
Item.new(
|
49
|
+
itemscopes.collect do |itemscope|
|
50
|
+
Item.new(itemscope, @page_url)
|
46
51
|
end
|
47
52
|
end
|
48
53
|
|
data/lib/mida/item.rb
CHANGED
@@ -4,6 +4,9 @@ module Mida
|
|
4
4
|
|
5
5
|
# Class that holds each item/itemscope
|
6
6
|
class Item
|
7
|
+
# The vocabulary used to interpret this item
|
8
|
+
attr_reader :vocabulary
|
9
|
+
|
7
10
|
# The Type of the item
|
8
11
|
attr_reader :type
|
9
12
|
|
@@ -17,20 +20,27 @@ module Mida
|
|
17
20
|
|
18
21
|
# Create a new Item object
|
19
22
|
#
|
20
|
-
# [itemscope] The itemscope that you want to parse
|
21
|
-
# [page_url] The url of target used for form absolute
|
23
|
+
# [itemscope] The itemscope that you want to parse.
|
24
|
+
# [page_url] The url of target used for form absolute url.
|
22
25
|
def initialize(itemscope, page_url=nil)
|
23
26
|
@itemscope, @page_url = itemscope, page_url
|
24
27
|
@type, @id = extract_attribute('itemtype'), extract_attribute('itemid')
|
28
|
+
@vocabulary = Mida::Vocabulary.find(@type)
|
25
29
|
@properties = {}
|
26
30
|
add_itemref_properties
|
27
|
-
|
31
|
+
parse_elements(extract_elements(@itemscope))
|
32
|
+
validate_properties
|
28
33
|
end
|
29
34
|
|
30
35
|
# Return a Hash representation
|
31
|
-
# of the form
|
36
|
+
# of the form:
|
37
|
+
# { vocabulary: 'http://example.com/vocab/review',
|
38
|
+
# type: 'The item type',
|
39
|
+
# id: 'urn:isbn:1-934356-08-5',
|
40
|
+
# properties: {'a name' => 'avalue' }
|
41
|
+
# }
|
32
42
|
def to_h
|
33
|
-
{type: @type, id: @id, properties: properties_to_h(@properties)}
|
43
|
+
{vocabulary: @vocabulary, type: @type, id: @id, properties: properties_to_h(@properties)}
|
34
44
|
end
|
35
45
|
|
36
46
|
def to_s
|
@@ -38,11 +48,55 @@ module Mida
|
|
38
48
|
end
|
39
49
|
|
40
50
|
def ==(other)
|
41
|
-
@
|
51
|
+
@vocabulary == other.vocabulary && @type == other.type &&
|
52
|
+
@id == other.id && @properties == other.properties
|
42
53
|
end
|
43
54
|
|
44
55
|
private
|
45
56
|
|
57
|
+
# Validate the properties so that they are in their proper form
|
58
|
+
def validate_properties
|
59
|
+
@properties =
|
60
|
+
@properties.each_with_object({}) do |(property, values), hash|
|
61
|
+
if valid_property?(property, values)
|
62
|
+
hash[property] = valid_values(property, values)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# Return whether the number of values conforms to the spec
|
68
|
+
def valid_num_values?(property, values)
|
69
|
+
return false unless @vocabulary.prop_spec.has_key?(property)
|
70
|
+
property_spec = @vocabulary.prop_spec[property]
|
71
|
+
(property_spec[:num] == :many ||
|
72
|
+
(property_spec[:num] == :one && values.length == 1))
|
73
|
+
end
|
74
|
+
|
75
|
+
def valid_property?(property, values)
|
76
|
+
[property, :any].any? {|prop| valid_num_values?(prop, values)}
|
77
|
+
end
|
78
|
+
|
79
|
+
def valid_values(property, values)
|
80
|
+
prop_types = if @vocabulary.prop_spec.has_key?(property)
|
81
|
+
@vocabulary.prop_spec[property][:types]
|
82
|
+
else
|
83
|
+
@vocabulary.prop_spec[:any][:types]
|
84
|
+
end
|
85
|
+
|
86
|
+
values.select {|value| valid_type(prop_types, value) }
|
87
|
+
end
|
88
|
+
|
89
|
+
def valid_type(prop_types, value)
|
90
|
+
if value.respond_to?(:vocabulary)
|
91
|
+
if prop_types.include?(value.vocabulary) || prop_types.include?(:any)
|
92
|
+
return true
|
93
|
+
end
|
94
|
+
elsif prop_types.include?(value.class) || prop_types.include?(:any)
|
95
|
+
return true
|
96
|
+
end
|
97
|
+
false
|
98
|
+
end
|
99
|
+
|
46
100
|
def extract_attribute(attribute)
|
47
101
|
(value = @itemscope.attribute(attribute)) ? value.value : nil
|
48
102
|
end
|
@@ -66,31 +120,33 @@ module Mida
|
|
66
120
|
end
|
67
121
|
|
68
122
|
def properties_to_h(properties)
|
69
|
-
|
70
|
-
|
71
|
-
|
123
|
+
properties.each_with_object({}) do |(name, value), hash|
|
124
|
+
hash[name] = value_to_h(value)
|
125
|
+
end
|
72
126
|
end
|
73
127
|
|
74
128
|
# Add any properties referred to by 'itemref'
|
75
129
|
def add_itemref_properties
|
76
130
|
itemref = extract_attribute('itemref')
|
77
131
|
if itemref
|
78
|
-
itemref.split.each {|id|
|
132
|
+
itemref.split.each {|id| parse_elements(find_with_id(id))}
|
79
133
|
end
|
80
134
|
end
|
81
135
|
|
82
|
-
def
|
83
|
-
elements.each
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
136
|
+
def parse_elements(elements)
|
137
|
+
elements.each {|element| parse_element(element)}
|
138
|
+
end
|
139
|
+
|
140
|
+
def parse_element(element)
|
141
|
+
itemscope = element.attribute('itemscope')
|
142
|
+
itemprop = element.attribute('itemprop')
|
143
|
+
internal_elements = extract_elements(element)
|
144
|
+
add_itemprop(element) if itemscope || itemprop
|
145
|
+
parse_elements(internal_elements) if internal_elements && !itemscope
|
90
146
|
end
|
91
147
|
|
92
148
|
def add_itemprop(itemprop)
|
93
|
-
properties =
|
149
|
+
properties = Itemprop.parse(itemprop, @page_url)
|
94
150
|
properties.each { |name, value| (@properties[name] ||= []) << value }
|
95
151
|
end
|
96
152
|
|
@@ -4,7 +4,7 @@ require 'uri'
|
|
4
4
|
module Mida
|
5
5
|
|
6
6
|
# Module that parses itemprop elements
|
7
|
-
module
|
7
|
+
module Itemprop
|
8
8
|
|
9
9
|
# Returns a Hash representing the property.
|
10
10
|
# Hash is of the form {'property name' => 'value'}
|
@@ -63,6 +63,9 @@ module Mida
|
|
63
63
|
end
|
64
64
|
end
|
65
65
|
|
66
|
+
private_class_method :make_absolute_url, :extract_property_names
|
67
|
+
private_class_method :extract_property_value, :extract_property
|
68
|
+
|
66
69
|
end
|
67
70
|
|
68
71
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Mida
|
2
|
+
|
3
|
+
# Module to register the Vocabularies with
|
4
|
+
module Vocabulary
|
5
|
+
|
6
|
+
# Register a vocabulary that can be used when parsing,
|
7
|
+
# later vocabularies are given precedence over earlier ones
|
8
|
+
def self.register(vocabulary)
|
9
|
+
(@vocabularies ||= []) << vocabulary
|
10
|
+
end
|
11
|
+
|
12
|
+
# Find the last vocabulary registered that matches the itemtype
|
13
|
+
def self.find(itemtype)
|
14
|
+
@vocabularies.reverse_each do |vocabulary|
|
15
|
+
if ((itemtype || "") =~ vocabulary.itemtype) then return vocabulary end
|
16
|
+
end
|
17
|
+
nil
|
18
|
+
end
|
19
|
+
|
20
|
+
# Return the registered vocabularies
|
21
|
+
def self.vocabularies
|
22
|
+
@vocabularies
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Mida
|
2
|
+
|
3
|
+
# Class used to describe a vocabulary
|
4
|
+
#
|
5
|
+
# To specify a vocabulary use the following methods:
|
6
|
+
# +itemtype+, +has_one+, +has_many+, +types+
|
7
|
+
class VocabularyDesc
|
8
|
+
|
9
|
+
# Sets the regular expression to match against the +itemtype+
|
10
|
+
# or returns the current regular expression
|
11
|
+
def self.itemtype(regexp_arg=nil)
|
12
|
+
if regexp_arg
|
13
|
+
@itemtype = regexp_arg
|
14
|
+
else
|
15
|
+
@itemtype
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# Getter to read the created propeties specification
|
20
|
+
def self.prop_spec
|
21
|
+
@prop_spec || {}
|
22
|
+
end
|
23
|
+
|
24
|
+
# The types a property can take. E.g. +String+, or another +Vocabulary+
|
25
|
+
# If you want to say any type, then use +:any+ as the class
|
26
|
+
# This should be used within a +has_one+ or +has_many+ block
|
27
|
+
def self.types(*type_classes)
|
28
|
+
{types: type_classes}
|
29
|
+
end
|
30
|
+
|
31
|
+
# Defines the properties as only containing one value
|
32
|
+
# If want to say any property name, then use +:any+ as a name
|
33
|
+
def self.has_one(*property_names, &block)
|
34
|
+
has(:one, *property_names, &block)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Defines the properties as containing many values
|
38
|
+
# If want to say any property name, then use +:any+ as a name
|
39
|
+
def self.has_many(*property_names, &block)
|
40
|
+
has(:many, *property_names, &block)
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.has(num, *property_names, &block)
|
44
|
+
@prop_spec ||= {}
|
45
|
+
property_names.each_with_object(@prop_spec) do |name, prop_spec|
|
46
|
+
prop_spec[name] = if block_given?
|
47
|
+
{num: num}.merge(yield)
|
48
|
+
else
|
49
|
+
{num: num, types: [String]}
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
private_class_method :has
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
data/spec/document_spec.rb
CHANGED
@@ -94,8 +94,10 @@ describe Mida::Document, 'when run with a document containing textContent and no
|
|
94
94
|
|
95
95
|
it 'should return all the properties and types with the correct values' do
|
96
96
|
expected_results = [
|
97
|
-
{
|
98
|
-
|
97
|
+
{ vocabulary: Mida::Vocabulary::Generic,
|
98
|
+
type: nil, id: nil, properties: {'link_field' => ['']} },
|
99
|
+
{ vocabulary: Mida::Vocabulary::Generic,
|
100
|
+
type: nil,
|
99
101
|
id: nil,
|
100
102
|
properties: {
|
101
103
|
'span_field' => ['Some span content'],
|
@@ -130,11 +132,13 @@ describe Mida::Document, 'when run with a document containing textContent and no
|
|
130
132
|
|
131
133
|
it 'should return all the properties and types with the correct values' do
|
132
134
|
expected_results = [
|
133
|
-
{
|
135
|
+
{ vocabulary: Mida::Vocabulary::Generic,
|
136
|
+
type: nil, id: nil, properties: {
|
134
137
|
'link_field' => ['http://example.com/start/stylesheet.css']
|
135
138
|
}
|
136
139
|
},
|
137
|
-
{
|
140
|
+
{ vocabulary: Mida::Vocabulary::Generic,
|
141
|
+
type: nil,
|
138
142
|
id: nil,
|
139
143
|
properties: {
|
140
144
|
'span_field' => ['Some span content'],
|
@@ -192,6 +196,7 @@ describe Mida::Document, 'when run against a full html document containing one i
|
|
192
196
|
|
193
197
|
it 'should return all the properties and types with the correct values' do
|
194
198
|
expected_results = [{
|
199
|
+
vocabulary: Mida::Vocabulary::Generic,
|
195
200
|
type: nil,
|
196
201
|
id: nil,
|
197
202
|
properties: {
|
@@ -238,11 +243,13 @@ describe Mida::Document, 'when run against a full html document containing one i
|
|
238
243
|
|
239
244
|
it 'should return all the properties and types with the correct values' do
|
240
245
|
expected_results = [{
|
246
|
+
vocabulary: Mida::Vocabulary::Generic,
|
241
247
|
type: nil,
|
242
248
|
id: nil,
|
243
249
|
properties: {
|
244
250
|
'itemreviewed' => ['Romeo Pizza'],
|
245
251
|
'address' => [{
|
252
|
+
vocabulary: Mida::Vocabulary::Generic,
|
246
253
|
type: nil, id: nil, properties: {
|
247
254
|
'firstline' => ['237 Italian Way'],
|
248
255
|
'country' => ['United Kingdom']
|
@@ -287,15 +294,18 @@ describe Mida::Document, 'when run against a full html document containing one i
|
|
287
294
|
|
288
295
|
it 'should return all the properties and types with the correct values' do
|
289
296
|
expected_results = [{
|
297
|
+
vocabulary: Mida::Vocabulary::Generic,
|
290
298
|
type: nil,
|
291
299
|
id: nil,
|
292
300
|
properties: {
|
293
301
|
'itemreviewed' => ['Romeo Pizza'],
|
294
302
|
'address' => [{
|
303
|
+
vocabulary: Mida::Vocabulary::Generic,
|
295
304
|
type: nil,
|
296
305
|
id: nil,
|
297
306
|
properties: {
|
298
307
|
'firstline' => [{
|
308
|
+
vocabulary: Mida::Vocabulary::Generic,
|
299
309
|
type: nil,
|
300
310
|
id: nil,
|
301
311
|
properties: {
|
@@ -351,6 +361,7 @@ describe Mida::Document, 'when run against a full html document containing one i
|
|
351
361
|
|
352
362
|
it 'should return all the properties and types with the correct values' do
|
353
363
|
expected_results = [{
|
364
|
+
vocabulary: Mida::Vocabulary::Generic,
|
354
365
|
type: 'http://data-vocabulary.org/Review',
|
355
366
|
id: nil,
|
356
367
|
properties: {
|
@@ -412,6 +423,7 @@ describe Mida::Document, 'when run against a full html document containing two n
|
|
412
423
|
|
413
424
|
it 'should return all the properties and types with the correct values for 1st itemscope' do
|
414
425
|
expected_results = [{
|
426
|
+
vocabulary: Mida::Vocabulary::Generic,
|
415
427
|
type: 'http://data-vocabulary.org/Review',
|
416
428
|
id: nil,
|
417
429
|
properties: {
|
@@ -424,6 +436,7 @@ describe Mida::Document, 'when run against a full html document containing two n
|
|
424
436
|
|
425
437
|
it 'should return all the properties from the text for 2nd itemscope' do
|
426
438
|
expected_results = [{
|
439
|
+
vocabulary: Mida::Vocabulary::Generic,
|
427
440
|
type: 'http://data-vocabulary.org/Organization',
|
428
441
|
id: nil,
|
429
442
|
properties: {
|
@@ -474,12 +487,14 @@ describe Mida::Document, 'when run against a full html document containing one
|
|
474
487
|
context "when looking at the outer vocabulary" do
|
475
488
|
it 'should return all the properties from the text with the correct values' do
|
476
489
|
expected_results = [{
|
490
|
+
vocabulary: Mida::Vocabulary::Generic,
|
477
491
|
type: 'http://data-vocabulary.org/Product',
|
478
492
|
id: nil,
|
479
493
|
properties: {
|
480
494
|
'name' => ['DC07'],
|
481
495
|
'brand' => ['Dyson'],
|
482
496
|
'review' => [{
|
497
|
+
vocabulary: Mida::Vocabulary::Generic,
|
483
498
|
type: 'http://data-vocabulary.org/Review-aggregate',
|
484
499
|
id: nil,
|
485
500
|
properties: {
|
@@ -580,11 +595,13 @@ describe Mida::Document, 'when run against a document using itemrefs' do
|
|
580
595
|
|
581
596
|
it 'should return all the properties from the text with the correct values' do
|
582
597
|
expected_results = [{
|
598
|
+
vocabulary: Mida::Vocabulary::Generic,
|
583
599
|
type: nil,
|
584
600
|
id: nil,
|
585
601
|
properties: {
|
586
602
|
'name' => ['Amanda'],
|
587
603
|
'band' => [{
|
604
|
+
vocabulary: Mida::Vocabulary::Generic,
|
588
605
|
type: nil,
|
589
606
|
id: nil,
|
590
607
|
properties: {
|
@@ -634,13 +651,15 @@ describe Mida::Document, 'when run against a document using multiple itemprops w
|
|
634
651
|
|
635
652
|
it 'should return all the properties from the text with the correct values' do
|
636
653
|
expected_results = [{
|
654
|
+
vocabulary: Mida::Vocabulary::Generic,
|
637
655
|
type: 'icecreams',
|
638
656
|
id: nil,
|
639
657
|
properties: {
|
640
658
|
'flavour' => [
|
641
659
|
'Lemon sorbet',
|
642
660
|
'Apricot sorbet',
|
643
|
-
{
|
661
|
+
{ vocabulary: Mida::Vocabulary::Generic,
|
662
|
+
type: 'icecream-type',
|
644
663
|
id: nil,
|
645
664
|
properties: {
|
646
665
|
'fruit' => ['Strawberry'],
|
@@ -671,6 +690,7 @@ describe Mida::Document, 'when run against a document using an itemprop with mul
|
|
671
690
|
|
672
691
|
it 'should return all the properties from the text with the correct values' do
|
673
692
|
expected_results = [{
|
693
|
+
vocabulary: Mida::Vocabulary::Generic,
|
674
694
|
type: nil,
|
675
695
|
id: nil,
|
676
696
|
properties: {
|
@@ -682,3 +702,63 @@ describe Mida::Document, 'when run against a document using an itemprop with mul
|
|
682
702
|
test_parsing(@md, %r{}, expected_results)
|
683
703
|
end
|
684
704
|
end
|
705
|
+
|
706
|
+
describe Mida::Document, 'when run against a full html document containing an itemtype that matches a registered vocabulary' do
|
707
|
+
|
708
|
+
before do
|
709
|
+
html = '
|
710
|
+
<html><body>
|
711
|
+
There is some text here
|
712
|
+
<div>
|
713
|
+
and also some here
|
714
|
+
<div itemscope itemtype="http://data-vocabulary.org/Review">
|
715
|
+
<span itemprop="itemreviewed">Romeo Pizza</span>
|
716
|
+
Reviewed by <span itemprop="reviewer">Ulysses Grant</span> on
|
717
|
+
<time itemprop="dtreviewed" datetime="2009-01-06">Jan 6</time>.
|
718
|
+
<span itemprop="summary">Delicious, tasty pizza in Eastlake!</span>
|
719
|
+
<span itemprop="description">This is a very nice pizza place.</span>
|
720
|
+
Rating: <span itemprop="rating">4.5</span>
|
721
|
+
</div>
|
722
|
+
</div>
|
723
|
+
</body></html>
|
724
|
+
'
|
725
|
+
|
726
|
+
class Review < Mida::VocabularyDesc
|
727
|
+
itemtype %r{http://data-vocabulary.org/Review}
|
728
|
+
has_one 'itemreviewed', 'reviewer', 'dtreviewed', 'summary'
|
729
|
+
has_one 'rating', 'description'
|
730
|
+
end
|
731
|
+
Mida::Vocabulary.register(Review)
|
732
|
+
|
733
|
+
@md = Mida::Document.new(html)
|
734
|
+
|
735
|
+
end
|
736
|
+
|
737
|
+
it_should_behave_like 'one root itemscope'
|
738
|
+
|
739
|
+
it '#search should match against Review' do
|
740
|
+
@md.search(Review).size.should == 1
|
741
|
+
end
|
742
|
+
|
743
|
+
it 'should specify the correct type' do
|
744
|
+
@md.search(Review).first.type.should == 'http://data-vocabulary.org/Review'
|
745
|
+
end
|
746
|
+
|
747
|
+
it 'should return all the properties and types with the correct values' do
|
748
|
+
expected_results = [{
|
749
|
+
vocabulary: Review,
|
750
|
+
type: 'http://data-vocabulary.org/Review',
|
751
|
+
id: nil,
|
752
|
+
properties: {
|
753
|
+
'itemreviewed' => ['Romeo Pizza'],
|
754
|
+
'reviewer' => ['Ulysses Grant'],
|
755
|
+
'dtreviewed' => ['2009-01-06'],
|
756
|
+
'summary' => ['Delicious, tasty pizza in Eastlake!'],
|
757
|
+
'description' => ['This is a very nice pizza place.'],
|
758
|
+
'rating' => ['4.5']
|
759
|
+
}
|
760
|
+
}]
|
761
|
+
test_parsing(@md, Review, expected_results)
|
762
|
+
end
|
763
|
+
|
764
|
+
end
|
data/spec/item_spec.rb
CHANGED
@@ -17,6 +17,10 @@ describe Mida::Item, 'when initialized with an itemscope containing just itempro
|
|
17
17
|
@item = Mida::Item.new(itemscope_el)
|
18
18
|
end
|
19
19
|
|
20
|
+
it '#vocabulary should return the correct vocabulary' do
|
21
|
+
@item.vocabulary.should == Mida::Vocabulary::Generic
|
22
|
+
end
|
23
|
+
|
20
24
|
it '#type should return the correct type' do
|
21
25
|
@item.type.should == nil
|
22
26
|
end
|
@@ -34,7 +38,7 @@ describe Mida::Item, 'when initialized with an itemscope containing just itempro
|
|
34
38
|
|
35
39
|
it '#to_h should return the correct type and properties' do
|
36
40
|
@item.to_h.should == {
|
37
|
-
type: nil, id: nil, properties: {
|
41
|
+
vocabulary: Mida::Vocabulary::Generic, type: nil, id: nil, properties: {
|
38
42
|
'first_name' => ['Lorry'],
|
39
43
|
'last_name' => ['Woodman']
|
40
44
|
}
|
@@ -49,6 +53,10 @@ describe Mida::Item, 'when initialized with an itemscope containing just itempro
|
|
49
53
|
@item = Mida::Item.new(itemscope_el)
|
50
54
|
end
|
51
55
|
|
56
|
+
it '#vocabulary should return the correct vocabulary' do
|
57
|
+
@item.vocabulary.should == Mida::Vocabulary::Generic
|
58
|
+
end
|
59
|
+
|
52
60
|
it '#type should return the correct type' do
|
53
61
|
@item.type.should == 'person'
|
54
62
|
end
|
@@ -66,6 +74,7 @@ describe Mida::Item, 'when initialized with an itemscope containing just itempro
|
|
66
74
|
|
67
75
|
it '#to_h should return the correct type and properties' do
|
68
76
|
@item.to_h.should == {
|
77
|
+
vocabulary: Mida::Vocabulary::Generic,
|
69
78
|
type: 'person',
|
70
79
|
id: nil,
|
71
80
|
properties: {
|
@@ -112,6 +121,10 @@ describe Mida::Item, 'when initialized with an itemscope containing itemprops su
|
|
112
121
|
@item.type.should == 'person'
|
113
122
|
end
|
114
123
|
|
124
|
+
it '#vocabulary should return the correct vocabulary' do
|
125
|
+
@item.vocabulary.should == Mida::Vocabulary::Generic
|
126
|
+
end
|
127
|
+
|
115
128
|
it '#id should return the correct id' do
|
116
129
|
@item.id.should == nil
|
117
130
|
end
|
@@ -125,6 +138,7 @@ describe Mida::Item, 'when initialized with an itemscope containing itemprops su
|
|
125
138
|
|
126
139
|
it '#to_h should return the correct type and properties' do
|
127
140
|
@item.to_h.should == {
|
141
|
+
vocabulary: Mida::Vocabulary::Generic,
|
128
142
|
type: 'person',
|
129
143
|
id: nil,
|
130
144
|
properties: {
|
@@ -145,6 +159,10 @@ describe Mida::Item, "when initialized with an itemscope containing itemprops
|
|
145
159
|
@item = Mida::Item.new(itemscope)
|
146
160
|
end
|
147
161
|
|
162
|
+
it '#vocabulary should return the correct vocabulary' do
|
163
|
+
@item.vocabulary.should == Mida::Vocabulary::Generic
|
164
|
+
end
|
165
|
+
|
148
166
|
it '#type should return the correct type' do
|
149
167
|
@item.type.should == nil
|
150
168
|
end
|
@@ -161,6 +179,7 @@ describe Mida::Item, "when initialized with an itemscope containing itemprops
|
|
161
179
|
|
162
180
|
it '#to_h should return the correct type and properties' do
|
163
181
|
@item.to_h.should == {
|
182
|
+
vocabulary: Mida::Vocabulary::Generic,
|
164
183
|
type: nil,
|
165
184
|
id: nil,
|
166
185
|
properties: {
|
@@ -184,6 +203,10 @@ describe Mida::Item, "when initialized with an itemscope containing an itemprop
|
|
184
203
|
@item = Mida::Item.new(itemscope)
|
185
204
|
end
|
186
205
|
|
206
|
+
it '#vocabulary should return the correct vocabulary' do
|
207
|
+
@item.vocabulary.should == Mida::Vocabulary::Generic
|
208
|
+
end
|
209
|
+
|
187
210
|
it '#type should return the correct type' do
|
188
211
|
@item.type.should == nil
|
189
212
|
end
|
@@ -201,6 +224,7 @@ describe Mida::Item, "when initialized with an itemscope containing an itemprop
|
|
201
224
|
|
202
225
|
it '#to_h should return the correct type and properties' do
|
203
226
|
@item.to_h.should == {
|
227
|
+
vocabulary: Mida::Vocabulary::Generic,
|
204
228
|
type: nil,
|
205
229
|
id: nil,
|
206
230
|
properties: {
|
@@ -239,6 +263,10 @@ describe Mida::Item, 'when initialized with an itemscope containing itemprops wi
|
|
239
263
|
@item = Mida::Item.new(icecreams)
|
240
264
|
end
|
241
265
|
|
266
|
+
it '#vocabulary should return the correct vocabulary' do
|
267
|
+
@item.vocabulary.should == Mida::Vocabulary::Generic
|
268
|
+
end
|
269
|
+
|
242
270
|
it '#type should return the correct type' do
|
243
271
|
@item.type.should == 'icecreams'
|
244
272
|
end
|
@@ -259,13 +287,15 @@ describe Mida::Item, 'when initialized with an itemscope containing itemprops wi
|
|
259
287
|
|
260
288
|
it '#to_h should return the correct type and properties' do
|
261
289
|
@item.to_h.should == {
|
290
|
+
vocabulary: Mida::Vocabulary::Generic,
|
262
291
|
type: 'icecreams',
|
263
292
|
id: nil,
|
264
293
|
properties: {
|
265
294
|
'flavour' => [
|
266
295
|
'Lemon Sorbet',
|
267
296
|
'Apricot Sorbet',
|
268
|
-
{
|
297
|
+
{ vocabulary: Mida::Vocabulary::Generic,
|
298
|
+
type: 'icecream-type',
|
269
299
|
id: nil,
|
270
300
|
properties: {
|
271
301
|
'fruit' => ['Strawberry'],
|
@@ -306,6 +336,10 @@ describe Mida::Item, 'when initialized with an itemscope containing itemrefs' do
|
|
306
336
|
@item = Mida::Item.new(age_div)
|
307
337
|
end
|
308
338
|
|
339
|
+
it '#vocabulary should return the correct vocabulary' do
|
340
|
+
@item.vocabulary.should == Mida::Vocabulary::Generic
|
341
|
+
end
|
342
|
+
|
309
343
|
it '#type should return the correct type' do
|
310
344
|
@item.type.should == nil
|
311
345
|
end
|
@@ -324,12 +358,14 @@ describe Mida::Item, 'when initialized with an itemscope containing itemrefs' do
|
|
324
358
|
|
325
359
|
it '#to_h should return the correct type and properties' do
|
326
360
|
@item.to_h.should == {
|
361
|
+
vocabulary: Mida::Vocabulary::Generic,
|
327
362
|
type: nil,
|
328
363
|
id: nil,
|
329
364
|
properties: {
|
330
365
|
'age' => ['30'],
|
331
366
|
'name' => ['Amanda'],
|
332
367
|
'band' => [{
|
368
|
+
vocabulary: Mida::Vocabulary::Generic,
|
333
369
|
type: nil,
|
334
370
|
id: nil,
|
335
371
|
properties: {
|
@@ -358,6 +394,10 @@ describe Mida::Item, 'when initialized with an itemscope containing an itemid' d
|
|
358
394
|
@item = Mida::Item.new(book)
|
359
395
|
end
|
360
396
|
|
397
|
+
it '#vocabulary should return the correct vocabulary' do
|
398
|
+
@item.vocabulary.should == Mida::Vocabulary::Generic
|
399
|
+
end
|
400
|
+
|
361
401
|
it '#type should return the correct type' do
|
362
402
|
@item.type.should == 'book'
|
363
403
|
end
|
@@ -375,6 +415,7 @@ describe Mida::Item, 'when initialized with an itemscope containing an itemid' d
|
|
375
415
|
|
376
416
|
it '#to_h should return the correct type and properties' do
|
377
417
|
@item.to_h.should == {
|
418
|
+
vocabulary: Mida::Vocabulary::Generic,
|
378
419
|
type: 'book',
|
379
420
|
id: 'urn:isbn:978-1-849510-50-9',
|
380
421
|
properties: {
|
@@ -425,6 +466,10 @@ describe Mida::Item, 'when initialized with an itemscope containing itemscopes a
|
|
425
466
|
before do
|
426
467
|
end
|
427
468
|
|
469
|
+
it '#vocabulary should return the correct vocabulary' do
|
470
|
+
@item.vocabulary.should == Mida::Vocabulary::Generic
|
471
|
+
end
|
472
|
+
|
428
473
|
it '#type should return the correct type' do
|
429
474
|
@item.type.should == 'review'
|
430
475
|
end
|
@@ -443,18 +488,21 @@ describe Mida::Item, 'when initialized with an itemscope containing itemscopes a
|
|
443
488
|
|
444
489
|
it '#to_h should return the correct type and properties' do
|
445
490
|
@item.to_h.should == {
|
491
|
+
vocabulary: Mida::Vocabulary::Generic,
|
446
492
|
type: 'review',
|
447
493
|
id: nil,
|
448
494
|
properties: {
|
449
495
|
'item_name' => ['Acme Anvil'],
|
450
496
|
'rating' => ['5'],
|
451
497
|
'reviewer' => [{
|
498
|
+
vocabulary: Mida::Vocabulary::Generic,
|
452
499
|
type: 'person',
|
453
500
|
id: nil,
|
454
501
|
properties: {
|
455
502
|
'first_name' => ['Lorry'],
|
456
503
|
'last_name' => ['Woodman'],
|
457
504
|
'represents' => [{
|
505
|
+
vocabulary: Mida::Vocabulary::Generic,
|
458
506
|
type: 'organization',
|
459
507
|
id: nil,
|
460
508
|
properties: {
|
@@ -467,3 +515,70 @@ describe Mida::Item, 'when initialized with an itemscope containing itemscopes a
|
|
467
515
|
}
|
468
516
|
end
|
469
517
|
end
|
518
|
+
|
519
|
+
describe Mida::Item, 'when initialized with an itemscope that matches a non-generic registered vocabulary' do
|
520
|
+
before do
|
521
|
+
|
522
|
+
class Colour < Mida::VocabularyDesc
|
523
|
+
itemtype %r{http://example.com/vocab/colour}
|
524
|
+
has_one 'red', 'green', 'blue'
|
525
|
+
end
|
526
|
+
Mida::Vocabulary.register(Colour)
|
527
|
+
|
528
|
+
class Person < Mida::VocabularyDesc
|
529
|
+
itemtype %r{http://example.com/vocab/person}
|
530
|
+
has_one 'name'
|
531
|
+
has_one 'url'
|
532
|
+
has_many 'limbs'
|
533
|
+
has_many 'favourite-colours' do
|
534
|
+
types Colour
|
535
|
+
end
|
536
|
+
end
|
537
|
+
Mida::Vocabulary.register(Person)
|
538
|
+
|
539
|
+
red = mock_element('span', {'itemprop' => 'red'}, '0xFF')
|
540
|
+
green = mock_element('span', {'itemprop' => 'green'}, '0x00')
|
541
|
+
blue = mock_element('span', {'itemprop' => 'blue'}, '0xFF')
|
542
|
+
purple = mock_element('div', {'itemscope' => true,
|
543
|
+
'itemtype' => 'http://example.com/vocab/colour',
|
544
|
+
'itemprop' => 'favourite-colours'},
|
545
|
+
nil, [red, green, blue])
|
546
|
+
orange = mock_element('span', {'itemprop' => 'favourite-colours'}, 'Orange')
|
547
|
+
|
548
|
+
name1 = mock_element('span', {'itemprop' => 'name'}, 'Lawrence Woodman')
|
549
|
+
name2 = mock_element('span', {'itemprop' => 'name'}, 'Lorry Woodman')
|
550
|
+
url = mock_element('a', {'itemprop' => 'url', 'href' => 'http://example.com/myhomepage'})
|
551
|
+
arm = mock_element('span', {'itemprop' => 'limbs'}, 'Arm')
|
552
|
+
leg = mock_element('span', {'itemprop' => 'limbs'}, 'Leg')
|
553
|
+
robert_wilson = mock_element('span', {'itemprop' => 'favourite-author'}, 'Robert Wilson')
|
554
|
+
itemscope_el = mock_element('div', {'itemscope' => true,
|
555
|
+
'itemtype' =>'http://example.com/vocab/person'
|
556
|
+
}, nil, [name1, name2, url, arm, leg, purple, orange, robert_wilson])
|
557
|
+
@item = Mida::Item.new(itemscope_el, "http://example.com")
|
558
|
+
end
|
559
|
+
|
560
|
+
it '#vocabulary should return the correct vocabulary' do
|
561
|
+
@item.vocabulary.should == Person
|
562
|
+
end
|
563
|
+
|
564
|
+
it 'should reject properties that have multiple values if has_one specified' do
|
565
|
+
@item.properties.should_not have_key('name')
|
566
|
+
end
|
567
|
+
|
568
|
+
it 'should accept properties that have a single value if has_one specified' do
|
569
|
+
@item.properties['url'].should == ['http://example.com/myhomepage']
|
570
|
+
end
|
571
|
+
|
572
|
+
it 'should accept properties that have a many values if has_many specified' do
|
573
|
+
@item.properties['limbs'].should == ['Arm', 'Leg']
|
574
|
+
end
|
575
|
+
|
576
|
+
it 'should register properties using the specified types' do
|
577
|
+
@item.properties['favourite-colours'].size.should == 1
|
578
|
+
@item.properties['favourite-colours'].first.vocabulary.should == Colour
|
579
|
+
end
|
580
|
+
|
581
|
+
it 'should reject properties that are not specified' do
|
582
|
+
@item.properties.should_not have_key('favourite-author')
|
583
|
+
end
|
584
|
+
end
|
@@ -2,27 +2,27 @@ require_relative 'spec_helper'
|
|
2
2
|
require_relative '../lib/mida'
|
3
3
|
|
4
4
|
|
5
|
-
describe Mida::
|
5
|
+
describe Mida::Itemprop, 'when parsing an element without an itemprop attribute' do
|
6
6
|
before do
|
7
7
|
@element = mock_element('span')
|
8
8
|
end
|
9
9
|
|
10
10
|
it '#parse should return an empty Hash' do
|
11
|
-
Mida::
|
11
|
+
Mida::Itemprop.parse(@element).should == {}
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
-
describe Mida::
|
15
|
+
describe Mida::Itemprop, 'when parsing an element with one itemprop name' do
|
16
16
|
before do
|
17
17
|
@element = mock_element('span', {'itemprop' => 'reviewer'}, 'Lorry Woodman')
|
18
18
|
end
|
19
19
|
|
20
20
|
it '#parse should return a Hash with the correct name/value pair' do
|
21
|
-
Mida::
|
21
|
+
Mida::Itemprop.parse(@element).should == {'reviewer' => 'Lorry Woodman'}
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
-
describe Mida::
|
25
|
+
describe Mida::Itemprop, "when parsing an element who's inner text contains\
|
26
26
|
non microdata elements" do
|
27
27
|
before do
|
28
28
|
html = '<span itemprop="reviewer">Lorry <em>Woodman</em></span>'
|
@@ -31,11 +31,11 @@ describe Mida::Property, "when parsing an element who's inner text contains\
|
|
31
31
|
end
|
32
32
|
|
33
33
|
it '#parse should return a Hash with the correct name/value pair' do
|
34
|
-
Mida::
|
34
|
+
Mida::Itemprop.parse(@itemprop).should == {'reviewer' => 'Lorry Woodman'}
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
|
-
describe Mida::
|
38
|
+
describe Mida::Itemprop, 'when parsing an itemscope element that has a relative url' do
|
39
39
|
before do
|
40
40
|
|
41
41
|
# The first_name element
|
@@ -54,7 +54,7 @@ describe Mida::Property, 'when parsing an itemscope element that has a relative
|
|
54
54
|
end
|
55
55
|
|
56
56
|
it '#parse should return a Hash with the correct name/value pair' do
|
57
|
-
property = Mida::
|
57
|
+
property = Mida::Itemprop.parse(@itemscope_el, "http://example.com")
|
58
58
|
property.size.should == 1
|
59
59
|
reviewer = property['reviewer']
|
60
60
|
reviewer.type.should == 'person'
|
@@ -66,13 +66,13 @@ describe Mida::Property, 'when parsing an itemscope element that has a relative
|
|
66
66
|
end
|
67
67
|
end
|
68
68
|
|
69
|
-
describe Mida::
|
69
|
+
describe Mida::Itemprop, 'when parsing an element with multiple itemprop names' do
|
70
70
|
before do
|
71
71
|
@element = mock_element('span', {'itemprop' => 'reviewer friend person'}, 'the property text')
|
72
72
|
end
|
73
73
|
|
74
74
|
it '#parse should return a Hash with the name/value pairs' do
|
75
|
-
Mida::
|
75
|
+
Mida::Itemprop.parse(@element).should == {
|
76
76
|
'reviewer' => 'the property text',
|
77
77
|
'friend' => 'the property text',
|
78
78
|
'person' => 'the property text'
|
@@ -80,7 +80,7 @@ describe Mida::Property, 'when parsing an element with multiple itemprop names'
|
|
80
80
|
end
|
81
81
|
end
|
82
82
|
|
83
|
-
describe Mida::
|
83
|
+
describe Mida::Itemprop, 'when parsing an element with non text content url values' do
|
84
84
|
before :all do
|
85
85
|
URL_ELEMENTS = {
|
86
86
|
'a' => 'href', 'area' => 'href',
|
@@ -98,7 +98,7 @@ describe Mida::Property, 'when parsing an element with non text content url valu
|
|
98
98
|
url = 'register/index.html'
|
99
99
|
URL_ELEMENTS.each do |tag, attr|
|
100
100
|
element = mock_element(tag, {'itemprop' => 'url', attr => url})
|
101
|
-
Mida::
|
101
|
+
Mida::Itemprop.parse(element).should == {'url' => ''}
|
102
102
|
end
|
103
103
|
end
|
104
104
|
|
@@ -112,7 +112,7 @@ describe Mida::Property, 'when parsing an element with non text content url valu
|
|
112
112
|
urls.each do |url|
|
113
113
|
URL_ELEMENTS.each do |tag, attr|
|
114
114
|
element = mock_element(tag, {'itemprop' => 'url', attr => url})
|
115
|
-
Mida::
|
115
|
+
Mida::Itemprop.parse(element).should == {'url' => url}
|
116
116
|
end
|
117
117
|
end
|
118
118
|
end
|
@@ -127,7 +127,7 @@ describe Mida::Property, 'when parsing an element with non text content url valu
|
|
127
127
|
url = 'register/index.html'
|
128
128
|
URL_ELEMENTS.each do |tag, attr|
|
129
129
|
element = mock_element(tag, {'itemprop' => 'url', attr => url})
|
130
|
-
Mida::
|
130
|
+
Mida::Itemprop.parse(element, @page_url).should ==
|
131
131
|
{'url' => 'http://example.com/test/register/index.html'}
|
132
132
|
end
|
133
133
|
end
|
@@ -142,7 +142,7 @@ describe Mida::Property, 'when parsing an element with non text content url valu
|
|
142
142
|
urls.each do |url|
|
143
143
|
URL_ELEMENTS.each do |tag, attr|
|
144
144
|
element = mock_element(tag, {'itemprop' => 'url', attr => url})
|
145
|
-
Mida::
|
145
|
+
Mida::Itemprop.parse(element, @page_url).should == {'url' => url}
|
146
146
|
end
|
147
147
|
end
|
148
148
|
end
|
@@ -150,16 +150,16 @@ describe Mida::Property, 'when parsing an element with non text content url valu
|
|
150
150
|
end
|
151
151
|
end
|
152
152
|
|
153
|
-
describe Mida::
|
153
|
+
describe Mida::Itemprop, 'when parsing an element with non text content non url values' do
|
154
154
|
it 'should get values from a meta content attribute' do
|
155
155
|
element = mock_element('meta', {'itemprop' => 'reviewer',
|
156
156
|
'content' => 'Lorry Woodman'})
|
157
|
-
Mida::
|
157
|
+
Mida::Itemprop.parse(element).should == {'reviewer' => 'Lorry Woodman'}
|
158
158
|
end
|
159
159
|
|
160
160
|
it 'should get time from an time datatime attribute' do
|
161
161
|
element = mock_element('time', {'itemprop' => 'dtreviewed',
|
162
162
|
'datetime' => '2011-04-04'})
|
163
|
-
Mida::
|
163
|
+
Mida::Itemprop.parse(element).should == {'dtreviewed' => '2011-04-04'}
|
164
164
|
end
|
165
165
|
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
require_relative '../lib/mida'
|
3
|
+
|
4
|
+
describe Mida::VocabularyDesc, 'when subclassed and given has statements with no blocks' do
|
5
|
+
before do
|
6
|
+
class Organization < Mida::VocabularyDesc
|
7
|
+
itemtype %r{http://example\.com.*?organization$}i
|
8
|
+
has_one 'name'
|
9
|
+
has_many 'tel', 'url'
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
it '#itemtype should return the correct regexp' do
|
14
|
+
Organization.itemtype.should == %r{http://example\.com.*?organization$}i
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'should specify name to appear once' do
|
18
|
+
Organization.prop_spec['name'][:num].should == :one
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should specify tel and url to appear many times' do
|
22
|
+
Organization.prop_spec['tel'][:num].should == :many
|
23
|
+
Organization.prop_spec['url'][:num].should == :many
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe Mida::VocabularyDesc, 'when subclassed and given has statements with blocks' do
|
28
|
+
before do
|
29
|
+
class Rating < Mida::VocabularyDesc
|
30
|
+
itemtype %r{http://example\.com.*?rating$}i
|
31
|
+
has_one 'best', 'value'
|
32
|
+
end
|
33
|
+
|
34
|
+
class Comment < Mida::VocabularyDesc
|
35
|
+
itemtype %r{http://example\.com.*?comment$}i
|
36
|
+
has_one 'commentor', 'comment'
|
37
|
+
end
|
38
|
+
|
39
|
+
class Review < Mida::VocabularyDesc
|
40
|
+
itemtype %r{http://example\.com.*?review$}i
|
41
|
+
has_one 'itemreviewed'
|
42
|
+
has_one 'rating' do
|
43
|
+
types Rating, String
|
44
|
+
end
|
45
|
+
has_many 'comments' do
|
46
|
+
types Comment
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
it '#itemtype should return the correct regexp' do
|
52
|
+
Review.itemtype.should == %r{http://example\.com.*?review$}i
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'should specify itemreviewed to appear once' do
|
56
|
+
Review.prop_spec['itemreviewed'][:num].should == :one
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'should specify that itemreviewed only have the type String' do
|
60
|
+
Review.prop_spec['itemreviewed'][:types].should == [String]
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'should specify rating to appear once' do
|
64
|
+
Review.prop_spec['rating'][:num].should == :one
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'should specify rating to only have the types: Rating, String' do
|
68
|
+
Review.prop_spec['rating'][:types].should == [Rating, String]
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'should specify comments to appear many times' do
|
72
|
+
Review.prop_spec['comments'][:num].should == :many
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'should specify that comments only have the type Comment' do
|
76
|
+
Review.prop_spec['comments'][:types].should == [Comment]
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe Mida::VocabularyDesc, 'when subclassed and used with :any for properties and types' do
|
81
|
+
before do
|
82
|
+
class Person < Mida::VocabularyDesc
|
83
|
+
itemtype %r{}
|
84
|
+
has_one 'name'
|
85
|
+
has_many :any do
|
86
|
+
types :any
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
it '#itemtype should return the correct regexp' do
|
92
|
+
Person.itemtype.should == %r{}
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'should specify that name only appears once' do
|
96
|
+
Person.prop_spec['name'][:num].should == :one
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'should specify that any other property can appear many times' do
|
100
|
+
Person.prop_spec[:any][:num].should == :many
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'should specify that any other property can have any type' do
|
104
|
+
Person.prop_spec[:any][:types].should == [:any]
|
105
|
+
end
|
106
|
+
end
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: mida
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.
|
5
|
+
version: 0.2.0
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Lawrence Woodman
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2011-
|
13
|
+
date: 2011-05-03 00:00:00 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: nokogiri
|
@@ -46,13 +46,17 @@ extra_rdoc_files:
|
|
46
46
|
- CHANGELOG.rdoc
|
47
47
|
files:
|
48
48
|
- lib/mida.rb
|
49
|
-
- lib/mida/property.rb
|
50
49
|
- lib/mida/item.rb
|
51
50
|
- lib/mida/document.rb
|
52
|
-
-
|
51
|
+
- lib/mida/vocabulary/generic.rb
|
52
|
+
- lib/mida/vocabularydesc.rb
|
53
|
+
- lib/mida/itemprop.rb
|
54
|
+
- lib/mida/vocabulary.rb
|
55
|
+
- spec/itemprop_spec.rb
|
53
56
|
- spec/document_spec.rb
|
54
57
|
- spec/item_spec.rb
|
55
58
|
- spec/spec_helper.rb
|
59
|
+
- spec/vocabularydesc_spec.rb
|
56
60
|
- TODO.rdoc
|
57
61
|
- CHANGELOG.rdoc
|
58
62
|
- README.rdoc
|