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,27 @@
|
|
1
|
+
module Gearbox
|
2
|
+
|
3
|
+
# I wanted to have all of my ActiveModel mixins in one place.
|
4
|
+
# I want to see how this is being used explicitly.
|
5
|
+
module ActiveModelImplementation
|
6
|
+
|
7
|
+
def self.included(base)
|
8
|
+
base.send :include, ActiveModel::Validations
|
9
|
+
base.send :include, ActiveModel::Conversion
|
10
|
+
|
11
|
+
# This isn't right...so I need to research these things a little bit.
|
12
|
+
# What I'm thinking is a RESTful API isn't too much to ask from Gearbox,
|
13
|
+
# So I want these to produce JSON and XML in a consistent way...
|
14
|
+
# I may be wrong, but I may be getting the RDF::JSON version here instead.
|
15
|
+
base.send :include, ActiveModel::Serializers::JSON
|
16
|
+
base.send :include, ActiveModel::Serializers::Xml
|
17
|
+
|
18
|
+
base.send :extend, ActiveModel::Naming
|
19
|
+
end
|
20
|
+
|
21
|
+
# TODO Temporary!!! Remove after finishing the Mutable changes.
|
22
|
+
def persisted?
|
23
|
+
false
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
@@ -8,10 +8,26 @@ module Gearbox
|
|
8
8
|
# ============
|
9
9
|
# = Behavior =
|
10
10
|
# ============
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
11
|
+
def self.included(base)
|
12
|
+
# Rethinking this one, they will be much more robust soon.
|
13
|
+
# This is more for knowledge base discovery or throw-away models
|
14
|
+
# So there's a new approach on the horizon of my imagination.
|
15
|
+
# base.send :include, AdHocProperties
|
16
|
+
base.send :include, SubjectMethods
|
17
|
+
base.send :include, SemanticAccessors
|
18
|
+
base.send :include, ActiveModelImplementation
|
19
|
+
base.send :include, RDF::Mutable
|
20
|
+
base.send :include, RDF::Queryable
|
21
|
+
end
|
22
|
+
|
23
|
+
# Depends on RDF::Queryable, SemanticAccessors and SubjectMethods
|
24
|
+
def each(opts={}, &block)
|
25
|
+
attribute_definitions.map{|name, attribute| attribute.to_rdf(self, opts)}.each(&block)
|
26
|
+
end
|
27
|
+
|
28
|
+
def inspect
|
29
|
+
"#{self.class.name} #{self.attributes.inspect}"
|
30
|
+
end
|
15
31
|
|
16
32
|
end
|
17
33
|
end
|
@@ -1,118 +1,157 @@
|
|
1
1
|
module Gearbox
|
2
2
|
|
3
|
-
|
4
|
-
# The attributes to add to a model.
|
5
|
-
# TODO: Add example from file.
|
6
|
-
##
|
3
|
+
# These are the attributes and associations that the user adds to a model.
|
7
4
|
module SemanticAccessors
|
8
5
|
|
9
|
-
# Treat this as a bundle of class methods and instance methods.
|
10
|
-
# @private
|
11
6
|
def self.included(base)
|
12
7
|
base.extend ClassMethods
|
13
8
|
base.send :include, InstanceMethods
|
14
9
|
end
|
15
10
|
|
16
|
-
##
|
17
|
-
# Class methods for the model.
|
18
|
-
##
|
19
11
|
module ClassMethods
|
20
12
|
|
21
|
-
|
22
|
-
|
23
|
-
# Requires a predicate option. Options are:
|
24
|
-
# * :predicate => RDF::URI
|
25
|
-
# * :reverse => Boolean store as value, predicate, subject
|
26
|
-
# * :index => Boolean maintain a full-text search index on this attribute
|
27
|
-
# @param [String, Symbol] getter_name, the field that is being created.
|
28
|
-
# @param [Hash] options
|
29
|
-
def attribute(getter_name, options={})
|
30
|
-
|
31
|
-
raise ArgumentError, "A predicate must be defined" unless options[:predicate]
|
32
|
-
|
33
|
-
send(attributes_source)[getter_name] = options
|
34
|
-
|
35
|
-
# Define a getter on the object
|
36
|
-
define_method(getter_name) do
|
37
|
-
self.class.yield_attr(getter_name, self)
|
38
|
-
end
|
39
|
-
|
40
|
-
# Define a setter on the object
|
41
|
-
define_method("#{getter_name}=") do |value|
|
42
|
-
self.class.store_attr(getter_name, self, value)
|
43
|
-
# attribute = send(self.class.attributes_source)[getter_name]
|
44
|
-
end
|
45
|
-
|
13
|
+
def attributes
|
14
|
+
@attributes ||= {}
|
46
15
|
end
|
47
16
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
# Gets the attributes_source...
|
52
|
-
def attributes_source
|
53
|
-
@attributes_source ||= :attribute_collection
|
54
|
-
end
|
17
|
+
def attribute(name, opts={})
|
18
|
+
opts = opts.merge(:name => name)
|
55
19
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
else
|
65
|
-
attribute_options = send(attributes_source)[getter_name]
|
66
|
-
attribute_options ? attribute_options.default : nil
|
20
|
+
define_method(name) do
|
21
|
+
attribute_definitions[name] ||= Attribute.new(opts)
|
22
|
+
attribute_definitions[name].to_value
|
23
|
+
end
|
24
|
+
|
25
|
+
define_method("#{name}=") do |value|
|
26
|
+
attribute_definitions[name] ||= Attribute.new(opts)
|
27
|
+
attribute_definitions[name].set(value)
|
67
28
|
end
|
68
|
-
end
|
69
|
-
|
70
|
-
def store_attr(getter_name, instance, value)
|
71
|
-
attribute_options = send(attributes_source)[getter_name]
|
72
|
-
# TODO: serialize value
|
73
|
-
statement = RDF::Statement.new(instance.subject, attribute_options.predicate, value)
|
74
|
-
instance.rdf_collection[getter_name] = statement
|
75
|
-
end
|
76
29
|
|
30
|
+
attributes[name] = opts
|
31
|
+
end
|
77
32
|
end
|
78
33
|
|
79
34
|
module InstanceMethods
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
def subject
|
87
|
-
"1"
|
35
|
+
|
36
|
+
def initialize(opts={})
|
37
|
+
super
|
38
|
+
assert_defaults
|
39
|
+
assert_options(opts)
|
88
40
|
end
|
89
41
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
merge_hash_values(obj)
|
95
|
-
when RDFCollection
|
96
|
-
merge_rdf_collection(obj)
|
42
|
+
def attributes
|
43
|
+
self.class.attributes.inject({:id => id}) do |hash, (name, opts)|
|
44
|
+
hash[name] = send(name)
|
45
|
+
hash
|
97
46
|
end
|
98
47
|
end
|
99
48
|
|
100
49
|
private
|
101
50
|
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
# What to do with the others?
|
108
|
-
end
|
51
|
+
def assert_defaults
|
52
|
+
self.class.attributes.each do |name, opts|
|
53
|
+
next unless opts.has_key?(:default)
|
54
|
+
setter = "#{name}="
|
55
|
+
send(setter, opts[:default])
|
109
56
|
end
|
110
|
-
|
111
|
-
|
112
|
-
|
57
|
+
end
|
58
|
+
|
59
|
+
def assert_options(opts)
|
60
|
+
opts.each do |name, value|
|
61
|
+
setter = "#{name}="
|
62
|
+
send(setter, value) if respond_to?(setter)
|
113
63
|
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def attribute_definitions
|
67
|
+
@attribute_definitions ||= {}
|
68
|
+
end
|
114
69
|
|
115
|
-
end
|
116
|
-
|
117
|
-
|
118
|
-
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
|
76
|
+
# class Z
|
77
|
+
#
|
78
|
+
# # ============
|
79
|
+
# # = Behavior =
|
80
|
+
# # ============
|
81
|
+
# include RDF::Queryable
|
82
|
+
# include ActiveModel::Validations
|
83
|
+
# include ActiveModel::Conversion
|
84
|
+
# extend ActiveModel::Naming
|
85
|
+
#
|
86
|
+
# def self.attribute(name, opts={})
|
87
|
+
#
|
88
|
+
# opts = opts.merge(:name => name)
|
89
|
+
#
|
90
|
+
# define_method(name) do
|
91
|
+
# attribute_definitions[name] ||= Attribute.new(opts)
|
92
|
+
# attribute_definitions[name].to_value
|
93
|
+
# end
|
94
|
+
#
|
95
|
+
# define_method("#{name}=") do |value|
|
96
|
+
# attribute_definitions[name] ||= Attribute.new(opts)
|
97
|
+
# attribute_definitions[name].set(value)
|
98
|
+
# end
|
99
|
+
#
|
100
|
+
# attributes[name] = opts
|
101
|
+
# end
|
102
|
+
#
|
103
|
+
# def self.attributes
|
104
|
+
# @attributes ||= {}
|
105
|
+
# end
|
106
|
+
#
|
107
|
+
# attribute :name, :predicate => RDF::FOAF.name
|
108
|
+
# attribute :email, :predicate => RDF::FOAF.mbox
|
109
|
+
#
|
110
|
+
# def initialize(opts={})
|
111
|
+
# assert_defaults
|
112
|
+
# assert_options(opts)
|
113
|
+
# end
|
114
|
+
#
|
115
|
+
# def id
|
116
|
+
# @id ||= object_id
|
117
|
+
# end
|
118
|
+
# attr_writer :id
|
119
|
+
#
|
120
|
+
# def subject
|
121
|
+
# "http://example.com/z/#{id}"
|
122
|
+
# end
|
123
|
+
#
|
124
|
+
# def attributes
|
125
|
+
# self.class.attributes.inject({:id => id}) do |hash, (name, opts)|
|
126
|
+
# hash[name] = send(name)
|
127
|
+
# hash
|
128
|
+
# end
|
129
|
+
# end
|
130
|
+
#
|
131
|
+
# def each(opts={}, &block)
|
132
|
+
# attribute_definitions.map{|name, attribute| attribute.to_rdf(self, opts)}.each(&block)
|
133
|
+
# end
|
134
|
+
#
|
135
|
+
# def inspect
|
136
|
+
# "Z: #{name}"
|
137
|
+
# end
|
138
|
+
#
|
139
|
+
# def persisted?
|
140
|
+
# false
|
141
|
+
# end
|
142
|
+
#
|
143
|
+
# private
|
144
|
+
#
|
145
|
+
# def assert_defaults
|
146
|
+
# end
|
147
|
+
#
|
148
|
+
# def assert_options(opts)
|
149
|
+
# opts.each do |accessor, value|
|
150
|
+
# send("#{accessor}=", value) if respond_to?("#{accessor}=")
|
151
|
+
# end
|
152
|
+
# end
|
153
|
+
#
|
154
|
+
# def attribute_definitions
|
155
|
+
# @attribute_definitions ||= {}
|
156
|
+
# end
|
157
|
+
# end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
module Gearbox
|
2
|
+
module SubjectMethods
|
3
|
+
|
4
|
+
def self.included(base)
|
5
|
+
base.extend ClassMethods
|
6
|
+
base.send :include, InstanceMethods
|
7
|
+
end
|
8
|
+
|
9
|
+
module ClassMethods
|
10
|
+
def base_uri(value=:_value_not_set)
|
11
|
+
@base_uri = value unless value == :_value_not_set
|
12
|
+
@base_uri
|
13
|
+
end
|
14
|
+
|
15
|
+
def id_method(value=:_value_not_set)
|
16
|
+
@id_method = value unless value == :_value_not_set
|
17
|
+
@id_method ||= :object_id
|
18
|
+
end
|
19
|
+
|
20
|
+
def subject_decorator(value=:_value_not_set)
|
21
|
+
@subject_decorator = value unless value == :_value_not_set
|
22
|
+
@subject_decorator
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
module InstanceMethods
|
28
|
+
|
29
|
+
attr_accessor :base_uri
|
30
|
+
|
31
|
+
def initialize(opts={})
|
32
|
+
super
|
33
|
+
set_attributes_from_configuration_or_opts(opts, :base_uri, :id_method, :id, :subject_decorator)
|
34
|
+
end
|
35
|
+
|
36
|
+
def id
|
37
|
+
return @id if @id
|
38
|
+
send(id_method)
|
39
|
+
end
|
40
|
+
attr_writer :id
|
41
|
+
|
42
|
+
# Gives us the ability to derive an id from other sources or patterns.
|
43
|
+
# Based on the identifier patterns: http://patterns.dataincubator.org/book/
|
44
|
+
attr_accessor :id_method
|
45
|
+
|
46
|
+
# Allows patterns to be used to define the subject.
|
47
|
+
attr_accessor :subject_decorator
|
48
|
+
|
49
|
+
# subject_decorator -> internal method -> subject
|
50
|
+
# subject_decorator -> lambda -> subject
|
51
|
+
# (base_uri + (id_method -> id)) -> subject
|
52
|
+
# There are several ways to create the subject. First, the subject_decorator
|
53
|
+
# will use whatever instance values that are set to build a pattern.
|
54
|
+
# Second, the base_uri and id are combined to create the subject.
|
55
|
+
# Note, the id can be set directly, or set with the id_method, so UUID,
|
56
|
+
# or an external source, or a slug generating method can be used to generate
|
57
|
+
# an id.
|
58
|
+
def subject
|
59
|
+
if subject_decorator
|
60
|
+
derive_subject_from_decorator
|
61
|
+
else
|
62
|
+
derive_subject_from_base_uri_and_id
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def derive_subject_from_decorator
|
69
|
+
subject_decorator.respond_to?(:call) ? subject_decorator.call(self)
|
70
|
+
: self.send(subject_decorator)
|
71
|
+
end
|
72
|
+
|
73
|
+
def derive_subject_from_base_uri_and_id
|
74
|
+
File.join(base_uri.to_s, id.to_s)
|
75
|
+
end
|
76
|
+
|
77
|
+
def set_attributes_from_configuration_or_opts(opts, *attributes)
|
78
|
+
attributes.each do |attribute|
|
79
|
+
variable_name = "@#{attribute}"
|
80
|
+
instance_variable_set(variable_name, self.class.send(attribute)) if self.class.respond_to?(attribute)
|
81
|
+
instance_variable_set(variable_name, opts[attribute]) if opts.has_key?(attribute)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
|
87
|
+
end
|
88
|
+
end
|
@@ -9,7 +9,7 @@ module Gearbox
|
|
9
9
|
# ============
|
10
10
|
# = Behavior =
|
11
11
|
# ============
|
12
|
-
include RDF::
|
12
|
+
include RDF::Queryable
|
13
13
|
|
14
14
|
def initialize
|
15
15
|
@source = {}
|
@@ -21,18 +21,23 @@ module Gearbox
|
|
21
21
|
# @param [Block] block Optional block. Creates an external iterator if omitted.
|
22
22
|
# @return [nil, Enumerator] Returns either nil, or an external iterator.
|
23
23
|
def each(&block)
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
24
|
+
local_repository.each(&block)
|
25
|
+
end
|
26
|
+
|
27
|
+
def each_with_field_names(&block)
|
28
|
+
@source.each(&block)
|
29
29
|
end
|
30
30
|
|
31
|
+
attr_accessor :source
|
32
|
+
|
31
33
|
# Set RDF::Statements to the underlying collection. Normalizes the keys.
|
32
34
|
# @param [String, Symbol] key
|
33
35
|
# @param [RDF::Statement] obj. RDF::Statement that will be added.
|
34
36
|
def add_statement(key, obj)
|
35
|
-
|
37
|
+
if obj.is_a?(RDF::Statement)
|
38
|
+
@source[normalize_key(key)] = obj
|
39
|
+
local_repository << obj
|
40
|
+
end
|
36
41
|
end
|
37
42
|
alias :[]= :add_statement
|
38
43
|
|
@@ -57,7 +62,16 @@ module Gearbox
|
|
57
62
|
# @param [Hash] hash. Collection of statements.
|
58
63
|
# @return [nil]
|
59
64
|
def merge!(hash)
|
60
|
-
hash.
|
65
|
+
hash.each_with_field_names {|key, obj| add_statement(key, obj)}
|
66
|
+
end
|
67
|
+
|
68
|
+
attr_writer :local_repository
|
69
|
+
def local_repository
|
70
|
+
@local_repository ||= RDF::Repository.new
|
71
|
+
end
|
72
|
+
|
73
|
+
def query(string)
|
74
|
+
SPARQL.execute(string, local_repository)
|
61
75
|
end
|
62
76
|
|
63
77
|
private
|