orientdb4r 0.2.0 → 0.2.1

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.
data/README.rdoc CHANGED
@@ -47,12 +47,19 @@ see Wiki page for more sample at https://github.com/veny/orientdb4r/wiki
47
47
  client.drop_class CLASS
48
48
  client.disconnect
49
49
 
50
+
50
51
  == INSTALL
51
52
 
52
53
  > sudo gem install orientdb4r
53
54
 
54
55
  * gem published on http://rubygems.org/gems/orientdb4r
55
56
 
57
+ === Important Upgrade Notice
58
+ 2012-06-19 [v0.2.1]: Client#create_class - parameter given to a block has new method 'link' to define a linked property
59
+ 2012-06-17 [v0.2.0]: Client#get_class raises Orientdb4r::NotFoundError instead of ArgumentError
60
+
61
+
62
+
56
63
  == FEATURES/PROBLEMS
57
64
 
58
65
  * Supports only REST API right now
@@ -63,6 +70,12 @@ Tested on
63
70
  * Ruby 1.9.3
64
71
  * OrientDB 1.0.0
65
72
 
73
+ == TESTS
74
+
75
+ rake test
76
+
77
+ Start an instance of OrientDB (on localhost with default port and 'admin/admin' account) before running.
78
+
66
79
  == AUTHOR
67
80
 
68
81
  * vaclav.sykora@gmail.com
@@ -94,6 +94,11 @@ module Orientdb4r
94
94
  def proxy.property(property, type, options={})
95
95
  self.target.send :create_property, self.context, property, type, options
96
96
  end
97
+ def proxy.link(property, type, linked_class, options={})
98
+ raise ArgumentError, "type has to be a linked-type, given=#{type}" unless type.to_s.start_with? 'link'
99
+ options[:linked_class] = linked_class
100
+ self.target.send :create_property, self.context, property, type, options
101
+ end
97
102
  yield proxy
98
103
  end
99
104
  end
@@ -128,13 +133,20 @@ module Orientdb4r
128
133
  raise ArgumentError, "property name is blank" if blank?(property)
129
134
  opt_pattern = {
130
135
  :mandatory => :optional , :notnull => :optional, :min => :optional, :max => :optional,
131
- :regexp => :optional, :custom => :optional
136
+ :regexp => :optional, :custom => :optional, :linked_class => :optional
132
137
  }
133
138
  verify_options(options, opt_pattern)
134
139
 
135
140
  cmd = "CREATE PROPERTY #{clazz}.#{property} #{type.to_s}"
141
+ # link?
142
+ if [:link, :linklist, :linkset, :linkmap].include? type.to_s.downcase.to_sym
143
+ raise ArgumentError, "defined linked-type, but not linked-class" unless options.include? :linked_class
144
+ cmd << " #{options[:linked_class]}"
145
+ end
136
146
  command cmd
137
147
 
148
+ # ALTER PROPERTY ...
149
+ options.delete :linked_class # it's not option for ALTER
138
150
  unless options.empty?
139
151
  options.each do |k,v|
140
152
  command "ALTER PROPERTY #{clazz}.#{property} #{k.to_s.upcase} #{v}"
@@ -142,6 +154,26 @@ module Orientdb4r
142
154
  end
143
155
  end
144
156
 
157
+
158
+ ###
159
+ # Creates links between two or more records of type Document.
160
+ # You need to create the class before.
161
+ # def create_link(clazz, options={})
162
+ # raise ArgumentError, "class name is blank" if blank?(clazz)
163
+ # opt_pattern = {
164
+ # :name => :optional, :type => :optional,
165
+ # :source_property => :mandatory, :destination_class => :mandatory, :destination_property => :mandatory
166
+ # }
167
+ # verify_options(options, opt_pattern)
168
+ #
169
+ # cmd = 'CREATE LINK '
170
+ # cmd << "#{options[:name]} " if options.include? :name
171
+ # cmd << "TYPE #{options[:type]} " if options.include? :type
172
+ # cmd << "FROM #{clazz}.#{options[:source_property]} TO #{options[:destination_class]}.#{options[:destination_property]}"
173
+ #puts cmd
174
+ # command cmd
175
+ # end
176
+
145
177
  # ----------------------------------------------------------------- DOCUMENT
146
178
 
147
179
  ###
@@ -178,7 +210,7 @@ module Orientdb4r
178
210
  ###
179
211
  # Asserts if the client is connected and raises an error if not.
180
212
  def assert_connected
181
- raise OrientdbError, "not connected" unless @connected
213
+ raise ConnectionError, 'not connected' unless @connected
182
214
  end
