ldp 0.4.1 → 0.5.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: 882fd676e2cd2aac5923a8f7a4b308228569607b
4
- data.tar.gz: b94c819301cb2ab968085aa6ca371b4eec682e94
3
+ metadata.gz: 3a68882c3e0ea6d21e3819d632a92e88734bec0f
4
+ data.tar.gz: a3f31f5e16fc2a60b109bef5f7da218ad008e949
5
5
  SHA512:
6
- metadata.gz: d4efcff3ae303486a051bc22477ce087e89ee197d2eba531aee9d8c9bbf9767d06f6949f0be830627539377c78828c4d542e08d7a81daaaec9714892e6831cdd
7
- data.tar.gz: b3a69169e198f975e8cdb1b5be96e9d9aedbda161eda6c9deac37393ed4615949edb8a970d531c3b8faa7889eb53d62c254366643cb33d207c2da5b9895e72a8
6
+ metadata.gz: 4111cddaaccda626e39b8ba24619763ca217f97915855ba2fb936e7fcb7ba1f9d6afc78d268393f7c3a67128d6427a0a41f99b2d24d2f09d41e287e5aa1f1ae0
7
+ data.tar.gz: 173b2d3954e4aa0184a5d87916c637c8348fe185ad561b51cdc28b844d81c14bf820bcdac27551d097f6ccf348c35eaf5c49d20759741ce3cf64571f963dd133
data/.gitignore CHANGED
@@ -15,3 +15,4 @@ spec/reports
15
15
  test/tmp
16
16
  test/version_tmp
17
17
  tmp
18
+ .storage
@@ -1,3 +1,7 @@
1
+ addons:
2
+ apt:
3
+ packages:
4
+ - libgmp-dev
1
5
  language: ruby
2
6
  cache: bundler
3
7
  sudo: false
@@ -5,6 +9,7 @@ env:
5
9
  global:
6
10
  - NOKOGIRI_USE_SYSTEM_LIBRARIES=true
7
11
  rvm:
8
- - 2.1
9
- - 2.2
10
- - jruby
12
+ - 2.3.0
13
+ - 2.2.4
14
+ - 2.1.8
15
+ - jruby-9.0.5.0
data/Gemfile CHANGED
@@ -4,5 +4,7 @@ source 'https://rubygems.org'
4
4
  gemspec
5
5
 
6
6
  gem 'slop', '~> 3.6' if RUBY_PLATFORM == "java"
7
- gem 'byebug', platforms: :mri_20
7
+ gem 'byebug', platforms: [:mri]
8
8
  gem 'activesupport'
9
+ gem 'capybara_discoball'
10
+ gem 'derby'
@@ -12,6 +12,7 @@ Gem::Specification.new do |spec|
12
12
  spec.summary = spec.description
13
13
  spec.homepage = "https://github.com/projecthydra/ldp"
14
14
  spec.license = "APACHE2"
15
+ spec.required_ruby_version = '~> 2.0'
15
16
 
16
17
  spec.files = `git ls-files`.split($/)
17
18
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
@@ -20,9 +21,13 @@ Gem::Specification.new do |spec|
20
21
 
21
22
  spec.add_dependency "faraday"
22
23
  spec.add_dependency "linkeddata", ">= 1.1"
24
+ spec.add_dependency "rdf-vocab"
23
25
  spec.add_dependency "http_logger"
26
+ spec.add_dependency "deprecation"
24
27
  spec.add_dependency "slop"
25
28
  spec.add_development_dependency "bundler", "~> 1.3"
26
29
  spec.add_development_dependency "rake"
27
30
  spec.add_development_dependency "rspec"
31
+ spec.add_development_dependency "coveralls"
32
+ spec.add_development_dependency "simplecov"
28
33
  end
data/lib/ldp.rb CHANGED
@@ -1,11 +1,14 @@
1
1
  require 'ldp/version'
2
2
  require 'linkeddata'
3
+ require 'rdf/vocab/ldp'
3
4
  require 'logger'
4
5
  require 'singleton'
6
+ require 'deprecation'
5
7
 
6
8
  module Ldp
7
9
  RDF::Graph.send(:include, RDF::Isomorphic)
8
10
 
11
+ require 'ldp/error'
9
12
  require 'ldp/client'
10
13
  require 'ldp/uri'
