gearbox 0.1.0 → 0.1.10
Sign up to get free protection for your applications and to get access to all the features.
- 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
|