183
215
 
184
216
  ###
@@ -89,7 +89,7 @@ module Orientdb4r
89
89
  connect_info = process_response(response, :mode => :strict)
90
90
 
91
91
  classes = connect_info['classes'].select { |i| i['name'] == name }
92
- raise ArgumentError, "class not found, name=#{name}" unless 1 == classes.size
92
+ raise NotFoundError, "class not found, name=#{name}" unless 1 == classes.size
93
93
  decorate_classes_with_model(classes)
94
94
  clazz = classes[0]
95
95
  clazz.extend Orientdb4r::HashExtension
@@ -109,7 +109,7 @@ module Orientdb4r
109
109
  def query(sql) #:nodoc:
110
110
  raise ArgumentError, 'query is blank' if blank? sql
111
111
 
112
- response = @resource["query/#{@database}/sql/#{URI.escape(sql)}"].get
112
+ response = @resource["query/#{@database}/sql/#{CGI::escape(sql)}"].get
113
113
  rslt = process_response(response)
114
114
  rslt['result']
115
115
  end
@@ -119,7 +119,7 @@ module Orientdb4r
119
119
  raise ArgumentError, 'command is blank' if blank? sql
120
120
  begin
121
121
  #puts "REQ #{sql}"
122
- response = @resource["command/#{@database}/sql/#{URI.escape(sql)}"].post ''
122
+ response = @resource["command/#{@database}/sql/#{CGI::escape(sql)}"].post ''
123
123
  rslt = process_response(response)
124
124
  rslt
125
125
  #puts "RESP #{response.code}"
@@ -92,6 +92,12 @@ module Orientdb4r
92
92
  get_mandatory_attribute :notNull
93
93
  end
94
94
 
95
+ ###
96
+ # Gets linked class if the property is a link.
97
+ def linked_class
98
+ self['linkedClass']
99
+ end
100
+
95
101
  ###
96
102
  # Gets the minimal allowed value.
97
103
  def min
@@ -60,9 +60,27 @@ module Orientdb4r
60
60
  block.call
61
61
  end
62
62
 
63
- end
63
+ end # Proxy
64
+
65
+
66
+ class DataGenerator
67
+
68
+ def initialize
69
+ @worlds = IO.readlines('/usr/share/dict/words')
70
+ 0.upto(@worlds.size - 1) do |i|
71
+ word = @worlds[i]
72
+ word.strip!
73
+ idx = word.index("'")
74
+ word = word[0..(idx - 1)] unless idx.nil?
75
+ @worlds[i] = word
76
+ end
77
+ @worlds.uniq
78
+ Orientdb4r::logger.info "DataGenerator: #{@worlds.size} words"
79
+ end
80
+
81
+ end # DataGenerator
64
82
 
65
- end
83
+ end # Utils
66
84
 
67
85
 
68
86
  # TODO extend it to work with already defined methods ('before :foo, :baz' after method definition)
@@ -2,6 +2,7 @@ module Orientdb4r
2
2
 
3
3
  # Version history.
