active-triples 0.6.1 → 0.7.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 809451f4e93b30a688fe6408869e9a854f17566b
4
- data.tar.gz: e7245d27ba5ead992693c0287cda780552525ab6
3
+ metadata.gz: a4dc6967bd4ea18668b379926f3504e0c67c5135
4
+ data.tar.gz: c75e487fcf484d7e1f91a7a919ac9c56c2728c1b
5
5
  SHA512:
6
- metadata.gz: b00382722ed8c6217be858229f817707f3e9ab79de5f9d8c286894f670c1918da137aefa2f30d852ccf6f4b61974cd28d97f9a6b0833faa6bd5dc70721208b2d
7
- data.tar.gz: 5a1df0a4b7f39d97af9a28f78cefb34af861b0a8c4276a0c50bce79b6455838d6f705b7fc6c737b7c02a1b864d5d200f70a5afcb13decc544e03d0b2d4a1bf15
6
+ metadata.gz: d548a15c50003b4625c33283399bd8d101edceec9671658012b1702cead051c7230188afe2a6100feb9bd93c3a08204bbd4395266fec6aebc071863e3e647b28
7
+ data.tar.gz: c2a1f637cd7a4edf4a9a3eb3fd78fcbf143e964561d6648d674353575a4c5312aee21f8502de003b4ae1a4bbb4c7f13760eabbdfe35d126ef9f312e9efd14775
@@ -1,12 +1,16 @@
1
1
  anguage: ruby
2
2
  bundler_args: --without debug
3
3
  script: "bundle exec rspec spec"
4
+ sudo: false
5
+ cache: bundler
4
6
  rvm:
5
- - 1.9.3
6
7
  - 2.0.0
7
8
  - 2.1.0
8
9
  - 2.1.1
9
- - jruby-19mode
10
+ - 2.2.1
11
+ - ruby-head
12
+ - jruby
13
+ - rbx-2
10
14
  matrix:
11
15
  allow_failures:
12
- - rvm: jruby-19mode
16
+ - rvm: jruby
@@ -0,0 +1,20 @@
1
+ 0.7.0
2
+ -----
3
+
4
+ __ATTN: This release withdraws support for Ruby 1.9__
5
+
6
+ - Removes `#solrize` which was a badly named holdever from the
7
+ ActiveFedroa days.
8
+ - Fixes a bug on properties defined without a predicate. They are now
9
+ rejected.
10
+ - Disallows setting properties on the `ActiveTriples::Resource` base
11
+ class directly. This kind of property setting is unintended and
12
+ resulted in unexpected behavior.
13
+ - Introduces `ActiveTriples::RDFSource` as a mixin module for which
14
+ forms the basis of `Resource`.
15
+ - Use of this module is now preferred to single inheritance of the
16
+ `Resource` base class.
17
+ - `Resource` will remain indefinitely as the generic model.
18
+ - Renamed `Term` to `Relation`. `Term` is deprecated for removal in
19
+ the next minor release.
20
+ - Allow configuration of multiple `rdf:type`s.
data/Gemfile CHANGED
@@ -1,3 +1,5 @@
1
1
  source "https://rubygems.org"
2
2
 
3
3
  gemspec
