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,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
- include AdHocProperties
12
- include SemanticAccessors
13
- include RDF::Mutable
14
- include RDF::Queryable
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
- # Add an attribute or a field to a model. Takes a field name.
22
- # Defines both a getter and a setter on the object.
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
- # Sets the attributes_source, where to store the attributes
49
- attr_writer :attributes_source
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
- def attribute_collection
57
- @attribute_collection ||= AttributeCollection.new
58
- end
59
-
60
- def yield_attr(getter_name, instance)
61
- if statement = instance.rdf_collection[getter_name]
62
- # TODO: Deserialize object
63
- return statement.object.to_s
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
- # We collect triples inside the models in order to query them, filter them
81
- # and handle the bridge between domain models and the graph we're building.
82
- def rdf_collection
83
- @rdf_collection ||= RDFCollection.new
84
- end
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
- # An initialization strategy for all occasions.
91
- def initialize(obj=nil)
92
- case obj
93
- when Hash
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
- def merge_hash_values(hash)
103
- # TODO: work with associations here...
104
- hash.each do |getter_name, value|
105
- setter_name = "#{getter_name}="
106
- send(setter_name, value) if respond_to?(setter_name)
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
- def merge_rdf_collection(collection)
112
- rdf_collection.merge!(collection)
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 # InstanceMethods
116
-
117
- end # SemanticAccessors
118
- end # Gearbox
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::Enumerable
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
- if block_given?
25
- @source.each(&block)
26
- else
27
- Enumerator.new(self, :each)
28
- end
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
- @source[normalize_key(key)] = obj if obj.is_a?(RDF::Statement)
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.each {|key, obj| add_statement(key, obj)}
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