active-triples 0.8.1 → 0.8.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +8 -9
  3. data/CHANGES.md +69 -0
  4. data/Gemfile +0 -2
  5. data/Guardfile +1 -2
  6. data/active-triples.gemspec +3 -3
  7. data/lib/active/triples.rb +1 -0
  8. data/lib/active_triples.rb +4 -0
  9. data/lib/active_triples/configurable.rb +3 -1
  10. data/lib/active_triples/configuration.rb +1 -0
  11. data/lib/active_triples/configuration/item.rb +1 -0
  12. data/lib/active_triples/configuration/item_factory.rb +1 -0
  13. data/lib/active_triples/configuration/merge_item.rb +5 -2
  14. data/lib/active_triples/extension_strategy.rb +1 -0
  15. data/lib/active_triples/identifiable.rb +1 -0
  16. data/lib/active_triples/list.rb +2 -0
  17. data/lib/active_triples/nested_attributes.rb +1 -1
  18. data/lib/active_triples/node_config.rb +5 -3
  19. data/lib/active_triples/persistable.rb +1 -0
  20. data/lib/active_triples/persistence_strategies/parent_strategy.rb +104 -29
  21. data/lib/active_triples/persistence_strategies/persistence_strategy.rb +15 -7
  22. data/lib/active_triples/persistence_strategies/repository_strategy.rb +26 -22
  23. data/lib/active_triples/properties.rb +84 -6
  24. data/lib/active_triples/property.rb +35 -4
  25. data/lib/active_triples/property_builder.rb +38 -4
  26. data/lib/active_triples/rdf_source.rb +225 -75
  27. data/lib/active_triples/reflection.rb +42 -3
  28. data/lib/active_triples/relation.rb +330 -73
  29. data/lib/active_triples/repositories.rb +4 -2
  30. data/lib/active_triples/resource.rb +1 -0
  31. data/lib/active_triples/schema.rb +1 -0
  32. data/lib/active_triples/undefined_property_error.rb +27 -0
  33. data/lib/active_triples/version.rb +2 -1
  34. data/spec/active_triples/configurable_spec.rb +3 -2
  35. data/spec/active_triples/configuration_spec.rb +2 -1
  36. data/spec/active_triples/extension_strategy_spec.rb +2 -1
  37. data/spec/active_triples/identifiable_spec.rb +7 -11
  38. data/spec/active_triples/list_spec.rb +1 -4
  39. data/spec/active_triples/nested_attributes_spec.rb +4 -3
  40. data/spec/active_triples/persistable_spec.rb +4 -1
  41. data/spec/active_triples/persistence_strategies/parent_strategy_spec.rb +141 -11
  42. data/spec/active_triples/persistence_strategies/persistence_strategy_spec.rb +1 -0
  43. data/spec/active_triples/persistence_strategies/repository_strategy_spec.rb +32 -17
  44. data/spec/active_triples/properties_spec.rb +68 -33
  45. data/spec/active_triples/property_builder_spec.rb +36 -0
  46. data/spec/active_triples/property_spec.rb +15 -1
  47. data/spec/active_triples/rdf_source_spec.rb +544 -6
  48. data/spec/active_triples/reflection_spec.rb +78 -0
  49. data/spec/active_triples/relation_spec.rb +505 -3
  50. data/spec/active_triples/repositories_spec.rb +3 -1
  51. data/spec/active_triples/resource_spec.rb +90 -147
  52. data/spec/active_triples/schema_spec.rb +3 -2
  53. data/spec/active_triples_spec.rb +1 -0
  54. data/spec/integration/dummies/dummy_resource_a.rb +6 -0
  55. data/spec/integration/dummies/dummy_resource_b.rb +6 -0
  56. data/spec/integration/parent_persistence_spec.rb +18 -0
  57. data/spec/integration/reciprocal_properties_spec.rb +69 -0
  58. data/spec/pragmatic_context_spec.rb +10 -8
  59. data/spec/spec_helper.rb +5 -0
  60. data/spec/support/active_model_lint.rb +4 -6
  61. data/spec/support/dummies/basic_persistable.rb +2 -11
  62. data/spec/support/matchers.rb +11 -0
  63. data/spec/support/shared_examples/persistence_strategy.rb +3 -16
  64. metadata +20 -13
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4928b254048d00cd2f52d050aea13407ba362425
4
- data.tar.gz: 11c44cb9efe80bfc6dd09f6e33a6aee0d288666d
3
+ metadata.gz: e1f422e5ac96c89ebdaeeb9d97d52ae3d5bfe526
4
+ data.tar.gz: b5fd9203d247be04fccab63466eee59bcc9af078
5
5
  SHA512:
