gearbox 0.1.0 → 0.1.10

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