11
14
 
@@ -17,15 +20,6 @@ module Ldp
17
20
 
18
21
  autoload :Orm, 'ldp/orm'
19
22
 
20
- class HttpError < RuntimeError; end
21
- class BadRequest < HttpError; end # 400
22
- class NotFound < HttpError; end # 404
23
- class Conflict < HttpError; end # 409
24
- class Gone < HttpError; end # 410
25
- class EtagMismatch < HttpError; end # 412
26
-
27
- class UnexpectedContentType < RuntimeError; end
28
-
29
23
  # Returned when there is no result (e.g. 404)
30
24
  class NoneClass
31
25
  include Singleton
@@ -7,24 +7,29 @@ module Ldp
7
7
  require 'ldp/client/prefer_headers'
8
8
  include Ldp::Client::Methods
9
9
 
10
- def initialize *http_client
11
- initialize_http_client *http_client
12
- end
10
+ attr_reader :options
13
11
 
14
- # Find or initialize a new LDP resource by URI
15
- def find_or_initialize subject, options = {}
16
- data = get(subject, options = {})
17
-
18
- case
19
- when !data.is_a?(Ldp::Response)
20
- Resource::BinarySource.new self, subject, data
21
- when data.container?
22
- Ldp::Container.new_from_response self, subject, data
23
- when data.resource?
24
- Resource::RdfSource.new self, subject, data
12
+ def initialize(*args)
13
+ http_client, options = if args.length == 2
14
+ args
15
+ elsif args.length == 1 && args.first.is_a?(Faraday::Connection)
16
+ [args.first, {}]
17
+ elsif args.length == 1
18
+ [nil, args.first]
25
19
  else
26
- Resource::BinarySource.new self, subject, data
20
+ raise ArgumentError
27
21
  end
22
+
23
+ @options = options
24
+
25
+ initialize_http_client(http_client || options)
26
+ end
27
+
28
+ # Find or initialize a new LDP resource by URI
29
+ def find_or_initialize(subject, options = {})
30
+ data = get(subject, options)
31
+
32
+ Ldp::Resource.for(self, subject, data)
28
33
  end
29
34
 
30
35
  def logger
@@ -23,6 +23,8 @@ module Ldp::Client::Methods
23
23
  end
24
24
 
25
25
  check_for_errors(resp)
26
+
27
+ Ldp::Response.new(resp)
26
28
  end
27
29
  end
28
30
 
@@ -48,13 +50,9 @@ module Ldp::Client::Methods
48
50
  yield req if block_given?
49
51
  end
50
52
 
51
- if Ldp::Response.resource? resp
52
- Ldp::Response.wrap self, resp
53
- else
54
- resp
55
- end
56
-
57
53
  check_for_errors(resp)
54
+
55
+ Ldp::Response.new(resp)
58
56
  end
59
57
  end
60
58
 
@@ -4,17 +4,27 @@ module Ldp
4
4
  require 'ldp/container/direct'
5
5
  require 'ldp/container/indirect'
6
6
 
7
- def self.new_from_response client, subject, data
7
+ def self.for(client, subject, data)
8
8
  case
9
- when data.types.include?(Ldp.indirect_container)
9
+ when data.types.include?(RDF::Vocab::LDP.IndirectContainer)
10
10
  Ldp::Container::Indirect.new client, subject, data
11
- when data.types.include?(Ldp.direct_container)
11
+ when data.types.include?(RDF::Vocab::LDP.DirectContainer)
12
12
  Ldp::Container::Direct.new client, subject, data
13
13
  else
14
14
  Ldp::Container::Basic.new client, subject, data
15
15
  end
16
16
  end
17
17
 
18
+ class << self
19
+ alias new_from_response for
20
+ end
21
+
22
+ def contains
23
+ @contains ||= Hash[graph.query(predicate: RDF::Vocab::LDP.contains).map do |x|
24
+ [x.object, Ldp::Resource::RdfSource.new(client, x.object, contained_graph(x.object))]
25
+ end]
26
+ end
27
+
18
28
  ##
19
29
  # Add a new resource to the LDP container
20
30
  def add *args
@@ -32,7 +42,7 @@ module Ldp
32
42
  graph_or_content = args.first
33
43
  else
34
44
  slug = args.first