6
- metadata.gz: 665fe27ad696dda89568310375194243760cfa22d8761bc10fc40eca9dcd39a81352c840e283e3501c4eb2504bdb1d663efa96138478660f5f9ab3454d3e874f
7
- data.tar.gz: ec21704f5faf6aadf57ec45c95bfb64113ef772f3fd48c8e7e26f4ddfa9dd08dfe786cd2039743c7b742d9cf24b600141f5e7dcfd1e1579f2d57fc181e625d8b
6
+ metadata.gz: 26f27fa5aae3444a211f339c2dcb5dcf26950b31f6f98697b09977f233fe0e23049a245f2ba1b3262b6104caf27b37e254ea5c829fc30f2daea675250ed4988a
7
+ data.tar.gz: 22400ed6fd5ace6f4772ca8b1c0ddb5a98e99be0d38fdeac42a8bce900d7cf65226e44c399fd38e1174770d1f040a0a98b4bd0589751fa27194443fa17591c3d
@@ -4,14 +4,13 @@ script: "bundle exec rspec spec"
4
4
  sudo: false
5
5
  cache: bundler
6
6
  rvm:
7
- - 2.0.0
8
- - 2.1.0
9
- - 2.1.1
10
- - 2.2.1
11
- - ruby-head
12
- - jruby
13
- - rbx-2
7
+ - 2.0
8
+ - 2.1
9
+ - 2.2.4
10
+ - 2.3.0
11
+ - jruby-9.0.4.0
12
+ - rbx-2
14
13
  matrix:
15
14
  allow_failures:
