redlander 0.6.1 → 0.6.2

Sign up to get free protection for your applications and to get access to all the features.
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