4
4
  VERSION_HISTORY = [
5
+ ['0.2.1', '2012-06-19', "Fixed linked property definition"],
5
6
  ['0.2.0', '2012-06-12', "Introduces document's CRUD operations"],
6
7
  ['0.1.2', '2012-06-10', 'Introduces new OClass module'],
7
8
  ['0.1.1', '2012-06-08', 'First working version (including unit tests) released at github.com'],
@@ -46,7 +46,7 @@ class TestDatabase < Test::Unit::TestCase
46
46
  @client.disconnect
47
47
  assert !@client.connected?
48
48
  # unable to query after disconnect
49
- assert_raise Orientdb4r::OrientdbError do @client.query 'SELECT FROM OUser'; end
49
+ assert_raise Orientdb4r::ConnectionError do @client.query 'SELECT FROM OUser'; end
50
50
  end
51
51
 
52
52
 
data/test/test_ddo.rb CHANGED
@@ -30,7 +30,7 @@ class TestDdo < Test::Unit::TestCase
30
30
  def test_get_class
31
31
  assert_nothing_thrown do ouser = @client.get_class 'OUser'; end
32
32
  # class does not exist
33
- assert_raise ArgumentError do @client.get_class 'OUserXXX'; end
33
+ assert_raise Orientdb4r::NotFoundError do @client.get_class 'OUserXXX'; end
34
34
 
35
35
  clazz = @client.get_class 'OUser'
36
36
  # test OClass
@@ -90,7 +90,7 @@ class TestDdo < Test::Unit::TestCase
90
90
  @client.create_class(super_clazz);
91
91
  @client.create_class(CLASS);
92
92
  assert_nothing_thrown do @client.drop_class(CLASS); end
93
- assert_raise ArgumentError do @client.get_class(CLASS); end # no info more
93
+ assert_raise Orientdb4r::NotFoundError do @client.get_class(CLASS); end # no info more
94
94
  # the class is not visible in class list delivered by connect
95
95
  rslt = @client.connect :database => DB, :user => 'admin', :password => 'admin'
96
96
  assert rslt['classes'].select { |i| i.name == CLASS }.empty?
@@ -110,10 +110,32 @@ class TestDdo < Test::Unit::TestCase
110
110
  @client.create_class(CLASS)
111
111
  assert_nothing_thrown do @client.create_property(CLASS, 'prop1', :integer); end
112
112
  clazz = @client.get_class(CLASS)
113
- assert_equal 'INTEGER', clazz.property(:prop1)['type']
113
+ assert_equal 'INTEGER', clazz.property(:prop1).type
114
+ assert_nil clazz.property(:prop1).linked_class
114
115
 
115
116
  # already exist
116
- # assert_raise Orientdb4r::OrientdbError do @client.create_property(CLASS, 'prop1', :integer); end
117
+ assert_raise Orientdb4r::OrientdbError do @client.create_property(CLASS, 'prop1', :integer); end
118
+ end
119
+
120
+
121
+ ###
122
+ # CREATE PROPERTY (linked-type)
123
+ def test_create_linkedtype
124
+ @client.create_class(CLASS)
125
+ assert_nothing_thrown do @client.create_property(CLASS, 'friends', :linkset, :linked_class => 'OUser'); end
126
+ clazz = @client.get_class(CLASS)
127
+ assert_equal 'LINKSET', clazz.property(:friends).type
128
+ assert_equal 'OUser', clazz.property(:friends).linked_class
129
+
130
+ # unknow linked-class
131
+ assert_raise Orientdb4r::OrientdbError do
132
+ @client.create_property(CLASS, 'friends2', :linkset, :linked_class => 'UnknownClass')
133
+ end
134
+
135
+ # already exist
136
+ assert_raise Orientdb4r::OrientdbError do
137
+ @client.create_property(CLASS, 'friends', :linkset, :linked_class => 'OUser');
138
+ end
117
139
  end
118
140
 
119
141
 
@@ -123,26 +145,37 @@ class TestDdo < Test::Unit::TestCase
123
145
  assert_nothing_thrown do
124
146
  @client.create_class(CLASS) do |c|
125
147
  c.property 'prop1', :integer
126
- c.property 'prop2', :string, :mandatory => true, :notnull => :true, :min => 1, :max => 99
148
+ c.property 'prop2', :string, :mandatory => true, :notnull => true, :min => 1, :max => 99
149
+ c.link 'user', :linkset, 'OUser', :mandatory => true
127
150
  end
128
151
  end
129
152
 
130
153
  clazz = @client.get_class(CLASS)
131
- assert_equal 2, clazz.properties.size
154
+ assert_equal 3, clazz.properties.size
132
155
 
133
156
  prop1 = clazz.property(:prop1)
134
- assert_equal 'INTEGER', prop1['type']
135
- assert !prop1['mandatory']
136
- assert !prop1['notNull']
137
- assert prop1['min'].nil?
138
- assert prop1['max'].nil?
157
+ assert_equal 'INTEGER', prop1.type
158
+ assert !prop1.mandatory
159
+ assert !prop1.not_null
160
+ assert_nil prop1.min
161
+ assert_nil prop1.max
162
+ assert_nil prop1.linked_class
139
163
 
140
164
  prop2 = clazz.property(:prop2)
141
- assert_equal 'STRING', prop2['type']
142
- assert prop2['mandatory']
143
- assert prop2['notNull']
144
- assert_equal '1', prop2['min']
145
- assert_equal '99', prop2['max']
165
+ assert_equal 'STRING', prop2.type
166
+ assert prop2.mandatory
167
+ assert prop2.not_null
168
+ assert_equal '1', prop2.min
169
+ assert_equal '99', prop2.max
170
+ assert_nil prop2.linked_class
171
+
172
+ user = clazz.property(:user)
173
+ assert_equal 'LINKSET', user.type
174
+ assert user.mandatory
175
+ assert !user.not_null
176
+ assert_nil user.min
177
+ assert_nil user.max
178
+ assert_equal 'OUser', user.linked_class
146
179
  end
147
180
 
148
181
  end
data/test/test_dmo.rb CHANGED
@@ -17,7 +17,9 @@ class TestDmo < Test::Unit::TestCase
17
17
  @client.create_class(CLASS) do |c|
18
18
  c.property 'prop1', :integer
19
19
  c.property 'prop2', :string, :mandatory => true, :notnull => :true, :min => 1, :max => 99
20
+ c.link 'friends', :linkset, 'OUser', :mandatory => true
20
21
  end
22
+ @admin = @client.query("SELECT FROM OUser WHERE name = 'admin'")[0]
21
23
  end
22
24
 
23
25
  def teardown
@@ -29,14 +31,25 @@ class TestDmo < Test::Unit::TestCase
29
31
 
30
32
  ###
31
33
  # INSERT INTO
32
- def test_insert
34
+ def xtest_insert
33
35
  assert_nothing_thrown do
34
36
  1.upto(10) do |i|
35
- @client.command "INSERT INTO #{CLASS} (prop1, prop2) VALUES (#{i}, '#{random_string}')"
37
+ @client.command "INSERT INTO #{CLASS} (prop1, prop2, friends) VALUES (#{i}, '#{random_string}', [#{@admin['@rid']}])"
36
38
  end
37
39
  end
38
40
 
39
- assert_equal 10, @client.query("SELECT count(*) FROM #{CLASS}")[0]['count'].to_i
41
+ entries = @client.query("SELECT FROM #{CLASS}")
42
+ assert_equal 10, entries.size
43
+ assert_equal 10, entries.select { |e| e if e['prop1'] <= 10 }.size
44
+ assert_equal 10, entries.select { |e| e if e['friends'].size == 1 }.size
45
+
46
+ # insert more users into LINKSET
47
+ urids = @client.query('SELECT FROM OUser').collect { |u| u['@rid'] }
48
+ assert_nothing_thrown do
49
+ @client.command "INSERT INTO #{CLASS} (prop1, prop2, friends) VALUES (1, 'linkset', [#{urids.join(',')}])"
50
+ end
51
+ assert_equal urids.size, @client.query("SELECT FROM #{CLASS} WHERE prop2 = 'linkset'")[0]['friends'].size
52
+
40
53
  end
41
54
 
42
55
 
@@ -44,10 +57,19 @@ class TestDmo < Test::Unit::TestCase
44
57
  # SELECT
45
58
  def test_query
46
59
  1.upto(10) do |i|
47
- @client.command "INSERT INTO #{CLASS} (prop1, prop2) VALUES (#{i}, 'string#{i}')"
60
+ @client.command "INSERT INTO #{CLASS} (prop1, prop2, friends) VALUES (#{i}, 'string#{i}', [#{@admin['@rid']}])"
48
61
  end
49
62
 
50
- puts @client.query("SELECT FROM #{CLASS}")
63
+ assert_equal 10, @client.query("SELECT FROM #{CLASS}").size
64
+ assert_equal 1, @client.query("SELECT FROM #{CLASS} WHERE prop1 = 1").size
65
+ assert_equal 0, @client.query("SELECT FROM #{CLASS} WHERE prop1 = 11").size
66
+ # graph
67
+ rid = @client.query("SELECT FROM #{CLASS} WHERE prop1 = 1")[0]['@rid']
68
+ gr = @client.query("SELECT FROM (TRAVERSE * FROM #{rid})")
69
+ assert_equal 3, gr.size # # entries: testing, OUser, ORole
70
+ assert_equal 1, gr.select { |e| e if e['@class'] == CLASS }.size
71
+ assert_equal 1, gr.select { |e| e if e['@class'] == 'OUser' }.size
72
+ assert_equal 1, gr.select { |e| e if e['@class'] == 'ORole' }.size
51
73
  end
52
74
 
53
75
  end
@@ -2,7 +2,7 @@ require 'test/unit'
2
2
  require 'orientdb4r'
3
3
 
4
4
  ###
5
- # This class tests Data Manipulation Operarions.
5
+ # This class tests CRUD operarions on document.
6
6
  class TestDocumentCrud < Test::Unit::TestCase
7
7
  include Orientdb4r::Utils
8
8
 
@@ -127,8 +127,8 @@ class TestDocumentCrud < Test::Unit::TestCase
127
127
  doc = @client.get_document rid
128
128
  assert_not_nil doc
129
129
 
130
+ assert_nothing_thrown do @client.delete_document rid; end
130
131
  # already deleted
131
- @client.delete_document rid
132
132
  assert_raise Orientdb4r::NotFoundError do @client.get_document rid; end
133
133
  end
134
134
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: orientdb4r
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-06-12 00:00:00.000000000 Z
12
+ date: 2012-06-19 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rest-client