gearbox 0.1.10 → 0.1.17

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -5,7 +5,7 @@ The purpose of this project is to make it easier for me to curate semantic graph
5
5
 
6
6
  To get to wherever I am now, I've been playing with semantic models for a while. I started by demonstrating working code from various corners of my imagination. After a while, I thought I had enough to create a useful gem. In the past, I've worked with [Spira](https://github.com/bhuga/spira) and examples given by [Gregg Kellogg](http://greggkellogg.net/). These have been very useful in forming ideas.
7
7
 
8
- As I worked on this code, I decided to go to [Spira](https://github.com/bhuga/spira) to see how similar the two gems are. I was surprised how similar they actually are. The similarities are:
8
+ As I worked on this code, I decided to go to [Spira](https://github.com/bhuga/spira) to see how similar the two gems are. I've read Ben's code a dozen times before, but this time I was surprised how similar they actually are. The similarities are:
9
9
 
10
10
  * both are ORMs for semantic data, written in Ruby
11
11
  * support for properties/attributes
@@ -13,43 +13,25 @@ As I worked on this code, I decided to go to [Spira](https://github.com/bhuga/sp
13
13
  * data validations
14
14
  * value types
15
15
 
16
- However, Gearbox is quite a bit different. It came from a different place. I've been trying to embrace the nature of semantic models. This, juxtaposed against relational models or other types of models. The major differences, I imagine are:
16
+ However, Gearbox is quite a bit different. It came from a different place. I've been trying to embrace the nature of semantic models (or find a way to express my imagination with semantic tools). The major differences, I imagine are:
17
17
 
18
18
  * support for SPARQL-based scopes and finder methods
19
19
  * better support for working with various SPARQL end points
20
20
  * creating and maintaining full-text indices
21
21
  * object factory from triples
22
22
 
23
- Development Workflow for Semantic Data
24
- ======================================
25
-
26
- For a typical domain, I test-drive some models to define the nature of the data. These are custom-built to support the user scenarios and behavior an application is built to serve. For semantic models, I'm going for something different. The relationships between resources are much more dynamic. It's tough to build an application on dynamic domain models.
27
-
28
- To work with this, I'd rather optimize for different things. Instead of trying to canonize the data, concretize the interaction. Given a head/buffer/file full of data, what's the easiest way to save it? Which values have to be recorded? Which values can be inferred or classified offline?
29
-
30
- I think that there's going to be an evolution of the data graph. I'm looking to start with the mundane, and hope to be able to create a broad view from the details collected. Possibly, I will have alternative broad views, such as a full view of the topic or a chronological account of the topic as it transpires. From here, I want to look for insightful information: inferences that show the nature of our subject.
31
-
32
- That's the goal.
33
-
34
- Practically, the work changes over time. We start with defining the attributes and associations that are needed. This is the mundane. We then start to qualify the data by writing validations. Probably, there will be overlapping models to reflect the interaction. For example, browsing email might have a cursory recording of the people involved. Looking up Twitter information might have a more-specific user model. Facebook, the same. We're building a summary of the users, or whatever we're studying. From here, we might be able to use various analytical methods to classify and enhance the models, to clarify the story we are able to gather.
35
-
36
- As you can see, this is a very different process than something we might do with typical relational data. I don't think there is much that we do with semantic data that can't be done with relational data, it's just that the technologies are optimized for different purposes.
37
-
38
23
  Practical Example
39
24
  =================
40
25
 
41
- It would be good to offer a practical example. I'll get to these in a bit. I don't need to have the documentation get ahead of the released code.
26
+ It would be good to offer a practical example. I'll get to these in a bit. Probably these will start appearing around version 0.2 or 0.3. They probably won't be very exciting until around version 0.4.
42
27
 
43
- TODO
44
- ====
28
+ Road Ahead
29
+ ==========
45
30
 
46
- * bring in the association and combination code
47
- * implement mutability
48
- * implement persistence
49
- * implement queryable
50
- * implement named scopes
51
- * implement some sort of repository access
52
- * use Gearbox in the examples (were written to concretize an example in my head)
31
+ * bring in the associations and type system (related, believe it or not)
32
+ * implement mutability (version 0.2)
33
+ * workflows with SPIN and full-text indexing (version 0.3)
34
+ * exploration utilities (version 0.4)
53
35
 
54
36
  Contributing to Gearbox
55
37
  =======================
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.10
1
+ 0.1.17
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "gearbox"
8
- s.version = "0.1.10"
8
+ s.version = "0.1.17"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["David Richards"]
12
- s.date = "2012-04-03"
12
+ s.date = "2012-04-05"
13
13
  s.description = "A SPARQL-driven modeling toolset for semantic models."
14
14
  s.email = "davidlamontrichards@gmail.com"
15
15
  s.executables = ["gearbox"]
@@ -34,6 +34,7 @@ Gem::Specification.new do |s|
34
34
  "lib/gearbox/attribute_collection.rb",
35
35
  "lib/gearbox/mixins/active_model_implementation.rb",
36
36
  "lib/gearbox/mixins/ad_hoc_properties.rb",
37
+ "lib/gearbox/mixins/queryable_implementation.rb",
37
38
  "lib/gearbox/mixins/resource.rb",
38
39
  "lib/gearbox/mixins/semantic_accessors.rb",
39
40
  "lib/gearbox/mixins/subject_methods.rb",
@@ -64,6 +65,7 @@ Gem::Specification.new do |s|
64
65
  "spec/gearbox/attribute_spec.rb",
65
66
  "spec/gearbox/mixins/active_model_implementation_spec.rb",
66
67
  "spec/gearbox/mixins/ad_hoc_properties_spec.rb",
68
+ "spec/gearbox/mixins/queryable_implementation_spec.rb",
67
69
  "spec/gearbox/mixins/resource_spec.rb",
68
70
  "spec/gearbox/mixins/semantic_accessors_spec.rb",
69
71
  "spec/gearbox/mixins/subject_methods_spec.rb",
@@ -129,6 +129,7 @@ module Gearbox
129
129
  autoload :AdHocProperties, path('mixins/ad_hoc_properties')
130
130
  autoload :ActiveModelImplementation, path('mixins/active_model_implementation')
131
131
  autoload :AttributeMethods, path('mixins/attribute_methods')
132
+ autoload :QueryableImplementation, path('mixins/queryable_implementation')
132
133
  autoload :Resource, path('mixins/resource')
133
134
  autoload :SemanticAccessors, path('mixins/semantic_accessors')
134
135
  autoload :SubjectMethods, path('mixins/subject_methods')
@@ -16,6 +16,7 @@ module Gearbox
16
16
  base.send :include, ActiveModel::Serializers::Xml
17
17
 
18
18
  base.send :extend, ActiveModel::Naming
19
+ base.send :include, ActiveModel::Dirty
19
20
  end
20
21
 
21
22
  # TODO Temporary!!! Remove after finishing the Mutable changes.
@@ -0,0 +1,14 @@
1
+ module Gearbox
2
+ module QueryableImplementation
3
+ def self.included(base)
4
+ base.send :include, RDF::Queryable
5
+ end
6
+
7
+ # Depends on RDF::Queryable, SemanticAccessors and SubjectMethods
8
+ def each(opts={}, &block)
9
+ attribute_definitions.map{|name, attribute| attribute.to_rdf(self, opts)}.each(&block)
10
+ end
11
+ alias :each_statement :each
12
+
13
+ end
14
+ end
@@ -13,16 +13,12 @@ module Gearbox
13
13
  # This is more for knowledge base discovery or throw-away models
14
14
  # So there's a new approach on the horizon of my imagination.
15
15
  # base.send :include, AdHocProperties
16
+
17
+ base.send :include, ActiveModelImplementation
16
18
  base.send :include, SubjectMethods
17
19
  base.send :include, SemanticAccessors
18
- base.send :include, ActiveModelImplementation
20
+ base.send :include, QueryableImplementation
19
21
  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
22
  end
27
23
 
28
24
  def inspect
@@ -23,11 +23,15 @@ module Gearbox
23
23
  end
24
24
 
25
25
  define_method("#{name}=") do |value|
26
+ @previously_changed = changes
26
27
  attribute_definitions[name] ||= Attribute.new(opts)
27
- attribute_definitions[name].set(value)
28
+ old_value = attribute_definitions[name].get
29
+ new_value = attribute_definitions[name].set(value)
30
+ name_will_change! unless new_value == old_value
28
31
  end
29
32
 
30
33
  attributes[name] = opts
34
+ define_attribute_method(name)
31
35
  end
32
36
  end
33
37
 
@@ -37,6 +41,7 @@ module Gearbox
37
41
  super
38
42
  assert_defaults
39
43
  assert_options(opts)
44
+ @changed_attributes.clear if @changed_attributes
40
45
  end
41
46
 
42
47
  def attributes
@@ -1,6 +1,7 @@
1
1
  # Useful for a Pry session.
2
2
 
3
3
  require 'forwardable'
4
+ require 'fileutils'
4
5
 
5
6
  include Gearbox
6
7
 
@@ -17,17 +18,49 @@ class Utilities
17
18
  alias :update_model :write_model
18
19
  alias :build_model :write_model
19
20
 
21
+ def edit_models
22
+ raise "Directory does not exist" unless File.exist?(model_directory)
23
+ raise "ENV['EDITOR'] not set" unless ENV['EDITOR']
24
+ `#{ENV['EDITOR']} #{model_directory}`
25
+ puts "The models are open in your editor, but you will need to load them again after completing your work."
26
+ true
27
+ end
28
+
20
29
  def load_model(name)
21
30
  raise "Directory does not exist" unless File.exist?(model_directory)
22
31
  filename = File.join(model_directory, "#{name}.rb")
23
32
  load filename
24
33
  end
34
+
35
+ def load_models
36
+ Dir.glob("#{model_directory}/*.rb").map { |filename| load filename}
37
+ end
25
38
 
39
+ def user_directory
40
+ File.expand_path("~/.gearbox")
41
+ end
42
+
43
+ def user_model_directory
44
+ @user_model_directory ||= File.join(user_directory, "models")
45
+ end
46
+
26
47
  def model_directory
27
- @model_directory ||= "/tmp"
48
+ return @model_directory if @model_directory
49
+ if File.exists?(user_directory)
50
+ FileUtils.mkdir(user_model_directory) unless File.exists?(user_model_directory)
51
+ @model_directory = user_model_directory
52
+ elsif File.exists?("/tmp")
53
+ @model_directory = File.expand_path("/tmp") if File.exists?("/tmp")
54
+ end
55
+ @model_directory
28
56
  end
29
57
  attr_writer :model_directory
30
58
 
59
+ def list_models
60
+ Dir.glob("#{model_directory}/*.rb").map { |file| File.basename(file).split('.')[0..-2].join('.').to_sym}
61
+ true
62
+ end
63
+
31
64
  def tmp_directory
32
65
  @tmp_directory ||= "/tmp"
33
66
  end
@@ -59,13 +92,16 @@ end
59
92
  @utilities = Utilities.new
60
93
  extend Forwardable
61
94
  def_delegators :@utilities,
62
- :write_model,
63
- :update_model,
64
95
  :build_model,
96
+ :edit_models,
97
+ :get_note,
98
+ :list_models,
99
+ :load_model,
100
+ :load_models,
65
101
  :model_directory,
66
102
  :model_directory=,
67
103
  :tmp_directory,
68
104
  :tmp_directory=,
69
- :get_note,
70
- :load_model
105
+ :update_model,
106
+ :write_model
71
107
 
@@ -0,0 +1,36 @@
1
+ require_relative '../../spec_helper'
2
+
3
+ include Gearbox
4
+
5
+ describe QueryableImplementation do
6
+
7
+ before do
8
+ @class = Class.new do
9
+ include Gearbox::Resource
10
+ end
11
+ end
12
+
13
+ subject { @class.new }
14
+
15
+ it "uses RDF::Queryable" do
16
+ @class = Class.new {include Gearbox::QueryableImplementation}
17
+ @class.included_modules.must_include RDF::Queryable
18
+ end
19
+
20
+ it "has each defined on the model" do
21
+ subject.respond_to?(:each).must_equal true
22
+ end
23
+
24
+ it "produces RDF statements from the enumeration" do
25
+ @class.attribute :name, :predicate => RDF::FOAF.name
26
+ subject = @class.new(:name => "George")
27
+ subject.to_a.must_equal([RDF::Statement.new(subject.subject, RDF::FOAF.name, RDF::Literal.new("George"))])
28
+ end
29
+
30
+ it "aliases each_statement to each" do
31
+ @class.attribute :name, :predicate => RDF::FOAF.name
32
+ subject = @class.new(:name => "George")
33
+ subject.each_statement.to_a.must_equal([RDF::Statement.new(subject.subject, RDF::FOAF.name, RDF::Literal.new("George"))])
34
+ end
35
+
36
+ end
@@ -35,23 +35,6 @@ describe Resource do
35
35
  @class.included_modules.must_include RDF::Mutable
36
36
  end
37
37
 
38
- it "uses RDF::Queryable" do
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
38
  describe "Load order" do
56
39
  # Unfortunately, the load order is important here.
57
40
  # There is only one example right now: id.
@@ -10,6 +10,7 @@ describe SemanticAccessors do
10
10
  @class = Class.new do
11
11
  def self.name; 'demo_class'; end
12
12
  include SemanticAccessors
13
+ include ActiveModelImplementation
13
14
  end
14
15
  end
15
16
 
@@ -33,6 +34,18 @@ describe SemanticAccessors do
33
34
  @class.attribute(:name, :predicate => RDF::FOAF.name)
34
35
  @class.attributes[:name].must_equal({:name => :name, :predicate => RDF::FOAF.name})
35
36
  end
37
+
38
+ it "uses define_attribute_method to tell ActiveModel about the attribute" do
39
+ def @class.define_attribute_method(name)
40
+ @attribute_methods_defined ||= []
41
+ @attribute_methods_defined << name
42
+ end
43
+ def @class.attribute_methods_defined
44
+ @attribute_methods_defined
45
+ end
46
+ @class.attribute(:name, :predicate => RDF::FOAF.name)
47
+ @class.attribute_methods_defined.must_equal([:name])
48
+ end
36
49
  end
37
50
  end # "Class methods"
38
51
 
@@ -40,6 +53,7 @@ describe SemanticAccessors do
40
53
  before do
41
54
  @class = Class.new do
42
55
  include SemanticAccessors
56
+ include ActiveModelImplementation
43
57
  attribute :name, :predicate => RDF::FOAF.name
44
58
  end
45
59
  end
@@ -51,6 +65,16 @@ describe SemanticAccessors do
51
65
  subject.name.must_equal "George"
52
66
  end
53
67
 
68
+ it "marks the attribute as dirty when changed" do
69
+ subject.name = "George"
70
+ subject.changed_attributes.must_equal({"name" => "George"})
71
+ end
72
+
73
+ it "does not mark the attributes as dirty after initialization" do
74
+ subject = @class.new(:name => "George")
75
+ subject.changed?.must_equal false
76
+ end
77
+
54
78
  it "supports the attribute data types" do
55
79
  # In fact, it supports the full attribute system, this is just a quick check.
56
80
  @class.attribute :birthday, :predicate => RDF::FOAF.birthday, :datatype => RDF::XSD.date
@@ -10,6 +10,7 @@ rescue Bundler::BundlerError => e
10
10
  exit e.status_code
11
11
  end
12
12
  require 'minitest/spec'
13
+ require 'minitest/mock'
13
14
  require 'minitest/autorun'
14
15
 
15
16
  $LOAD_PATH.unshift(File.dirname(__FILE__))
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gearbox
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.10
4
+ version: 0.1.17
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-04-03 00:00:00.000000000Z
12
+ date: 2012-04-05 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: linkeddata
@@ -276,6 +276,7 @@ files:
276
276
  - lib/gearbox/attribute_collection.rb
277
277
  - lib/gearbox/mixins/active_model_implementation.rb
278
278
  - lib/gearbox/mixins/ad_hoc_properties.rb
279
+ - lib/gearbox/mixins/queryable_implementation.rb
279
280
  - lib/gearbox/mixins/resource.rb
280
281
  - lib/gearbox/mixins/semantic_accessors.rb
281
282
  - lib/gearbox/mixins/subject_methods.rb
@@ -306,6 +307,7 @@ files:
306
307
  - spec/gearbox/attribute_spec.rb
307
308
  - spec/gearbox/mixins/active_model_implementation_spec.rb
308
309
  - spec/gearbox/mixins/ad_hoc_properties_spec.rb
310
+ - spec/gearbox/mixins/queryable_implementation_spec.rb
309
311
  - spec/gearbox/mixins/resource_spec.rb
310
312
  - spec/gearbox/mixins/semantic_accessors_spec.rb
311
313
  - spec/gearbox/mixins/subject_methods_spec.rb
@@ -327,7 +329,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
327
329
  version: '0'
328
330
  segments:
329
331
  - 0
330
- hash: -845810536138016079
332
+ hash: 1172307424994719689
331
333
  required_rubygems_version: !ruby/object:Gem::Requirement
332
334
  none: false
333
335
  requirements: