redlander 0.6.1 → 0.6.2

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: 404c236f798d03be422ed5dfdec8d8973d078bce
4
- data.tar.gz: 9c03079988a15a3e7d0ac629f40200a0601c25f3
3
+ metadata.gz: 1adddb051e9cc3f1aeda6b6eaa46012b87647506
4
+ data.tar.gz: 0cf0890720062fbc51b5123d27837aeb0ce86d3c
5
5
  SHA512:
6
- metadata.gz: 4c124c2143a8be75a94744e8f235749d9da5b94dc3da9fdc2cfdeb3031bc80091c7cb8b4d89ae6cb541b81360c13177ece23105142543734a7ed380f9a97317c
7
- data.tar.gz: 51abbecbb0071b5014c004d0ea807b0a2a0a22f8ff94e6f87f4f67ec0e2e33be8b320dbbfb340c1f26f9ae64ccb4a00b863e2fb94f7167319cf5fc37369cb592
6
+ metadata.gz: 3a0e2236aa7a13cb3d71c97b12d43d4079e41cbf9472731b26bc18e22f178970acb340c417f91c3c0e0fe8a0796e2ed6aa14f92c90d9aa0f7f7ebeb3424807be
7
+ data.tar.gz: d5cb579ca3f38910c6346f7706c0ddd296695c22626559c323445b445fef5e75060095b0d36c120062e62970c7c8befa7fbd76fd41e6f2e60007055202450561
data/ChangeLog CHANGED
@@ -1,3 +1,7 @@
1
+ redlander (0.6.2)
2
+ * fixed a few memory (double-freeing) issues
3
+ * memoizing the accessors for Statement, Node and Uri
4
+
1
5
  redlander (0.6.1)
2
6
  * librdf_query_set_offset from low-level API is now available
3
7
 
data/README.md CHANGED
@@ -5,6 +5,7 @@ which is used to manipulate RDF graphs. This is an alternative implementation
5
5
  of Ruby bindings (as opposed to the official bindings), aiming to be more
6
6
  intuitive, lightweight, high-performing and as bug-free as possible.
7
7
 
8
+
8
9
  # Installing
9
10
 
10
11
  Installing Redlander is simple:
@@ -13,6 +14,7 @@ Installing Redlander is simple:
13
14
 
14
15
  Note, that you will have to install Redland runtime library (librdf) for Redlander to work.
15
16
 
17
+
16
18
  # Usage
17
19
 
18
20
  This README outlines most obvious use cases.
@@ -29,6 +31,7 @@ for the list of available options.
29
31
  Naturally, you don't need to create a model if you just want to play around
30
32
  with independent statements, nodes and the like.
31
33
 
34
+
32
35
  ## RDF Statements
33
36
 
34
37
  Now that you have created a model, you can access its RDF statements:
@@ -52,7 +55,8 @@ The API is almost identical to [ActiveRecord](https://github.com/rails/rails/tre
52
55
 
53
56
  $ m.statements.each { |st| puts st }
54
57
 
55
- Finding statements:
58
+
59
+ ### Finding and enumerating statements
56
60
 
57
61
  $ m.statements.find(:first, :object => "subject!")
58
62
  $ m.statements.all(:object => "another label")
@@ -60,7 +64,20 @@ Finding statements:
60
64
  puts statement.subject
61
65
  }
62
66
 
63
- Note that `m.statements.each` is "lazy", while `m.statements.all` (and other finders) is not.
67
+ Note that `m.statements.each` does not have to pull and instantiate all statements in one call,
68
+ while `m.statements.all` (and other finders) can potentially create huge arrays of data
69
+ before you can handle individual statements of it.
70
+
71
+ For those interested in laziness, `m.statements` has `lazy` method which works exactly as users of
72
+ Ruby 2+ would expect:
73
+
74
+ $ m.statements.lazy.each {|s| puts s.object }
75
+
76
+ This, and other similar features are inherited by `m.statements` (which is actually an instance of
77
+ `Redlander::ModelProxy`) from `Enumerable` module.
78
+
79
+
80
+ ### Accessing and querying subject, predicate and object
64
81
 
65
82
  You can access the subject, predicate or object of a statement:
66
83
 
@@ -82,6 +99,7 @@ hash for *SELECT* queries. Binding hash values are instances of `Redlander::Node
82
99
 
83
100
  For query options and available query languages refer to `Model#query` documentation.
84
101
 
102
+
85
103
  ### Localized string literals
86
104
 
87
105
  Localized string literals are instantiated as LocalizedString objects.
@@ -191,6 +209,7 @@ SPARQL DESCRIBE is not implemented in librdf.
191
209
  # Authors and Contributors
192
210
 
193
211
  [Slava Kravchenko](https://github.com/cordawyn)
212
+ [Anthony Bargnesi](https://github.com/abargnesi)
194
213
 
195
214
 
196
215
  # Thanks
@@ -12,17 +12,19 @@ require 'redlander/statement'
12
12
  # Main Redlander namespace
13
13
  module Redlander
14
14
  class << self
15
+
15
16
  # @api private
16
17
  def rdf_world
17
18
  unless @rdf_world
18
19
  @rdf_world = Redland.librdf_new_world
19
20
  raise RedlandError, "Could not create a new RDF world" if @rdf_world.null?
20
- ObjectSpace.define_finalizer(self, proc { Redland.librdf_free_world(@rdf_world) })
21
+ ObjectSpace.define_finalizer(self, finalize_world(@rdf_world))
21
22
  Redland.librdf_world_open(@rdf_world)
22
23
  end
23
24
  @rdf_world
24
25
  end
25
26
 
27
+
26
28
  # @api private
27
29
  # Convert options hash into a string for librdf.
28
30
  # What it does:
@@ -44,5 +46,13 @@ module Redlander
44
46
  opts << "#{key}='#{value}'"
45
47
  }.join(',')
46
48
  end
49
+
50
+
51
+ private
52
+
53
+ # @api private
54
+ def finalize_world(rdf_world_ptr)
55
+ proc { Redland.librdf_free_world(rdf_world_ptr) }
56
+ end
47
57
  end
48
58
  end
@@ -12,6 +12,19 @@ module Redlander
12
12
  # @api private
13
13
  attr_reader :rdf_model
14
14
 
15
+ class << self
16
+ private
17
+
18
+ # @api private
19
+ def finalize_storage(rdf_storage_ptr)
20
+ proc { Redland.librdf_free_storage(rdf_storage_ptr) }
21
+ end
22
+
23
+ def finalize_model(rdf_model_ptr)
24
+ proc { Redland.librdf_free_model(rdf_model_ptr) }
25
+ end
26
+ end
27
+
15
28
  # Create a new RDF model.
16
29
  # (For available storage options see http://librdf.org/docs/api/redland-storage-modules.html)
17
30
  #
@@ -50,11 +63,12 @@ module Redlander
50
63
  storage_name.to_s,
51
64
  Redlander.to_rdf_options(options))
52
65
  raise RedlandError, "Failed to initialize '#{storage_name}' storage (type: #{storage_type})" if @rdf_storage.null?
53
- ObjectSpace.define_finalizer(self, proc { Redland.librdf_free_storage(@rdf_storage) })
66
+ ObjectSpace.define_finalizer(self, self.class.send(:finalize_storage, @rdf_storage))
54
67
 
55
68
  @rdf_model = Redland.librdf_new_model(Redlander.rdf_world, @rdf_storage, "")
56
69
  raise RedlandError, "Failed to create a new model" if @rdf_model.null?
57
- ObjectSpace.define_finalizer(self, proc { Redland.librdf_free_model(@rdf_model) })
70
+
71
+ ObjectSpace.define_finalizer(self, self.class.send(:finalize_model, @rdf_model))
58
72
  end
59
73
 
60
74
  # Statements contained in the model.
@@ -1,11 +1,50 @@
1
1
  module Redlander
2
2
  # RDF node (usually, a part of an RDF statement)
3
3
  class Node
4
+ class << self
5
+ private
6
+
7
+ # @api private
8
+ def finalize_node(rdf_node_ptr)
9
+ proc { Redland.librdf_free_node(rdf_node_ptr) }
10
+ end
11
+ end
12
+
4
13
  # @api private
5
- attr_reader :rdf_node
14
+ def rdf_node
15
+ unless instance_variable_defined?(:@rdf_node)
16
+ @rdf_node = case @arg
17
+ when FFI::Pointer
18
+ @arg
19
+ when NilClass
20
+ Redland.librdf_new_node_from_blank_identifier(Redlander.rdf_world, @options[:blank_id])
21
+ when URI
22
+ Redland.librdf_new_node_from_uri_string(Redlander.rdf_world, @arg.to_s)
23
+ else
24
+ value = @arg.respond_to?(:xmlschema) ? @arg.xmlschema : @arg.to_s
25
+ lang = @arg.respond_to?(:lang) ? @arg.lang.to_s : nil
26
+ dt = lang ? nil : Uri.new(XmlSchema.datatype_of(@arg)).rdf_uri
27
+ Redland.librdf_new_node_from_typed_literal(Redlander.rdf_world, value, lang, dt)
28
+ end
29
+ raise RedlandError, "Failed to create a new node" if @rdf_node.null?
30
+ ObjectSpace.define_finalizer(self, self.class.send(:finalize_node, @rdf_node))
31
+ end
32
+ @rdf_node
33
+ end
6
34
 
7
35
  # Datatype URI for the literal node, or nil
8
- attr_reader :datatype
36
+ def datatype
37
+ if instance_variable_defined?(:@datatype)
38
+ @datatype
39
+ else
40
+ @datatype = if literal?
41
+ rdf_uri = Redland.librdf_node_get_literal_value_datatype_uri(rdf_node)
42
+ rdf_uri.null? ? XmlSchema.datatype_of("") : URI.parse(Redland.librdf_uri_to_string(rdf_uri))
43
+ else
44
+ nil
45
+ end
46
+ end
47
+ end
9
48
 
10
49
  # Create a RDF node.
11
50
  #
@@ -19,47 +58,31 @@ module Redlander
19
58
  # @option options [String] :blank_id optional ID to use for a blank node.
20
59
  # @raise [RedlandError] if it fails to create a node from the given args.
21
60
  def initialize(arg = nil, options = {})
22
- @rdf_node = case arg
23
- when FFI::Pointer
24
- unless Redland.librdf_node_is_literal(arg).zero?
25
- rdf_uri = Redland.librdf_node_get_literal_value_datatype_uri(arg)
26
- @datatype = rdf_uri.null? ? XmlSchema.datatype_of("") : URI(Redland.librdf_uri_to_string(rdf_uri))
27
- end
28
- wrap(arg)
29
- when NilClass
30
- Redland.librdf_new_node_from_blank_identifier(Redlander.rdf_world, options[:blank_id])
31
- when URI
32
- Redland.librdf_new_node_from_uri_string(Redlander.rdf_world, arg.to_s)
33
- else
34
- @datatype = XmlSchema.datatype_of(arg)
35
- value = arg.respond_to?(:xmlschema) ? arg.xmlschema : arg.to_s
36
- lang = arg.respond_to?(:lang) ? arg.lang.to_s : nil
37
- dt = lang ? nil : Uri.new(@datatype).rdf_uri
38
- Redland.librdf_new_node_from_typed_literal(Redlander.rdf_world, value, lang, dt)
39
- end
40
- raise RedlandError, "Failed to create a new node" if @rdf_node.null?
41
- ObjectSpace.define_finalizer(self, proc { Redland.librdf_free_node(@rdf_node) })
61
+ # If FFI::Pointer is passed, wrap it instantly,
62
+ # because it can be freed outside before it is used here.
63
+ @arg = arg.is_a?(FFI::Pointer) ? wrap(arg) : arg
64
+ @options = options
42
65
  end
43
66
 
44
67
  # Check whether the node is a resource (identified by a URI)
45
68
  #
46
69
  # @return [Boolean]
47
70
  def resource?
48
- Redland.librdf_node_is_resource(@rdf_node) != 0
71
+ Redland.librdf_node_is_resource(rdf_node) != 0
49
72
  end
50
73
 
51
74
  # Return true if node is a literal.
52
75
  #
53
76
  # @return [Boolean]
54
77
  def literal?
55
- Redland.librdf_node_is_literal(@rdf_node) != 0
78
+ Redland.librdf_node_is_literal(rdf_node) != 0
56
79
  end
57
80
 
58
81
  # Return true if node is a blank node.
59
82
  #
60
83
  # @return [Boolean]
61
84
  def blank?
62
- Redland.librdf_node_is_blank(@rdf_node) != 0
85
+ Redland.librdf_node_is_blank(rdf_node) != 0
63
86
  end
64
87
 
65
88
  # Equivalency. Only works for comparing two Nodes.
@@ -67,7 +90,7 @@ module Redlander
67
90
  # @param [Node] other_node Node to be compared with.
68
91
  # @return [Boolean]
69
92
  def eql?(other_node)
70
- Redland.librdf_node_equals(@rdf_node, other_node.rdf_node) != 0
93
+ Redland.librdf_node_equals(rdf_node, other_node.rdf_node) != 0
71
94
  end
72
95
  alias_method :==, :eql?
73
96
 
@@ -79,7 +102,7 @@ module Redlander
79
102
  #
80
103
  # @return [String]
81
104
  def to_s
82
- Redland.librdf_node_to_string(@rdf_node)
105
+ Redland.librdf_node_to_string(rdf_node)
83
106
  end
84
107
 
85
108
  # Internal URI of the Node.
@@ -90,7 +113,7 @@ module Redlander
90
113
  # @return [URI, nil]
91
114
  def uri
92
115
  if resource?
93
- URI(to_s[1..-2])
116
+ URI.parse(to_s[1..-2])
94
117
  elsif literal?
95
118
  datatype
96
119
  else
@@ -108,20 +131,19 @@ module Redlander
108
131
  if resource?
109
132
  uri
110
133
  elsif blank?
111
- Redland.librdf_node_get_blank_identifier(@rdf_node).force_encoding("UTF-8")
134
+ Redland.librdf_node_get_blank_identifier(rdf_node).force_encoding("UTF-8")
112
135
  else
113
- v = Redland.librdf_node_get_literal_value(@rdf_node).force_encoding("UTF-8")
136
+ v = Redland.librdf_node_get_literal_value(rdf_node).force_encoding("UTF-8")
114
137
  v << "@#{lang}" if lang
115
- XmlSchema.instantiate(v, @datatype)
138
+ XmlSchema.instantiate(v, datatype)
116
139
  end
117
140
  end
118
141
 
119
142
  def lang
120
- lng = Redland.librdf_node_get_literal_value_language(@rdf_node)
143
+ lng = Redland.librdf_node_get_literal_value_language(rdf_node)
121
144
  lng ? lng.to_sym : nil
122
145
  end
123
146
 
124
-
125
147
  private
126
148
 
127
149
  # @api private
@@ -4,6 +4,15 @@ module Redlander
4
4
  class Results
5
5
  include Enumerable
6
6
 
7
+ class << self
8
+ private
9
+
10
+ # @api private
11
+ def finalize_query(rdf_query_ptr)
12
+ proc { Redland.librdf_free_query(rdf_query_ptr) }
13
+ end
14
+ end
15
+
7
16
  # (see Model#query)
8
17
  def initialize(q, options = {})
9
18
  language = options[:language] || "sparql10"
@@ -13,7 +22,7 @@ module Redlander
13
22
  @rdf_query = Redland.librdf_new_query(Redlander.rdf_world, language, language_uri, q, base_uri)
14
23
  raise RedlandError, "Failed to create a #{language.upcase} query from '#{q}'" if @rdf_query.null?
15
24
 
16
- ObjectSpace.define_finalizer(self, proc { Redland.librdf_free_query(@rdf_query) })
25
+ ObjectSpace.define_finalizer(self, self.class.send(:finalize_query, @rdf_query))
17
26
  end
18
27
 
19
28
  def process(model)
@@ -76,6 +85,7 @@ module Redlander
76
85
  !Redland.librdf_query_results_is_syntax(@rdf_results).zero?
77
86
  end
78
87
 
88
+
79
89
  private
80
90
 
81
91
  def process_bindings
@@ -1,8 +1,35 @@
1
1
  module Redlander
2
2
  # RDF statement
3
3
  class Statement
4
+ class << self
5
+ private
6
+
7
+ # @api private
8
+ def finalize_statement(rdf_statement_ptr)
9
+ proc { Redland.librdf_free_statement(rdf_statement_ptr) }
10
+ end
11
+ end
12
+
4
13
  # @api private