16
- - rvm: jruby
17
- - rvm: ruby-head
15
+ - rvm: jruby-9.0.4.0
16
+ - rvm: rbx-2
data/CHANGES.md CHANGED
@@ -1,3 +1,72 @@
1
+ 0.8.2
2
+ -----
3
+ * Allow PersistenceStrategy set by property config [Tom Johnson]
4
+ * Extend NodeConfig for arbitrary properties [Tom Johnson]
5
+ * Add `Relation#delete?` and `#swap` [Tom Johnson]
6
+ * Make Relation#delete singular; add #subtract [Tom Johnson]
7
+ * Re-add `Relation#delete` with a new implementation [Tom Johnson]
8
+ * Documentation and formatting cleanup on Relation [Tom Johnson]
9
+ * Remove Relation#reset! [Tom Johnson]
10
+ * Remove `Relation#[]=` [Tom Johnson]
11
+ * Remove Relation#delete [Tom Johnson]
12
+ * FIX #200 Use == instead of eql? for resource equality test [E. Lynette Rayle]
13
+ * Add some docs and tests for `PropertyBuilder` [Tom Johnson]
14
+ * Test undefined property on Relation#set [Tom Johnson]
15
+ * add loaded flag to lazy load property sources with parent_strategy [E. Lynette Rayle]
16
+ * Add deprecation warning [MJ Suhonos]
17
+ * Rename #obj to #source for clarity [MJ Suhonos]
18
+ * Update Guardfile [MJ Suhonos]
19
+ * Update comment terminology [MJ Suhonos]
20
+ * Remove reference to concrete persistable from abstract class [MJ Suhonos]
21
+ * Allow fetch to pass args to RDF::Reader.open [Justin Coyne]
22
+ * Delegate join to Relation. [Trey Terrell]
23
+ * Change ParentStrategy usage [Tom Johnson]
24
+ * Delegate #size in Relation. [Trey Terrell]
25
+ * Remove singleton_class call from RepositoryStrategy [Tom Johnson]
26
+ * Convert ancestors enumerator method to Class [Tom Johnson]
27
+ * Avoid circularity in `ParentStrategy` [Tom Johnson]
28
+ * Update .travis.yml Rubies to match RDF.rb [Tom Johnson]
29
+ * Add frozen_string_literals pragma [Justin Coyne]
30
+ * Fixup specs [Tom Johnson]
31
+ * Specs/docs for ValueError scenarios on #set_value [Tom Johnson]
32
+ * Add initial docs/specs for `RDFSource#attributes` [Tom Johnson]
33
+ * Add docs and specs for `Relation#first_or_create` [Tom Johnson]
34
+ * Add tests & docs for `Relation#build` [Tom Johnson]
35
+ * Make `Relation#clear` atomic [Tom Johnson]
36
+ * Test `RDFSource#rdf_label` [Tom Johnson]
37
+ * Fix for circular parent relationships [Tom Johnson]
38
+ * Add documentation and tests for key Relation [Tom Johnson]
39
+ * Refactor Relation#value_arguments [Tom Johnson]
40
+ * Move property methods from RDFSource in Properties [Tom Johnson]
41
+ * Add documentation and some tests for Properties [Tom Johnson]
42
+ * Refactor and rearrange RDFSource & Reflection [Tom Johnson]
43
+ * Finish documentation and testing of Reflection [Tom Johnson]
44
+ * Cleaner handling of undefined properties [Tom Johnson]
45
+ * Add some tests for `#get_values` [Tom Johnson]
46
+ * Make `#set_value` return the Relation it updates [Tom Johnson]
47
+ * Add triple in `#set_value` when argument is self [Tom Johnson]
48
+ * Removes odd logic surrounding property clearance [Tom Johnson]
49
+ * Removing OpenStruct in favor of PORO [Jeremy Friesen]
50
+ * Switching from Array() to Array.wrap [Jeremy Friesen]
51
+ * Fixup RDF.rb and rdf-spec dependencies [Tom Johnson]
52
+ * Track latest `rdf-spec` and `rdf-vocab` [Tom Johnson]
53
+ * Complete update to use RDF::Vocab [Tom Johnson]
54
+ * Use rdf-vocab for vocabularies [Justin Coyne]
55
+ * Add `RDFSource#graph_name` since quads aren't returned [Tom Johnson]
56
+ * Update specs to use a managable invalid statement [Tom Johnson]
57
+ * Test with develop version of rdf-spec [Justin Coyne]
58
+ * Graph#query is faster than using Queryable#query [Justin Coyne]
59
+ * Update error handling specs. [Tom Johnson]
60
+ * Adds a default block to `RDFSource#fetch` [Tom Johnson]
61
+ * Run `ActiveModel` lints on `RDFSource` [Tom Johnson]
62
+ * Fix ActiveModel linter to test `#to_key` [Tom Johnson]
63
+ * Remove unnecessary lines in `parent_strategy_spec` [Tom Johnson]
64
+ * Make `Relation#predicate` a public method [Tom Johnson]
65
+ * Cleanup and unit tests for `RDFSource#get_value` [Tom Johnson]
66
+ * Test ActiveModel validations with RDF's `#valid?` [Tom Johnson]
67
+ * Children should not be persisted? unless their parents are. Fixes #148 [Justin Coyne]
68
+
69
+
1
70
  0.8.1
2
71
  -----
3
72
 
data/Gemfile CHANGED
@@ -3,5 +3,3 @@ source "https://rubygems.org"
3
3
  gemspec
4
4
 
5
5
  gem 'pry-byebug' unless ENV["CI"]
6
-
7
- gem 'rdf-spec', :github => 'ruby-rdf/rdf-spec', :branch => 'develop'
data/Guardfile CHANGED
@@ -1,9 +1,8 @@
1
1
  # A sample Guardfile
