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.
Files changed (43) hide show
  1. data/Gemfile +5 -3
  2. data/Rakefile +1 -0
  3. data/VERSION +1 -1
  4. data/bin/gearbox +9 -0
  5. data/gearbox.gemspec +134 -0
  6. data/lib/gearbox.rb +124 -5
  7. data/lib/gearbox/attribute.rb +128 -0
  8. data/lib/gearbox/mixins/active_model_implementation.rb +27 -0
  9. data/lib/gearbox/mixins/resource.rb +20 -4
  10. data/lib/gearbox/mixins/semantic_accessors.rb +128 -89
  11. data/lib/gearbox/mixins/subject_methods.rb +88 -0
  12. data/lib/gearbox/rdf_collection.rb +22 -8
  13. data/lib/gearbox/types.rb +9 -8
  14. data/lib/gearbox/vocabulary.rb +149 -0
  15. data/lib/pry_utilities.rb +71 -0
  16. data/scratch/4s.rb +335 -0
  17. data/scratch/DEVELOPMENT_NOTES.md +85 -0
  18. data/scratch/actionable.md +34 -0
  19. data/scratch/ccrdf.html-rdfa.nq +100 -0
  20. data/scratch/foo.rb +17 -0
  21. data/scratch/index.rdf +7932 -0
  22. data/scratch/j2.rb +10 -0
  23. data/scratch/junk.rb +16 -0
  24. data/scratch/out.rb +67 -0
  25. data/spec/gearbox/attribute_spec.rb +455 -0
  26. data/spec/gearbox/mixins/active_model_implementation_spec.rb +18 -0
  27. data/spec/gearbox/mixins/ad_hoc_properties_spec.rb +44 -44
  28. data/spec/gearbox/mixins/resource_spec.rb +47 -8
  29. data/spec/gearbox/mixins/semantic_accessors_spec.rb +72 -43
  30. data/spec/gearbox/mixins/subject_methods_spec.rb +126 -0
  31. data/spec/gearbox/rdf_collection_spec.rb +28 -2
  32. data/spec/gearbox_spec.rb +6 -2
  33. data/spec/spec_helper.rb +1 -0
  34. metadata +150 -42
  35. data/Gemfile.lock +0 -138
  36. data/lib/examples/audience.rb +0 -24
  37. data/lib/examples/person.rb +0 -29
  38. data/lib/examples/reference.rb +0 -38
  39. data/lib/examples/theme.rb +0 -8
  40. data/spec/examples/audience_spec.rb +0 -28
  41. data/spec/examples/person_spec.rb +0 -45
  42. data/spec/examples/reference_spec.rb +0 -43
  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
- @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
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
- def self.name; 'demo_class'; end
10
- include Gearbox
9
+ include Gearbox::Resource
11
10
  end
12
11
  end
13
12
 
14
13
  subject { @class.new }
15
14
 
16
- it "uses AdHocProperties" do
17
- Resource.included_modules.must_include Gearbox::AdHocProperties
18
- end
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
- Resource.included_modules.must_include Gearbox::SemanticAccessors
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
- Resource.included_modules.must_include RDF::Mutable
35
+ @class.included_modules.must_include RDF::Mutable
26
36
  end
27
37
 
28
38
  it "uses RDF::Queryable" do
29
- Resource.included_modules.must_include RDF::Queryable
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
- it "raises an error unless a predicate is defined" do
33
- lambda{@class.attribute :given_name}.must_raise(ArgumentError, /predicate/i)
34
- end
35
-
36
- it "takes a hash on initialization" do
37
- @class.attribute :given_name, :predicate => RDF::FOAF.givenname
38
- subject = @class.new :given_name => "Frank"
39
- subject.given_name.must_equal "Frank"
40
- end
41
-
42
- it "takes an RDFCollection on initialization" do
43
- @class.attribute :given_name, :predicate => RDF::FOAF.givenname
44
- collection = RDFCollection.new
45
- collection[:given_name] = RDF::Statement.new(:a, RDF::FOAF.givenname, 'Frank')
46
- collection[:family_name] = RDF::Statement.new(:a, RDF::FOAF.familyname, 'Wilde')
47
- subject = @class.new(collection)
48
- subject.given_name.must_equal "Frank"
49
- end
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
- it "takes an Array of RDF::Statement objects on initialization"
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::Enumerable " do
10
- RDFCollection.included_modules.must_include RDF::Enumerable
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