5
- attr_reader :rdf_statement
14
+ def rdf_statement
15
+ unless instance_variable_defined?(:@rdf_statement)
16
+ @rdf_statement = case @source
17
+ when FFI::Pointer
18
+ @source
19
+ when Hash
20
+ # Create a new statement from nodes
21
+ s = rdf_node_from(@source[:subject])
22
+ p = rdf_node_from(@source[:predicate])
23
+ o = rdf_node_from(@source[:object])
24
+ Redland.librdf_new_statement_from_nodes(Redlander.rdf_world, s, p, o)
25
+ else
26
+ raise NotImplementedError, "Cannot create Statement from '#{@source.inspect}'"
27
+ end
28
+ raise RedlandError, "Failed to create a new statement" if @rdf_statement.null?
29
+ ObjectSpace.define_finalizer(self, self.class.send(:finalize_statement, @rdf_statement))
30
+ end
31
+ @rdf_statement
32
+ end
6
33
 
7
34
  # Create an RDF statement.
8
35
  #
@@ -13,44 +40,45 @@ module Redlander
13
40
  # @raise [NotImplementedError] if cannot create a Statement from the given source.
14
41
  # @raise [RedlandError] if it fails to create a Statement.
15
42
  def initialize(source = {})
16
- @rdf_statement = case source
17
- when FFI::Pointer
18
- wrap(source)
19
- when Hash
20
- # Create a new statement from nodes
21
- s = rdf_node_from(source[:subject])
22
- p = rdf_node_from(source[:predicate])
23
- o = rdf_node_from(source[:object])
24
- Redland.librdf_new_statement_from_nodes(Redlander.rdf_world, s, p, o)
25
- else
26
- raise NotImplementedError, "Cannot create Statement from '#{source.inspect}'"
27
- end
28
- raise RedlandError, "Failed to create a new statement" if @rdf_statement.null?
29
- ObjectSpace.define_finalizer(self, proc { Redland.librdf_free_statement(@rdf_statement) })
43
+ # If FFI::Pointer is passed, wrap it instantly,
44
+ # because it can be freed outside before it is used here.
45
+ @source = source.is_a?(FFI::Pointer) ? wrap(source) : source
30
46
  end
31
47
 
32
48
  # Subject of the statment.
33
49
  #
34
50
  # @return [Node, nil]
35
51
  def subject
36
- rdf_node = Redland.librdf_statement_get_subject(@rdf_statement)
37
- rdf_node.null? ? nil : Node.new(rdf_node)
52
+ if instance_variable_defined?(:@subject)
53
+ @subject
54
+ else
55
+ rdf_node = Redland.librdf_statement_get_subject(rdf_statement)
56
+ @subject = rdf_node.null? ? nil : Node.new(rdf_node)
57
+ end
38
58
  end
39
59
 
40
60
  # Predicate of the statement.
41
61
  #
42
62
  # @return [Node, nil]
43
63
  def predicate
44
- rdf_node = Redland.librdf_statement_get_predicate(@rdf_statement)
45
- rdf_node.null? ? nil : Node.new(rdf_node)
64
+ if instance_variable_defined?(:@predicate)
65
+ @predicate
66
+ else
67
+ rdf_node = Redland.librdf_statement_get_predicate(rdf_statement)
68
+ @predicate = rdf_node.null? ? nil : Node.new(rdf_node)
69
+ end
46
70
  end
47
71
 
48
72
  # Object of the statement.
49
73
  #
50
74
  # @return [Node, nil]
51
75
  def object
52
- rdf_node = Redland.librdf_statement_get_object(@rdf_statement)
53
- rdf_node.null? ? nil : Node.new(rdf_node)
76
+ if instance_variable_defined?(:@object)
77
+ @object
78
+ else
79
+ rdf_node = Redland.librdf_statement_get_object(rdf_statement)
80
+ @object = rdf_node.null? ? nil : Node.new(rdf_node)
81
+ end
54
82
  end
55
83
 
56
84
  # Set the subject of the statement
@@ -58,7 +86,8 @@ module Redlander
58
86
  # @param [Node, nil] node
59
87
  # @return [void]
60
88
  def subject=(node)
61
- Redland.librdf_statement_set_subject(@rdf_statement, rdf_node_from(node))
89
+ Redland.librdf_statement_set_subject(rdf_statement, rdf_node_from(node))
90
+ @subject = node
62
91
  end
63
92
 
64
93
  # Set the predicate of the statement
@@ -66,7 +95,8 @@ module Redlander
66
95
  # @param [Node, nil] node
67
96
  # @return [void]
68
97
  def predicate=(node)
