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