2
2
  # More info at https://github.com/guard/guard#readme
3
3
 
4
- guard :rspec do
4
+ guard :rspec, cmd: "bundle exec rspec" do
5
5
  watch(%r{^spec/.+_spec\.rb$})
6
6
  watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
7
7
  watch('spec/spec_helper.rb') { "spec" }
8
8
  end
9
-
@@ -14,15 +14,15 @@ Gem::Specification.new do |s|
14
14
  s.license = "APACHE2"
15
15
  s.required_ruby_version = '>= 1.9.3'
16
16
 
17
- s.add_dependency('rdf', '~> 1.1.13')
18
- s.add_dependency('linkeddata', '~> 1.1')
17
+ s.add_dependency('rdf', '1.99')
18
+ s.add_dependency('linkeddata', '~> 1.99')
19
19
  s.add_dependency('activemodel', '>= 3.0.0')
20
20
  s.add_dependency('deprecation', '~> 0.1')
21
21
  s.add_dependency('activesupport', '>= 3.0.0')
22
22
 
23
23
  s.add_development_dependency('rdoc')
24
24
  s.add_development_dependency('rspec')
25
- s.add_development_dependency('rdf-spec')
25
+ s.add_development_dependency('rdf-spec', '~> 1.99')
26
26
  s.add_development_dependency('coveralls')
27
27
  s.add_development_dependency('guard-rspec')
28
28
  s.add_development_dependency('webmock')
@@ -1 +1,2 @@
1
+ # frozen_string_literal: true
1
2
  require 'active_triples'
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'rdf'
2
3
  require 'active_triples/version'
3
4
  require 'active_support'
@@ -53,6 +54,9 @@ module ActiveTriples
53
54
  'active_triples/persistence_strategies/parent_strategy'
54
55
  autoload :RepositoryStrategy,
55
56
  'active_triples/persistence_strategies/repository_strategy'
57
+
58
+ # error classes
59
+ autoload :UndefinedPropertyError
56
60
  end
57
61
 
58
62
  ##
@@ -1,4 +1,6 @@
1
+ # frozen_string_literal: true
1
2
  require 'deprecation'
3
+ require 'active_support/core_ext/array/wrap'
2
4
 
3
5
  module ActiveTriples
4
6
  ##
@@ -61,7 +63,7 @@ module ActiveTriples
61
63
  end
62
64
 
63
65
  def transform_type(values)
64
- Array(values).map do |value|
66
+ Array.wrap(values).map do |value|
65
67
  RDF::URI.new(value).tap do |uri|
66
68
  RDFSource.type_registry[uri] = self
67
69
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module ActiveTriples
2
3
  require_relative 'configuration/item'
3
4
  require_relative 'configuration/merge_item'
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module ActiveTriples
2
3
  class Configuration
3
4
  # Basic configuration item which overrides the value for a key on the object.
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module ActiveTriples
2
3
  class Configuration
3
4
  ## Returns a configuration item appropriate for a given configuration property.
@@ -1,3 +1,6 @@
1
+ # frozen_string_literal: true
2
+ require 'active_support/core_ext/array/wrap'
3
+
1
4
  module ActiveTriples
2
5
  class Configuration
3
6
  # Configuration item which sets a value by turning the original into an array and
@@ -6,8 +9,8 @@ module ActiveTriples
6
9
  # This enables multiple types to be set on an object, for example.
7
10
  class MergeItem < Item
8
11
  def set(value)
9
- object.inner_hash[key] = Array(object.inner_hash[key])
10
- object.inner_hash[key] |= Array(value)
12
+ object.inner_hash[key] = Array.wrap(object.inner_hash[key])
13
+ object.inner_hash[key] |= Array.wrap(value)
11
14
  end
12
15
  end
13
16
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module ActiveTriples
2
3
  ##
3
4
  # Default property applying strategy which just copies all configured properties
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'active_support'
2
3
  require 'active_support/core_ext/module/delegation'
3
4
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module ActiveTriples
2
3
  ##
3
4
  # An implementation of RDF::List intregrated with ActiveTriples.