69
- Redland.librdf_statement_set_predicate(@rdf_statement, rdf_node_from(node))
98
+ Redland.librdf_statement_set_predicate(rdf_statement, rdf_node_from(node))
99
+ @predicate = node
70
100
  end
71
101
 
72
102
  # Set the object of the statement
@@ -74,7 +104,8 @@ module Redlander
74
104
  # @param [Node, nil] node
75
105
  # @return [void]
76
106
  def object=(node)
77
- Redland.librdf_statement_set_object(@rdf_statement, rdf_node_from(node))
107
+ Redland.librdf_statement_set_object(rdf_statement, rdf_node_from(node))
108
+ @object = node
78
109
  end
79
110
 
80
111
  def eql?(other_statement)
@@ -89,7 +120,7 @@ module Redlander
89
120
  end
90
121
 
91
122
  def to_s
92
- Redland.librdf_statement_to_string(@rdf_statement)
123
+ Redland.librdf_statement_to_string(rdf_statement)
93
124
  end
94
125
 
95
126
 
@@ -112,9 +143,9 @@ module Redlander
112
143
  when NilClass
113
144
  nil
114
145
  when Node
115
- source.rdf_node
146
+ Redland.librdf_new_node_from_node(source.rdf_node)
116
147
  else
117
- Node.new(source).rdf_node
148
+ Redland.librdf_new_node_from_node(Node.new(source).rdf_node)
118
149
  end
119
150
  end
120
151
  end
@@ -3,7 +3,30 @@ module Redlander
3
3
  # Uri (for internal use)
4
4
  class Uri
5
5
  # @api private
6
- attr_reader :rdf_uri
6
+ def rdf_uri
7
+ unless instance_variable_defined?(:@rdf_uri)
8
+ @rdf_uri = case @source
9
+ when FFI::Pointer
10
+ @source
11
+ when URI, String
12
+ Redland.librdf_new_uri(Redlander.rdf_world, @source.to_s)
13
+ else
14
+ raise NotImplementedError, "Cannot create Uri from '#{@source.inspect}'"
15
+ end
16
+ raise RedlandError, "Failed to create Uri from '#{@source.inspect}'" if @rdf_uri.null?
17
+ ObjectSpace.define_finalizer(self, self.class.send(:finalize_uri, @rdf_uri))
18
+ end
19
+ @rdf_uri
20
+ end
21
+
22
+ class << self
23
+ private
24
+
25
+ # @api private
26
+ def finalize_uri(rdf_uri_ptr)
27
+ proc { Redland.librdf_free_uri(rdf_uri_ptr) }
28
+ end
29
+ end
7
30
 
8
31
  # Create Redlander::Uri
9
32
  #
@@ -11,24 +34,15 @@ module Redlander
11
34
  # @raise [NotImplementedError] if cannot create a Uri from the given source.
12
35
  # @raise [RedlandError] if it fails to create a Uri.
13
36
  def initialize(source)
14
- @rdf_uri = case source
15
- when FFI::Pointer
16
- wrap(source)
17
- when URI, String
18
- Redland.librdf_new_uri(Redlander.rdf_world, source.to_s)
19
- else
20
- raise NotImplementedError, "Cannot create Uri from '#{source.inspect}'"
21
- end
22
- raise RedlandError, "Failed to create Uri from '#{source.inspect}'" if @rdf_uri.null?
23
- ObjectSpace.define_finalizer(self, proc { Redland.librdf_free_uri(@rdf_uri) })
37
+ @source = source.is_a?(FFI::Pointer) ? wrap(source) : source
24
38
  end
25
39
 
26
40
  def to_s
27
- Redland.librdf_uri_to_string(@rdf_uri)
41
+ Redland.librdf_uri_to_string(rdf_uri)
28
42
  end
29
43
 
30
44
  def eql?(other_uri)
31
- other_uri.is_a?(Uri) && (Redland.librdf_uri_equals(@rdf_uri, other_uri.rdf_uri) != 0)
45
+ other_uri.is_a?(Uri) && (Redland.librdf_uri_equals(rdf_uri, other_uri.rdf_uri) != 0)
32
46
  end
33
47
  alias_method :==, :eql?
34
48
 
@@ -1,4 +1,4 @@
1
1
  module Redlander
2
2
  # Redlander version number
3
- VERSION = "0.6.1"
3
+ VERSION = "0.6.2"
4
4
  end