35
- graph_or_content = RDF::Graph.new
45
+ graph_or_content = build_empty_graph
36
46
  end
37
47
 
38
48
  resp = client.post subject, (graph_or_content.is_a?(RDF::Enumerable) ? graph_or_content.dump(:ttl) : graph_or_content) do |req|
@@ -41,5 +51,21 @@ module Ldp
41
51
 
42
52
  client.find_or_initialize resp.headers['Location']
43
53
  end
54
+
55
+ private
56
+
57
+ def contained_graph subject
58
+ g = RDF::Graph.new
59
+ response_graph.query(subject: subject) do |stmt|
60
+ g << stmt
61
+ end
62
+ g
63
+ end
64
+
65
+ def rdf_source_for(object)
66
+ g = contained_graph(object)
67
+
68
+ Ldp::Resource::RdfSource.new(client, object, (g unless g.empty?))
69
+ end
44
70
  end
45
71
  end
@@ -5,19 +5,10 @@ module Ldp
5
5
  contains.each { |k, x| yield x }
6
6
  end
7
7
 
8
- def contains
9
- @contains ||= Hash[get.graph.query(predicate: Ldp.contains).map do |x|
10
- [x.object, Ldp::Resource::RdfSource.new(client, x.object, contained_graph(x.object))]
11
- end]
12
- end
13
-
14
- private
15
- def contained_graph subject
16
- g = RDF::Graph.new
17
- get.graph.query(subject: subject) do |stmt|
18
- g << stmt
19
- end
20
- g
8
+ protected
9
+
10
+ def interaction_model
11
+ RDF::Vocab::LDP.BasicContainer
21
12
  end
22
13
  end
23
14
  end
@@ -2,15 +2,20 @@ module Ldp
2
2
  class Container::Direct < Container::Basic
3
3
  def members
4
4
  return enum_for(:members) unless block_given?
5
-
6
- get.graph.query(subject: subject, predicate: member_relation).map do |x|
7
- yield contains[x.object] || Ldp::Resource::RdfSource.new(client, x.object)
5
+
6
+ response_graph.query(subject: subject, predicate: member_relation).map do |x|
7
+ yield rdf_source_for(x.object)
8
8
  end
9
9
  end
10
-
10
+
11
11
  def member_relation
12
- graph.first_object(predicate: Ldp.hasMemberRelation) || Ldp.member
12
+ response_graph.first_object(predicate: RDF::Vocab::LDP.hasMemberRelation) || RDF::Vocab::LDP.member
13
+ end
14
+
15
+ protected
16
+
17
+ def interaction_model
18
+ RDF::Vocab::LDP.DirectContainer
13
19
  end
14
-
15
20
  end
16
21
  end
@@ -2,10 +2,16 @@ module Ldp
2
2
  class Container::Indirect < Container::Direct
3
3
  def members
4
4
  return enum_for(:members) unless block_given?
5
-
6
- get.graph.query(predicate: member_relation, object: subject).map do |x|
7
- yield contains[x.object] || Ldp::Resource::RdfSource.new(client, x.object)
5
+
6
+ response_graph.query(predicate: member_relation, object: subject).map do |x|
7
+ yield rdf_source_for(x.object)
8
8
  end
9
9
  end
10
+
11
+ protected
12
+
13
+ def interaction_model
14
+ RDF::Vocab::LDP.IndirectContainer
15
+ end
10
16
  end
11
17
  end
@@ -0,0 +1,20 @@
1
+ module Ldp
2
+ class Error < StandardError; end
3
+
4
+ class HttpError < RuntimeError; end
5
+ class BadRequest < HttpError; end # 400
6
+ class NotFound < HttpError; end # 404
7
+ class Conflict < HttpError; end # 409
8
+ class Gone < HttpError; end # 410
9
+ class EtagMismatch < HttpError; end # 412
10
+
11
+ class UnexpectedContentType < RuntimeError; end
12
+
13
+ class GraphDifferenceException < Ldp::Error
14
+ attr_reader :diff
15
+ def initialize message, diff
16
+ super(message)
17
+ @diff = diff
18
+ end
19
+ end
20
+ end
@@ -54,22 +54,19 @@ module Ldp
54
54
 
55
55
  def save
56
56
  Ldp.instrument 'save.orm.ldp', subject: subject_uri do