@@ -162,6 +163,7 @@ module ActiveTriples
162
163
  if subject == RDF.nil
163
164
  @subject = RDF::Node.new
164
165
  @graph = ListResource.new(subject)
166
+ @graph.list = self
165
167
  @graph.type = RDF.List
166
168
  end
167
169
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'active_support'
2
3
  require 'active_support/concern'
3
4
  require 'active_support/core_ext/class'
@@ -121,7 +122,6 @@ module ActiveTriples
121
122
  assign_nested_attributes_for_collection_association(:#{association_name}, attributes)
122
123
  ## in lieu of autosave_association_callbacks just save all of em.
123
124
  send(:#{association_name}).each {|obj| obj.marked_for_destruction? ? obj.destroy : nil}
124
- send(:#{association_name}).reset!
125
125
  end
126
126
  eoruby
127
127
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module ActiveTriples
2
3
  class NodeConfig
3
4
  attr_accessor :predicate, :term, :class_name, :type, :behaviors, :cast
@@ -5,14 +6,15 @@ module ActiveTriples
5
6
  def initialize(term, predicate, args={})
6
7
  self.term = term
7
8
  self.predicate = predicate
8
- self.class_name = args.fetch(:class_name) { default_class_name }
9
- self.cast = args.fetch(:cast) { true }
9
+ self.class_name = args.delete(:class_name) { default_class_name }
10
+ self.cast = args.delete(:cast) { true }
11
+ @opts = args
10
12
  yield(self) if block_given?
11
13
  end
12
14
 
13
15
  def [](value)
14
16
  value = value.to_sym
15
- self.respond_to?(value) ? self.send(value) : nil
17
+ self.respond_to?(value) ? self.send(value) : @opts[value]
16
18
  end
17
19
 
18
20
  def class_name
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module ActiveTriples
2
3
  ##
3
4
  # Bundles the core interfaces used by ActiveTriples persistence strategies
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module ActiveTriples
2
3
  ##
3
4
  # Persistence strategy for projecting `RDFSource`s onto the graph of an owning
@@ -6,50 +7,76 @@ module ActiveTriples
6
7
  class ParentStrategy
7
8
  include PersistenceStrategy
8
9
 
9
- # @!attribute [r] obj
10
+ # @!attribute [r] source
10
11
  # the source to persist with this strategy
11
12
  # @!attribute [r] parent
12
13
  # the target parent source for persistence
13
- attr_reader :obj, :parent
14
+ attr_reader :source, :parent
14
15
 
15
16
  ##
16
- # @param obj [RDFSource, RDF::Enumerable] the `RDFSource` (or other
17
+ # @param source [RDFSource, RDF::Enumerable] the `RDFSource` (or other
17
18
  # `RDF::Enumerable` to persist with the strategy.
18
- def initialize(obj)
19
- @obj = obj
19
+ def initialize(source)
20
+ @source = source
20
21
  end
21
22
 
23
+ ##
24
+ # Resources using this strategy are persisted only if their parent is also
25
+ # persisted.
26
+ #
27
+ # @see PersistenceStrategy#persisted?
28
+ def persisted?
29
+ super && parent.persisted?
30
+ end
31
+
32
+ ##
33
+ # Indicates if the resource has been loaded from the repository (used for lazy load)
34
+ #
35
+ # @return [Boolean] true if loaded; else false.
36
+ def loaded?
37
+ @loaded ||= false
38
+ end
39
+
40
+ ##
41
+ # Destroys the resource by removing it graph and references from the
42
+ # parent.
43
+ #
44
+ # @see PersistenceStrategy#destroy
22
45
  def destroy
23
- super { parent.destroy_child(obj) }
46
+ final_parent.delete(source.statements)
47
+
48
+ parent.statements.each do |statement|
49
+ parent.delete_statement(statement) if
50
+ statement.subject == source.rdf_subject ||
51
+ statement.object == source.rdf_subject
52
+ end
53
+
54
+ super { source.clear }
24
55
  end
25
56
 
26
- # Clear out any old assertions in the repository about this node or statement
27
- # thus preparing to receive the updated assertions.
57
+ ##
58
+ # @abstract Clear out any old assertions in the datastore / repository
59
+ # about this node or statement thus preparing to receive the updated
60
+ # assertions.
28
61
  def erase_old_resource
29
- if obj.rdf_subject.node?
30
- final_parent.statements.each do |statement|
31
- final_parent.send(:delete_statement, statement) if
32
- statement.subject == obj.rdf_subject
33
- end
34
- else
35
- final_parent.delete [obj.rdf_subject, nil, nil]
62
+ final_parent.statements.each do |statement|
63
+ final_parent.send(:delete_statement, statement) if
64
+ statement.subject == source.rdf_subject
36
65
  end
37
66
  end
38
67
 
68
+ ##
69
+ # @return [Enumerator<RDFSource>]
70
+ def ancestors
71
+ Ancestors.new(source).to_enum
72
+ end
73
+
39
74
  ##
40
75
  # @return [#persist!] the last parent in a chain from `parent` (e.g.
41
76
  # the parent's parent's parent). This is the RDF::Mutable that the
42
- # object will project itself on when persisting.
77
+ # resource will project itself on when persisting.
43
78
  def final_parent
44
- raise NilParentError if parent.nil?
45
- @final_parent ||= begin
46
- current = self.parent
47
- while current && current.respond_to?(:parent) && current.parent
48
- break if current.parent == current
49
- current = current.parent
50
- end
51
- current
52
- end
79
+ ancestors.to_a.last
53
80
  end
54
81
 
55
82
  ##
@@ -64,12 +91,12 @@ module ActiveTriples
64
91
  end
65
92
 
66
93
  ##
67
- # Persists the object to the final parent.
94
+ # Persists the resource to the final parent.
68
95
  #
69
96
  # @return [true] true if the save did not error
70
97
  def persist!
71
98
  erase_old_resource
72
- final_parent << obj
99
+ final_parent << source
73
100
  @persisted = true
74
101
  end
75
102
 
@@ -78,11 +105,59 @@ module ActiveTriples
78
105
  #
79
106
  # @return [Boolean]
80
107
  def reload
81
- obj << final_parent.query(subject: obj.rdf_subject)
82
- @persisted = true unless obj.empty?
108
+ if loaded? || !persisted?
109
+ source << final_parent.query(subject: source.rdf_subject)
110
+ else
111
+ RepositoryStrategy.new(source).reload
112
+ source.persist!
113
+ @loaded=true
114
+ end
115
+ @persisted = true unless source.empty?
83
116
  true
84
117
  end
85
118
 
119
+ ##
120
+ # An enumerable over the ancestors of an resource
121
+ class Ancestors
122
+ include Enumerable
123
+
124
+ # @!attribute source
125
+ # @return [RDFSource]
126
+ attr_reader :source
127
+
128
+ ##
129
+ # @param source [RDFSource]
130
+ def initialize(source)
131
+ @source = source
132
+ end
133
+
134
+ ##
135
+ # @yield [RDFSource] gives each ancestor to the block
136
+ # @return [Enumerator<RDFSource>]
137
+ #
138
+ # @raise [NilParentError] if `source` does not persist to a parent
139
+ def each
140
+ raise NilParentError if
141
+ !source.persistence_strategy.respond_to?(:parent) ||
142
+ source.persistence_strategy.parent.nil?
143
+
144
+ current = source.persistence_strategy.parent
145
+
146
+ if block_given?
147
+ loop do
148
+ yield current
149
+
150
+ break unless (current.persistence_strategy.respond_to?(:parent) &&
151
+ current.persistence_strategy.parent)
152
+ break if current.persistence_strategy.parent == current
153
+
154
+ current = current.persistence_strategy.parent
155
+ end
156
+ end
157
+ to_enum
158
+ end
159
+ end
160
+
86
161
  class NilParentError < RuntimeError; end
87
162
  class UnmutableParentError < ArgumentError; end
88
163
  end