@@ -0,0 +1,82 @@
1
+ require "spec_helper"
2
+
3
+ describe "garbage collection" do
4
+
5
+ describe Uri do
6
+ it "is garbage collected when destroyed" do
7
+ Uri.new("http://example.com/subject")
8
+ expect(ObjectSpace.each_object(Uri).count).to eq(1)
9
+ GC.start
10
+ expect(ObjectSpace.each_object(Uri).count).to eq(0)
11
+ end
12
+ end
13
+
14
+ describe Node do
15
+ it "is garbage collected when destroyed" do
16
+ Node.new(test_statement[:subject])
17
+ expect(ObjectSpace.each_object(Node).count).to eq(1)
18
+ GC.start
19
+ expect(ObjectSpace.each_object(Node).count).to eq(0)
20
+ end
21
+ end
22
+
23
+ describe Statement do
24
+ it "is garbage collected when destroyed" do
25
+ Statement.new(test_statement)
26
+ expect(ObjectSpace.each_object(Statement).count).to eq(1)
27
+ GC.start
28
+ expect(ObjectSpace.each_object(Statement).count).to eq(0)
29
+ end
30
+ end
31
+
32
+ describe Model do
33
+ it "is garbage collected when destroyed" do
34
+ Model.new
35
+ expect(ObjectSpace.each_object(Model).count).to eq(1)
36
+ GC.start
37
+ expect(ObjectSpace.each_object(Model).count).to eq(0)
38
+ end
39
+ end
40
+
41
+ describe Query::Results do
42
+ it "is garbage collected when destroyed" do
43
+ model = Model.new
44
+ model.statements.add(Statement.new(test_statement))
45
+ model.query("select * {?s ?p ?o}")
46
+ expect(ObjectSpace.each_object(Query::Results).count).to eq(1)
47
+ GC.start
48
+ expect(ObjectSpace.each_object(Query::Results).count).to eq(0)
49
+ end
50
+ end
51
+
52
+ it "collects all objects after using Model" do
53
+ model = Model.new
54
+ expect(ObjectSpace.each_object(Model).count).to eq(1)
55
+
56
+ model.statements.add(Statement.new(test_statement))
57
+ expect(ObjectSpace.each_object(Node).count).to eq(3)
58
+ expect(ObjectSpace.each_object(Statement).count).to eq(1)
59
+
60
+ model.query("select * {?s ?p ?o}")
61
+ expect(ObjectSpace.each_object(Node).count).to eq(6)
62
+ expect(ObjectSpace.each_object(Query::Results).count).to eq(1)
63
+
64
+ # allow model to be garbage collected
65
+ model = nil
66
+
67
+ GC.start
68
+ expect(ObjectSpace.each_object(Model).count).to eq(0)
69
+ expect(ObjectSpace.each_object(Statement).count).to eq(0)
70
+ expect(ObjectSpace.each_object(Query::Results).count).to eq(0)
71
+ end
72
+
73
+ private
74
+
75
+ def test_statement
76
+ {
77
+ :subject => URI.parse("http://example.com/subject"),
78
+ :predicate => URI.parse("http://example.com/predicate"),
79
+ :object => URI.parse("object!")
80
+ }
81
+ end
82
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: redlander
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.1
4
+ version: 0.6.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Slava Kravchenko
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-12-10 00:00:00.000000000 Z
11
+ date: 2014-08-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: xml_schema
@@ -84,6 +84,7 @@ files:
84
84
  - spec/fixtures/doap.nt
85
85
  - spec/fixtures/doap.rdf
86
86
  - spec/fixtures/doap.ttl
87
+ - spec/integration/finalizer_gc_spec.rb
87
88
  - spec/integration/memory_leak_spec.rb
88
89
  - spec/lib/redlander/model_spec.rb
89
90
  - spec/lib/redlander/node_spec.rb
@@ -118,6 +119,7 @@ test_files:
118
119
  - spec/fixtures/doap.nt
119
120
  - spec/fixtures/doap.rdf
120
121
  - spec/fixtures/doap.ttl
122
+ - spec/integration/finalizer_gc_spec.rb
121
123
  - spec/integration/memory_leak_spec.rb
122
124
  - spec/lib/redlander/model_spec.rb
123
125
  - spec/lib/redlander/node_spec.rb