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,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
|