57
- @last_response = resource.save
58
- @last_response.success?
57
+ response = create_or_update
58
+
59
+ response.success?
59
60
  end
60
- rescue Ldp::HttpError => e
61
- @last_response = e
62
- logger.debug e
61
+ rescue Ldp::HttpError
63
62
  false
64
63
  end
65
64
 
66
65
  def save!
67
- result = save
66
+ result = create_or_update
68
67
 
69
68
  if result.is_a? RDF::Enumerable
70
- raise GraphDifferenceException.new "", result
71
- elsif !result
72
- raise @last_response
69
+ raise Ldp::GraphDifferenceException, 'Graph failed to persist', result
73
70
  end
74
71
 
75
72
  result
@@ -81,26 +78,18 @@ module Ldp
81
78
  end
82
79
  end
83
80
 
84
- def method_missing meth, *args, &block
85
- super
86
- end
81
+ private
87
82
 
88
- def respond_to?(meth)
89
- super
83
+ def create_or_update
84
+ @last_response = resource.save
85
+ rescue Ldp::HttpError => e
86
+ @last_response = e
87
+ logger.debug e
88
+ raise e
90
89
  end
91
90
 
92
- private
93
-
94
91
  def logger
95
92
  Ldp.logger
96
93
  end
97
94
  end
98
-
99
- class GraphDifferenceException < Exception
100
- attr_reader :diff
101
- def initialize message, diff
102
- super(message)
103
- @diff = diff
104
- end
105
- end
106
95
  end
@@ -6,6 +6,17 @@ module Ldp
6
6
  attr_reader :client, :subject
7
7
  attr_accessor :content
8
8
 
9
+ def self.for(client, subject, response = nil)
10
+ case
11
+ when response.container?
12
+ Ldp::Container.for client, subject, response
13
+ when response.rdf_source?
14
+ Resource::RdfSource.new client, subject, response
15
+ else
16
+ Resource::BinarySource.new client, subject, response
17
+ end
18
+ end
19
+
9
20
  def initialize client, subject, response = nil, base_path = ''
10
21
  @client = client
11
22
  @subject = subject
@@ -67,10 +78,10 @@ module Ldp
67
78
  # Create a new resource at the URI
68
79
  # @return [RdfSource] the new representation
69
80
  def create &block
70
- raise "Can't call create on an existing resource" unless new?
81
+ raise Ldp::Error, "Can't call create on an existing resource" unless new?
71
82
  verb = subject.nil? ? :post : :put
72
83
  resp = client.send(verb, (subject || @base_path), content) do |req|
73
-
84
+ req.headers["Link"] = "<#{interaction_model}>;rel=\"type\"" if interaction_model
74
85
  yield req if block_given?
75
86
  end
76
87
 
@@ -103,14 +114,21 @@ module Ldp
103
114
  new_response.headers['Last-Modified'] == response.headers['Last-Modified']
104
115
  end
105
116
 
106
- def update_cached_get response
107
- Response.wrap(client, response)
117
+ def update_cached_get(response)
118
+ response = Response.new(response)
119
+
108
120
  if response.etag.nil? || response.last_modified.nil?
109
- response = Response.wrap(client, client.head(subject))
121
+ response = client.head(subject)
110
122
  end
111
123
  @get.etag = response.etag
112
124
  @get.last_modified = response.last_modified
113
125
  end
114
126
 
127
+ protected
128
+
129
+ def interaction_model
130
+ nil
131
+ end
132
+
115
133
  end
116
134
  end
@@ -17,7 +17,9 @@ module Ldp
17
17
  end
18
18
 
19
19
  def described_by
20
- client.find_or_initialize Array(Ldp::Response.links(self)["describedby"]).first
20
+ described_by = Array(head.links["describedby"]).first
21
+
22
+ client.find_or_initialize described_by if described_by
21
23
  end
22
24
 
23
25
  # Override inspect so that `content` is never shown. It is typically too big to be helpful
@@ -26,5 +28,11 @@ module Ldp
26
28
  fields = [:subject].map{|field| "#{field}=\"#{self.send(field)}\""}
27
29
  string << fields.join(", ") << ">"
28
30
  end
31
+
32
+ protected
33
+
34
+ def interaction_model
35
+ RDF::Vocab::LDP.NonRDFSource
36
+ end
29
37
  end
30
38
  end