4
+
5
+ gem 'pry-byebug' unless ENV["CI"]
data/README.md CHANGED
@@ -5,7 +5,7 @@ Description
5
5
  [![Coverage Status](https://coveralls.io/repos/ActiveTriples/ActiveTriples/badge.png?branch=master)](https://coveralls.io/r/ActiveTriples/ActiveTriples?branch=master)
6
6
  [![Gem Version](https://badge.fury.io/rb/active-triples.svg)](http://badge.fury.io/rb/active-triples)
7
7
 
8
- An ActiveModel-like interface for RDF data. Models graphs as Resources with property/attribute configuration, accessors, and other methods to support Linked Data in a Ruby/Rails enviornment.
8
+ An ActiveModel-like interface for RDF data. Models graphs as RDFSources with property/attribute configuration, accessors, and other methods to support Linked Data in a Ruby/Rails enviornment. See [RDF Concepts and Abstract Syntax](http://www.w3.org/TR/2014/REC-rdf11-concepts-20140225/#change-over-time) for an informal definition of an RDF Source.
9
9
 
10
10
  This library was extracted from work on [ActiveFedora](https://github.com/projecthydra/active_fedora). It is closely related to (and borrows some syntax from) [Spira](https://github.com/ruby-rdf/spira), but does some important things differently.
11
11
 
@@ -16,14 +16,15 @@ Add `gem "active-triples"` to your Gemfile and run `bundle`.
16
16
 
17
17
  Or install manually with `gem install active-triples`.
18
18
 
19
- Defining Resource Models
20
- ------------------------
19
+ Defining RDFSource Models
20
+ -------------------------
21
21
 
22
- The core class of ActiveTriples is ActiveTriples::Resource. You can subclass this to create ActiveModel-like classes that represent a node in an RDF graph, and its surrounding statements. Resources implement all the functionality of an RDF::Graph. You can manipulate them by adding or deleting statements, query, serialize, and load arbitrary RDF.
22
+ The core module of `ActiveTriples` is `ActiveTriples::RDFSource`. You can use this module as a mixin to create ActiveModel-like classes that represent an RDF resource as a stateful entity represented by an `RDF::Graph`. `RDFSource` implements the `RDF::Resource` interface, as well as `RDF::Queryable`, `RDF::Enumerable`, and `RDF::Mutable`. This means you can manipulate them by adding or deleting statements, query, serialize, and load arbitrary RDF.
23
23
 
24
24
 
25
25
  ```ruby
26
- class Thing < ActiveTriples::Resource
26
+ class Thing
27
+ include ActiveTriples::RDFSource
27
28
  configure :type => RDF::OWL.Thing, :base_uri => 'http://example.org/things#'
28
29
  property :title, :predicate => RDF::DC.title
29
30
  property :description, :predicate => RDF::DC.description
@@ -34,12 +35,13 @@ obj.title = 'Resource'
34
35
  obj.description = 'A resource.'
35
36
  obj.dump :ntriples # => "<http://example.org/things#123> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2002/07/owl#Thing> .\n<http://example.org/things#123> <http://purl.org/dc/terms/title> \"Resource\" .\n<http://example.org/things#123> <http://purl.org/dc/terms/description> \"A resource.\" .\n"
36
37
  ```
37
- URI and bnode values are built out as Resources when accessed, and a model class can be configured on individual properties.
38
+ URI and bnode values are built out as generic Resources when accessed. A more specific model class can be configured on individual properties.
38
39
 
39
40
  ```ruby
40
41
  Thing.property :creator, :predicate => RDF::DC.creator, :class_name => 'Person'
41
42
 
42
- class Person < ActiveTriples::Resource
43
+ class Person
44
+ include ActiveTriples::RDFSource
43
45
  configure :type => RDF::FOAF.Person, :base_uri => 'http://example.org/people#'
44
46
  property :name, :predicate => RDF::FOAF.name
45
47
  end
@@ -56,24 +58,24 @@ obj_2.dump :ntriples # => "<http://example.org/things#2> <http://www.w3.org/1999
56
58
  Open Model
57
59
  -----------
58
60
 
59
- A Resource lets you handle data as a graph, independent of whether it is defined in the model. This is important for working in a Linked Data context, where you will want access to data you may not have known about when your models were written.
61
+ An RDFSource lets you handle data as a graph, independent of whether it is defined in the model. This is important for working in a Linked Data context, where you will want access to data you may not have known about when your models were written.
60
62
 
61
63
  ```ruby
62
64
  related = Thing.new
63
65
 
64
66
  related << RDF::Statement(related, RDF::DC.relation, obj)
65
67
  related << RDF::Statement(related, RDF::DC.subject, 'ActiveTriples')
66
-
68
+
67
69
  related.query(:subject => related, :predicate => RDF::DC.relation).each_statement {|s,p,o| puts o}
68
70
  # => http://example.org/things#123
69
71
  related.query(:subject => subject, :predicate => RDF::DC.relation).each_statement {|s,p,o| puts o}
70
72
  # => http://example.org/things#123
71
73
  ```
72
74
 
73
- Any operation you can run against an RDF::Graph works with Resources, too. Or you can use generic setters and getters with URI predicates:
75
+ Any operation you can run against an RDF::Graph works with RDFSources, too. Or you can use generic setters and getters with URI predicates:
74
76
 
75
77
  ```ruby
76
- related.set_value(RDF::DC.relation, obj)
78
+ related.set_value(RDF::DC.relation, obj)
77
79
  related.set_value(RDF::DC.subject, 'ActiveTriples')
78
80
 
79
81
  related.get_values(RDF::DC.relation) # => [#<Thing:0x3f949c6a2294(default)>]
@@ -81,7 +83,7 @@ related.get_values(RDF::DC.subject) # => ["ActiveTriples"]
81
83
  ```
82
84
 
83
85
  Some convienience methods provide support for handling data from web sources:
84
- * `fetch` loads data from the Resource's #rdf_subject URI
86
+ * `fetch` loads data from the RDFSource's #rdf_subject URI
85
87
  * `rdf_label` queries across common (& configured) label fields and returning the best match
86
88
 
87
89
  ```ruby
@@ -115,10 +117,10 @@ Data is cast back to the appropriate class when it is accessed.
115
117
  my_thing.date
116
118
  # => [Thu, 19 Jun 2014]
117
119
  ```
118
-
120
+
119
121
  Note that you can mix types on a single property.
120
122
 
121
- ```ruby
123
+ ```ruby
122
124
  my_thing.date << DateTime.now
123
125
  my_thing.date << "circa 2014"
124
126
  my_thing.date
@@ -143,12 +145,15 @@ Resources can persist to various databases and triplestores though integration w
143
145
  ActiveTriples::Repositories.add_repository :default, RDF::Repository.new
144
146
  ActiveTriples::Repositories.add_repository :people, RDF::Repository.new
145
147
 
146
- class Person < ActiveTriples::Resource
148
+ class Person
149
+ include ActiveTriples::RDFSource
147
150
  configure :type => RDF::FOAF.Person, :base_uri => 'http://example.org/people#', :repository => :people
148
151
  property :name, :predicate => RDF::FOAF.name
149
152
  end
150
153
 
151
- class Thing < ActiveTriples::Resource
154
+ class Thing
155
+ include ActiveTriples::RDFSource
156
+
152
157
  configure :type => RDF::OWL.Thing, :base_uri => 'http://example.org/things#', :repository => :default
153
158
  property :title, :predicate => RDF::DC.title
154
159
  property :description, :predicate => RDF::DC.description
@@ -183,4 +188,3 @@ Please observe the following guidelines:
183
188
  - Organize your commits into logical units.
184
189
  - Don't leave trailing whitespace (i.e. run ```git diff --check``` before committing).
185
190
  - Use [well formed](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html) commit messages.
186
-
@@ -5,9 +5,10 @@ require 'active_support'
5
5
  module ActiveTriples
6
6
  extend ActiveSupport::Autoload
7
7
  eager_autoload do
8
+ autoload :RDFSource
8
9
  autoload :Resource
9
10
  autoload :List
10
- autoload :Term
11
+ autoload :Relation
11
12
  autoload :Configurable
12
13
  autoload :Properties
13
14
  autoload :PropertyBuilder
@@ -16,6 +17,10 @@ module ActiveTriples
16
17
  autoload :NodeConfig
17
18
  autoload :NestedAttributes
18
19
  autoload :Identifiable
20
+ autoload :Configuration
21
+
22
+ # deprecated class
23
+ autoload :Term, 'active_triples/relation'
19
24
  end
20
25
 
21
26
  # Raised when a declared repository doesn't have a definition
@@ -12,17 +12,20 @@ module ActiveTriples
12
12
  # Available properties are base_uri, rdf_label, type, and repository
13
13
  module Configurable
14
14
  extend Deprecation
15
-
16
15
  def base_uri
17
- nil
16
+ configuration[:base_uri]
18
17
  end
19
18
 
20
19
  def rdf_label
21
- nil
20
+ configuration[:rdf_label]
22
21
  end
23
22
 
24
23
  def type
25
- nil
24
+ configuration[:type]
25
+ end
26
+
27
+ def configuration
28
+ @configuration ||= Configuration.new
26
29
  end
27
30
 
28
31
  ##
@@ -33,7 +36,7 @@ module ActiveTriples
33
36
  end
34
37
 
35
38
  def repository
36
- :parent
39
+ configuration[:repository] || :parent
37
40
  end
38
41
 
39
42
  ##
@@ -52,24 +55,20 @@ module ActiveTriples
52
55
  #
53
56
  # @param options [Hash]
54
57
  def configure(options = {})
55
- {
56
- base_uri: options[:base_uri],
57
- rdf_label: options[:rdf_label],
58
- type: options[:type],
59
- repository: options[:repository]
60
- }.each do |name, value|
61
- if value
62
- value = self.send("transform_#{name}", value) if self.respond_to?("transform_#{name}")
63
- define_singleton_method(name) do
64
- value
65
- end
58
+ options = options.map do |key, value|
59
+ if self.respond_to?("transform_#{key}")
60
+ value = self.__send__("transform_#{key}", value)
66
61
  end
62
+ [key, value]
67
63
  end
64
+ @configuration = configuration.merge(options)
68
65
  end
69
66
 
70
- def transform_type(value)
71
- RDF::URI.new(value).tap do |value|
72
- Resource.type_registry[value] = self
67
+ def transform_type(values)
68
+ Array(values).map do |value|
69
+ RDF::URI.new(value).tap do |uri|
70
+ Resource.type_registry[uri] = self
71
+ end
73
72
  end
74
73
  end
75
74
  end
@@ -0,0 +1,72 @@
1
+ module ActiveTriples
2
+ require_relative 'configuration/item'
3
+ require_relative 'configuration/merge_item'
4
+ require_relative 'configuration/item_factory'
5
+ ##
6
+ # Class which contains configuration for RDFSources.
7
+ class Configuration
8
+ attr_accessor :inner_hash
9
+ # @param [Hash] options the configuration options.
10
+ def initialize(options={})
11
+ @inner_hash = Hash[options.to_a]
12
+ end
13
+
14
+ # Merges this configuration with other configuration options. This uses
15
+ # reflection setters to handle special cases like :type.
16
+ #
17
+ # @param [Hash] options configuration options to merge in.
18
+ # @return [ActiveTriples::Configuration] the configuration object which is a
19
+ # result of merging.
20
+ def merge(options)
21
+ new_config = Configuration.new(options)
22
+ new_config.items.each do |property, item|
23
+ build_configuration_item(property).set item.value
24
+ end
25
+ self
26
+ end
27
+
28
+ # Returns a hash with keys as the configuration property and values as
29
+ # reflections which know how to set a new value to it.
30
+ #
31
+ # @return [Hash{Symbol => ActiveTriples::Configuration::Item}]
32
+ def items
33
+ to_h.each_with_object({}) do |config_value, hsh|
34
+ key = config_value.first
35
+ hsh[key] = build_configuration_item(key)
36
+ end
37
+ end
38
+
39
+ # Returns the configured value for an option
40
+ #
41
+ # @return the configured value
42
+ def [](value)
43
+ to_h[value]
44
+ end
45
+
46
+ # Returns the available configured options as a hash.
47
+ #
48
+ # This filters the options the class is initialized with.
49
+ #
50
+ # @return [Hash{Symbol => String, ::RDF::URI}]
51
+ def to_h
52
+ @inner_hash.slice(*valid_config_options)
53
+ end
54
+
55
+ protected
56
+
57
+ def build_configuration_item(key)
58
+ configuration_item_factory.new(self, key)
59
+ end
60
+
61
+ private
62
+
63
+ def configuration_item_factory
64
+ @configuration_item_factory ||= ItemFactory.new
65
+ end
66
+
67
+ def valid_config_options
68
+ [:base_uri, :rdf_label, :type, :repository]
69
+ end
70
+ end
71
+
72
+ end
@@ -0,0 +1,20 @@
1
+ module ActiveTriples
2
+ class Configuration
3
+ # Basic configuration item which overrides the value for a key on the object.
4
+ class Item
5
+ attr_reader :object, :key
6
+ def initialize(object, key)
7
+ @object = object
8
+ @key = key
9
+ end
10
+
11
+ def value
12
+ object.inner_hash[key]
13
+ end
14
+
15
+ def set(value)
16
+ object.inner_hash[key] = value
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,27 @@
1
+ module ActiveTriples
2
+ class Configuration
3
+ ## Returns a configuration item appropriate for a given configuration property.
4
+ class ItemFactory
5
+ # @return [MergeItem, Item]
6
+ def new(object, name)
7
+ if merge_configs.include?(name)
8
+ merge_item.new(object, name)
9
+ else
10
+ item.new(object, name)
11
+ end
12
+ end
13
+
14
+ def merge_item
15
+ MergeItem
16
+ end
17
+
18
+ def item
19
+ Item
20
+ end
21
+
22
+ def merge_configs
23
+ [:type]
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,14 @@
1
+ module ActiveTriples
2
+ class Configuration
3
+ # Configuration item which sets a value by turning the original into an array and
4
+ # appending the given value to it.
5
+ #
6
+ # This enables multiple types to be set on an object, for example.
7
+ class MergeItem < Item
8
+ def set(value)
9
+ object.inner_hash[key] = Array(object.inner_hash[key])
10
+ object.inner_hash[key] |= Array(value)
11
+ end
12
+ end
13
+ end
14
+ end
@@ -7,12 +7,12 @@ module ActiveTriples::Identifiable
7
7
  delegate :rdf_subject, :type, to: :resource
8
8
 
9
9
  ##
10
- # @return [ActiveTriples::Resource] a resource that contains this object's
10
+ # @return [ActiveTriples::Resource] a resource that contains this object's
11
11
  # graph.
12
12
  def resource
13
13
  @resource ||= resource_class.new(to_uri)
14
14
  end
15
-
15
+
16
16
  def parent
17
17
  @parent ||= resource.parent
18
18
  end
@@ -21,7 +21,7 @@ module ActiveTriples::Identifiable
21
21
  @parent = val
22
22
  end
23
23
 
24
- ##
24
+ ##
25
25
  # @return [String] a uri or slug
26
26
  def to_uri
27
27
  return id if respond_to? :id and !resource_class.base_uri.nil?
@@ -28,7 +28,7 @@ module ActiveTriples
28
28
  def initialize(*args)
29
29
  super
30
30
  parent = graph.parent if graph.respond_to? :parent
31
- @graph = ListResource.new(subject) << graph unless graph.kind_of? Resource
31
+ @graph = ListResource.new(subject) << graph unless graph.kind_of? RDFSource
32
32
  graph << parent if parent
33
33
  graph.list = self
34
34
  graph.reload
@@ -97,7 +97,9 @@ module ActiveTriples
97
97
  ##
98
98
  # This class is the graph/Resource that backs the List and
99
99
  # supplies integration with the rest of ActiveTriples
100
- class ListResource < Resource
100
+ class ListResource
101
+ include ActiveTriples::RDFSource
102
+
101
103
  attr_reader :list
102
104
 
103
105
  def list=(list)
@@ -171,11 +173,11 @@ module ActiveTriples
171
173
  @graph.type = RDF.List
172
174
  resource.set_value(RDF.first, value)
173
175
  resource.insert([subject, RDF.rest, RDF.nil])
174
- resource << value if value.kind_of? Resource
176
+ resource << value if value.kind_of? RDFSource
175
177
  return self
176
178
  end
177
179
  super
178
- resource << value if value.kind_of? Resource
180
+ resource << value if value.kind_of? RDFSource
179
181
  end
180
182
  end
181
183
  end