gearbox 0.1.0 → 0.1.10
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/Gemfile +5 -3
- data/Rakefile +1 -0
- data/VERSION +1 -1
- data/bin/gearbox +9 -0
- data/gearbox.gemspec +134 -0
- data/lib/gearbox.rb +124 -5
- data/lib/gearbox/attribute.rb +128 -0
- data/lib/gearbox/mixins/active_model_implementation.rb +27 -0
- data/lib/gearbox/mixins/resource.rb +20 -4
- data/lib/gearbox/mixins/semantic_accessors.rb +128 -89
- data/lib/gearbox/mixins/subject_methods.rb +88 -0
- data/lib/gearbox/rdf_collection.rb +22 -8
- data/lib/gearbox/types.rb +9 -8
- data/lib/gearbox/vocabulary.rb +149 -0
- data/lib/pry_utilities.rb +71 -0
- data/scratch/4s.rb +335 -0
- data/scratch/DEVELOPMENT_NOTES.md +85 -0
- data/scratch/actionable.md +34 -0
- data/scratch/ccrdf.html-rdfa.nq +100 -0
- data/scratch/foo.rb +17 -0
- data/scratch/index.rdf +7932 -0
- data/scratch/j2.rb +10 -0
- data/scratch/junk.rb +16 -0
- data/scratch/out.rb +67 -0
- data/spec/gearbox/attribute_spec.rb +455 -0
- data/spec/gearbox/mixins/active_model_implementation_spec.rb +18 -0
- data/spec/gearbox/mixins/ad_hoc_properties_spec.rb +44 -44
- data/spec/gearbox/mixins/resource_spec.rb +47 -8
- data/spec/gearbox/mixins/semantic_accessors_spec.rb +72 -43
- data/spec/gearbox/mixins/subject_methods_spec.rb +126 -0
- data/spec/gearbox/rdf_collection_spec.rb +28 -2
- data/spec/gearbox_spec.rb +6 -2
- data/spec/spec_helper.rb +1 -0
- metadata +150 -42
- data/Gemfile.lock +0 -138
- data/lib/examples/audience.rb +0 -24
- data/lib/examples/person.rb +0 -29
- data/lib/examples/reference.rb +0 -38
- data/lib/examples/theme.rb +0 -8
- data/spec/examples/audience_spec.rb +0 -28
- data/spec/examples/person_spec.rb +0 -45
- data/spec/examples/reference_spec.rb +0 -43
- data/spec/examples/theme_spec.rb +0 -137
@@ -0,0 +1,18 @@
|
|
1
|
+
require_relative '../../spec_helper'
|
2
|
+
|
3
|
+
include Gearbox
|
4
|
+
|
5
|
+
describe ActiveModelImplementation do
|
6
|
+
|
7
|
+
before do
|
8
|
+
@class = Class.new do
|
9
|
+
include Gearbox::ActiveModelImplementation
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
let(:model) { @class.new }
|
14
|
+
subject { @class.new }
|
15
|
+
|
16
|
+
# I need to get the Lint working with the spec format. I'll need to read how they do that in MiniTest...
|
17
|
+
|
18
|
+
end
|
@@ -4,49 +4,49 @@ include Gearbox
|
|
4
4
|
|
5
5
|
describe AdHocProperties do
|
6
6
|
|
7
|
-
before do
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
end
|
14
|
-
|
15
|
-
subject { @class.new }
|
16
|
-
|
17
|
-
it "has an id getter and setter" do
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
end
|
22
|
-
|
23
|
-
# Concerned about the id and the model lifecycle.
|
24
|
-
it "offers a bnode, deriving from the id" do
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
end
|
29
|
-
|
30
|
-
it "generates a UUID for the bnode if the id is nil" do
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
end
|
36
|
-
|
37
|
-
it "has an attributes_list" do
|
38
|
-
|
39
|
-
|
40
|
-
end
|
41
|
-
|
42
|
-
# Excited about models that can take new properties ad hoc, therefore being more
|
43
|
-
# friendly to the underlying graph and the nature of semantic data generally.
|
44
|
-
it "can add_property with a predicate and an object" do
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
end
|
7
|
+
# before do
|
8
|
+
# @class = Class.new do
|
9
|
+
# def self.name; 'demo_class'; end
|
10
|
+
# include SemanticAccessors
|
11
|
+
# include AdHocProperties
|
12
|
+
# end
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
# subject { @class.new }
|
16
|
+
#
|
17
|
+
# it "has an id getter and setter" do
|
18
|
+
# id = 1
|
19
|
+
# subject.id = id
|
20
|
+
# subject.id.must_equal(id)
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# # Concerned about the id and the model lifecycle.
|
24
|
+
# it "offers a bnode, deriving from the id" do
|
25
|
+
# subject.id = 3
|
26
|
+
# subject.bnode.must_be_kind_of RDF::Node
|
27
|
+
# subject.bnode.id.must_equal "demo_class_3"
|
28
|
+
# end
|
29
|
+
#
|
30
|
+
# it "generates a UUID for the bnode if the id is nil" do
|
31
|
+
# subject.id.must_be_nil
|
32
|
+
# subject.bnode
|
33
|
+
# subject.id.wont_be_nil
|
34
|
+
# subject.bnode.id.must_equal "demo_class_#{subject.id}"
|
35
|
+
# end
|
36
|
+
#
|
37
|
+
# it "has an attributes_list" do
|
38
|
+
# subject.must_respond_to :attributes_list
|
39
|
+
# subject.attributes_list.must_be_kind_of RDFCollection
|
40
|
+
# end
|
41
|
+
#
|
42
|
+
# # Excited about models that can take new properties ad hoc, therefore being more
|
43
|
+
# # friendly to the underlying graph and the nature of semantic data generally.
|
44
|
+
# it "can add_property with a predicate and an object" do
|
45
|
+
# subject.add_property :field_name, :predicate, :object
|
46
|
+
# newly_created = subject.attributes_list[:field_name]
|
47
|
+
# newly_created.subject.id.must_equal subject.bnode.id
|
48
|
+
# newly_created.predicate.id.must_equal 'predicate'
|
49
|
+
# newly_created.object.id.must_equal 'object'
|
50
|
+
# end
|
51
51
|
|
52
52
|
end
|
@@ -6,27 +6,66 @@ describe Resource do
|
|
6
6
|
|
7
7
|
before do
|
8
8
|
@class = Class.new do
|
9
|
-
|
10
|
-
include Gearbox
|
9
|
+
include Gearbox::Resource
|
11
10
|
end
|
12
11
|
end
|
13
12
|
|
14
13
|
subject { @class.new }
|
15
14
|
|
16
|
-
|
17
|
-
|
18
|
-
|
15
|
+
# Rethinking this one, they will be much more robust soon.
|
16
|
+
# This is more for knowledge base discovery or throw-away models
|
17
|
+
# So there's a new approach on the horizon of my imagination.
|
18
|
+
# it "uses AdHocProperties" do
|
19
|
+
# @class.included_modules.must_include Gearbox::AdHocProperties
|
20
|
+
# end
|
19
21
|
|
20
22
|
it "uses SemanticAccessors" do
|
21
|
-
|
23
|
+
@class.included_modules.must_include Gearbox::SemanticAccessors
|
24
|
+
end
|
25
|
+
|
26
|
+
it "uses SubjectMethods" do
|
27
|
+
@class.included_modules.must_include Gearbox::SubjectMethods
|
28
|
+
end
|
29
|
+
|
30
|
+
it "uses ActiveModelImplementation" do
|
31
|
+
@class.included_modules.must_include Gearbox::ActiveModelImplementation
|
22
32
|
end
|
23
33
|
|
24
34
|
it "uses RDF::Mutable" do
|
25
|
-
|
35
|
+
@class.included_modules.must_include RDF::Mutable
|
26
36
|
end
|
27
37
|
|
28
38
|
it "uses RDF::Queryable" do
|
29
|
-
|
39
|
+
@class.included_modules.must_include RDF::Queryable
|
40
|
+
end
|
41
|
+
|
42
|
+
describe "Enumerable integration" do
|
43
|
+
it "has each defined on the model" do
|
44
|
+
subject.respond_to?(:each).must_equal true
|
45
|
+
end
|
46
|
+
|
47
|
+
it "produces RDF statements from the enumeration" do
|
48
|
+
@class.attribute :name, :predicate => RDF::FOAF.name
|
49
|
+
subject = @class.new(:name => "George")
|
50
|
+
subject.to_a.must_equal([RDF::Statement.new(subject.subject, RDF::FOAF.name, RDF::Literal.new("George"))])
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
describe "Load order" do
|
56
|
+
# Unfortunately, the load order is important here.
|
57
|
+
# There is only one example right now: id.
|
58
|
+
# id is part of the subject system. It's actually quite robust, so that any identification pattern
|
59
|
+
# can be implemented in Gearbox. That's handled in the SubjectMethods. The attribute system needs
|
60
|
+
# id for some ActiveModel goodness. So, I have to load SubjectMethods before SemanticAccessors.
|
61
|
+
# A recent MWRC kept picking on this dependency problem, but none of their suggestions would help
|
62
|
+
# make this code follow the Law of Demeter any better.
|
63
|
+
|
64
|
+
it "has an id for the attribute system" do
|
65
|
+
@class.attribute :name, :predicate => RDF::FOAF.name
|
66
|
+
subject = @class.new(:name => "George")
|
67
|
+
subject.attributes.must_equal({:id => subject.id, :name => "George"})
|
68
|
+
end
|
30
69
|
end
|
31
70
|
|
32
71
|
end
|
@@ -4,50 +4,79 @@ include Gearbox
|
|
4
4
|
|
5
5
|
describe SemanticAccessors do
|
6
6
|
|
7
|
-
before do
|
8
|
-
@class = Class.new do
|
9
|
-
def self.name; 'demo_class'; end
|
10
|
-
include SemanticAccessors
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
subject { @class.new }
|
15
|
-
|
16
|
-
it "has an rdf_collection" do
|
17
|
-
subject.must_respond_to :rdf_collection
|
18
|
-
subject.rdf_collection.must_be_kind_of RDFCollection
|
19
|
-
end
|
20
|
-
|
21
|
-
it "has an attribute_collection on the class" do
|
22
|
-
subject.class.must_respond_to :attribute_collection
|
23
|
-
subject.class.attribute_collection.must_be_kind_of AttributeCollection
|
24
|
-
end
|
25
|
-
|
26
|
-
it "has an attribute macro for setting up new attributes" do
|
27
|
-
@class.attribute :given_name, :predicate => RDF::FOAF.givenname
|
28
|
-
subject.given_name = "Frank"
|
29
|
-
subject.given_name.must_equal("Frank")
|
30
|
-
end
|
31
7
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
8
|
+
describe "Class methods" do
|
9
|
+
before do
|
10
|
+
@class = Class.new do
|
11
|
+
def self.name; 'demo_class'; end
|
12
|
+
include SemanticAccessors
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
it "uses an attributes hash" do
|
17
|
+
@class.attributes.must_be_kind_of Hash
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "attribute" do
|
21
|
+
it "has an attribute method" do
|
22
|
+
@class.respond_to?(:attribute).must_equal true
|
23
|
+
end
|
24
|
+
|
25
|
+
it "defines a setter and getter" do
|
26
|
+
@class.attribute(:name, :predicate => RDF::FOAF.name)
|
27
|
+
subject = @class.new
|
28
|
+
subject.respond_to?(:name).must_equal true
|
29
|
+
subject.respond_to?(:name=).must_equal true
|
30
|
+
end
|
31
|
+
|
32
|
+
it "stores the options + {:name => name} in the attributes hash" do
|
33
|
+
@class.attribute(:name, :predicate => RDF::FOAF.name)
|
34
|
+
@class.attributes[:name].must_equal({:name => :name, :predicate => RDF::FOAF.name})
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end # "Class methods"
|
50
38
|
|
51
|
-
|
39
|
+
describe "Instance methods" do
|
40
|
+
before do
|
41
|
+
@class = Class.new do
|
42
|
+
include SemanticAccessors
|
43
|
+
attribute :name, :predicate => RDF::FOAF.name
|
44
|
+
end
|
45
|
+
end
|
52
46
|
|
47
|
+
subject { @class.new }
|
48
|
+
|
49
|
+
it "creates a setter and a getter for each attribute" do
|
50
|
+
subject.name = "George"
|
51
|
+
subject.name.must_equal "George"
|
52
|
+
end
|
53
|
+
|
54
|
+
it "supports the attribute data types" do
|
55
|
+
# In fact, it supports the full attribute system, this is just a quick check.
|
56
|
+
@class.attribute :birthday, :predicate => RDF::FOAF.birthday, :datatype => RDF::XSD.date
|
57
|
+
subject.birthday = Time.now
|
58
|
+
subject.birthday.must_equal Time.now.to_date
|
59
|
+
end
|
60
|
+
|
61
|
+
it "creates an attributes hash from attribute values" do
|
62
|
+
subject.name = "George"
|
63
|
+
def subject.id; 1; end
|
64
|
+
subject.attributes.must_equal({:id => subject.id, :name => "George"})
|
65
|
+
end
|
66
|
+
|
67
|
+
it "uses the default attribute parameter to set defaults" do
|
68
|
+
@class.attribute :spanish_name, :predicate => RDF::FOAF.name, :language => :es, :default => "Jorge"
|
69
|
+
subject = @class.new
|
70
|
+
subject.spanish_name.must_equal "Jorge"
|
71
|
+
end
|
72
|
+
|
73
|
+
it "can take attribute values as an initialization hash" do
|
74
|
+
subject = @class.new(:name => "George")
|
75
|
+
subject.name.must_equal "George"
|
76
|
+
end
|
77
|
+
|
78
|
+
# TODO: Once I implement some finds via SPARQL, I should standardize the kind of data I'll be feeding
|
79
|
+
# the model initialization. At that point, either refactor the RDF::Statement feature in Attribute,
|
80
|
+
# or add it in the initialization process.
|
81
|
+
end # "Instance methods"
|
53
82
|
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
require_relative '../../spec_helper'
|
2
|
+
|
3
|
+
include Gearbox
|
4
|
+
|
5
|
+
describe SubjectMethods do
|
6
|
+
|
7
|
+
before do
|
8
|
+
@class = Class.new do
|
9
|
+
include SubjectMethods
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
let(:base_uri) { "http://example.com" }
|
14
|
+
subject { @class.new }
|
15
|
+
|
16
|
+
# =============
|
17
|
+
# = ID Method =
|
18
|
+
# =============
|
19
|
+
it "can define the id_method on the class level" do
|
20
|
+
@class.id_method :new_id
|
21
|
+
@class.id_method.must_equal :new_id
|
22
|
+
end
|
23
|
+
|
24
|
+
it "defaults id_method to :object_id" do
|
25
|
+
@class.id_method.must_equal :object_id
|
26
|
+
end
|
27
|
+
|
28
|
+
it "can set the id_method at initialization" do
|
29
|
+
subject = @class.new(:id_method => :new_id)
|
30
|
+
subject.id_method.must_equal(:new_id)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "defaults the id to object_id" do
|
34
|
+
subject.id.must_equal subject.object_id
|
35
|
+
end
|
36
|
+
|
37
|
+
it "uses id_method to define which method sets the id" do
|
38
|
+
def subject.new_id; :new_id; end
|
39
|
+
subject.id_method = :new_id
|
40
|
+
subject.id.must_equal :new_id
|
41
|
+
end
|
42
|
+
|
43
|
+
# ======
|
44
|
+
# = Id =
|
45
|
+
# ======
|
46
|
+
it "has an id setter" do
|
47
|
+
subject.id = :whale
|
48
|
+
subject.id.must_equal :whale
|
49
|
+
end
|
50
|
+
|
51
|
+
it "can set the id at initialization" do
|
52
|
+
subject = @class.new(:id => "george")
|
53
|
+
subject.id.must_equal "george"
|
54
|
+
end
|
55
|
+
|
56
|
+
# ============
|
57
|
+
# = Base URI =
|
58
|
+
# ============
|
59
|
+
it "can define the base_uri on the class level" do
|
60
|
+
@class.base_uri base_uri
|
61
|
+
@class.base_uri.must_equal base_uri
|
62
|
+
end
|
63
|
+
|
64
|
+
it "can set the base_uri at initialization" do
|
65
|
+
subject = @class.new(:base_uri => base_uri)
|
66
|
+
subject.base_uri.must_equal base_uri
|
67
|
+
end
|
68
|
+
|
69
|
+
it "can set the base_uri as a normal accessor" do
|
70
|
+
subject.base_uri = "http://weird.com"
|
71
|
+
subject.base_uri.must_equal "http://weird.com"
|
72
|
+
end
|
73
|
+
|
74
|
+
it "defaults to the class.base_uri" do
|
75
|
+
@class.base_uri base_uri
|
76
|
+
subject = @class.new
|
77
|
+
subject.base_uri.must_equal base_uri
|
78
|
+
end
|
79
|
+
|
80
|
+
# =====================
|
81
|
+
# = Subject Decorator =
|
82
|
+
# =====================
|
83
|
+
it "can define the subject_decorator on the class level" do
|
84
|
+
@class.subject_decorator :spoofy
|
85
|
+
@class.subject_decorator :spoofy
|
86
|
+
end
|
87
|
+
|
88
|
+
it "can set the subject_decorator at initialization" do
|
89
|
+
subject = @class.new(:subject_decorator => :spoofy)
|
90
|
+
subject.subject_decorator.must_equal :spoofy
|
91
|
+
end
|
92
|
+
|
93
|
+
it "can set the subject_decorator as a normal accessor" do
|
94
|
+
subject.subject_decorator = :spoofy
|
95
|
+
subject.subject_decorator.must_equal :spoofy
|
96
|
+
end
|
97
|
+
|
98
|
+
it "default to the class.subject_decorator" do
|
99
|
+
@class.subject_decorator :spoofy
|
100
|
+
subject = @class.new
|
101
|
+
subject.subject_decorator.must_equal :spoofy
|
102
|
+
end
|
103
|
+
|
104
|
+
# ===========
|
105
|
+
# = Subject =
|
106
|
+
# ===========
|
107
|
+
it "has a default subject method that combines the base_uri with the id" do
|
108
|
+
subject.base_uri = base_uri
|
109
|
+
subject.id = "george"
|
110
|
+
subject.subject.must_equal "#{base_uri}/george"
|
111
|
+
end
|
112
|
+
|
113
|
+
it "uses the subject_decorator if it is set" do
|
114
|
+
def subject.special_case; "#{base_uri}/special/#{id}"; end
|
115
|
+
subject.subject_decorator = :special_case
|
116
|
+
subject.base_uri = "http://example.com"
|
117
|
+
subject.subject.must_equal subject.special_case
|
118
|
+
end
|
119
|
+
|
120
|
+
it "can use a lambda for a subject_decorator" do
|
121
|
+
subject.subject_decorator = lambda{|model| "#{model.base_uri}/special/#{model.id}"}
|
122
|
+
subject.base_uri = "http://example.com"
|
123
|
+
subject.subject.must_equal "http://example.com/special/#{subject.id}"
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
@@ -6,8 +6,8 @@ describe RDFCollection do
|
|
6
6
|
|
7
7
|
subject { RDFCollection.new() }
|
8
8
|
|
9
|
-
it "uses RDF::
|
10
|
-
RDFCollection.included_modules.must_include RDF::
|
9
|
+
it "uses RDF::Queryable " do
|
10
|
+
RDFCollection.included_modules.must_include RDF::Queryable
|
11
11
|
end
|
12
12
|
|
13
13
|
it "adds statements with add_statement or []=" do
|
@@ -49,4 +49,30 @@ describe RDFCollection do
|
|
49
49
|
subject.has_key?(key, :normalize => false).must_equal false
|
50
50
|
subject.has_key?(normalized_key, :normalize => false).must_equal true
|
51
51
|
end
|
52
|
+
|
53
|
+
it "has a local_repository" do
|
54
|
+
subject.local_repository.must_be_kind_of RDF::Repository
|
55
|
+
end
|
56
|
+
|
57
|
+
it "has a local_repository setter" do
|
58
|
+
subject.local_repository = :blah
|
59
|
+
subject.local_repository.must_equal :blah
|
60
|
+
end
|
61
|
+
|
62
|
+
it "delegates to the local_repository from each" do
|
63
|
+
subject.local_repository = [1,2,3]
|
64
|
+
subject.to_a.must_equal [1,2,3]
|
65
|
+
end
|
66
|
+
|
67
|
+
it "uses each_with_field_names to iterate the labeled statements" do
|
68
|
+
statement = RDF::Statement(:a, :b, :c)
|
69
|
+
subject.add_statement :x, statement
|
70
|
+
subject.each_with_field_names.to_a.must_equal [[:x, statement]]
|
71
|
+
end
|
72
|
+
|
73
|
+
it "has a query method for SPARQL.execute" do
|
74
|
+
statement = RDF::Statement(RDF::Node.new, RDF::FOAF.givenname, "Frank")
|
75
|
+
subject.add_statement :x, statement
|
76
|
+
subject.query("select ?object where {?s ?p ?object}")[0].object.value.must_equal "Frank"
|
77
|
+
end
|
52
78
|
end
|