faststep 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
data/README.markdown CHANGED
@@ -35,7 +35,7 @@ Have some fun!
35
35
  >> db["users"].find(:name => /0$/).to_a
36
36
  => [{"_id"=>BSON::ObjectId('4d83c53555ca381d572c1cf7'), "name"=>"Person 0"}, {"_id"=>BSON::ObjectId('4d83c53555ca381d572c1d01'), "name"=>"Person 10"}, ...]
37
37
  >> db["users"].remove(:name => /0$/)
38
- => nil
38
+ => true
39
39
  >> db["users"].count(:name => /0$/)
40
40
  => 0
41
41
  >> db["users"].count
@@ -47,13 +47,13 @@ Have some fun!
47
47
 
48
48
  ### Caveats
49
49
 
50
- This is under heavy development (what gem isn't?) but there's a lot of stuff to be implemented still. Some methods return nil (remove, for example) when they shouldn't.
50
+ This is under heavy development (what gem isn't?) but there's a lot of stuff to be implemented still.
51
51
  It's not nearly as smart as the mongo Ruby driver and it doesn't handle errors that well.
52
52
 
53
53
  ### Todo
54
54
 
55
55
  * Connection pooling
56
- * Safe mode
56
+ * Safe mode (per database or connection)
57
57
  * Master/slave
58
58
  * Replica sets
59
59
 
@@ -56,10 +56,19 @@ VALUE ensure_document_ok(const VALUE document) {
56
56
  }
57
57
 
58
58
  static char* _invalid_command_description(const VALUE document) {
59
- VALUE message = rb_str_new2("Invalid command (");
60
- rb_str_concat(message, rb_inspect(rb_hash_aref(document, rb_str_new2("bad cmd"))));
61
- rb_str_concat(message, rb_str_new2("): "));
62
- rb_str_concat(message, rb_hash_aref(document, rb_str_new2("errmsg")));
59
+ VALUE message = rb_str_new2("");
60
+
61
+ if(RTEST(rb_hash_aref(document, rb_str_new2("bad cmd")))) {
62
+ rb_str_concat(message, rb_str_new2("Invalid command ("));
63
+ rb_str_concat(message, rb_inspect(rb_hash_aref(document, rb_str_new2("bad cmd"))));
64
+ rb_str_concat(message, rb_str_new2("): "));
65
+ rb_str_concat(message, rb_hash_aref(document, rb_str_new2("errmsg")));
66
+ } else {
67
+ rb_str_concat(message, rb_str_new2("Error ("));
68
+ rb_str_concat(message, rb_inspect(rb_hash_aref(document, rb_str_new2("code"))));
69
+ rb_str_concat(message, rb_str_new2("): "));
70
+ rb_str_concat(message, rb_hash_aref(document, rb_str_new2("err")));
71
+ }
63
72
 
64
73
  return RSTRING_PTR(message);
65
74
  }
@@ -15,7 +15,7 @@ void faststep_collection_main() {
15
15
  rb_define_method(rb_cFaststepCollection, "find", faststep_collection_find, -1);
16
16
  rb_define_method(rb_cFaststepCollection, "find_one", faststep_collection_find_one, -1);
17
17
  rb_define_method(rb_cFaststepCollection, "count", faststep_collection_count, -1);
18
- rb_define_method(rb_cFaststepCollection, "insert", faststep_collection_insert, 1);
18
+ rb_define_method(rb_cFaststepCollection, "insert", faststep_collection_insert, -1);
19
19
  rb_define_method(rb_cFaststepCollection, "update", faststep_collection_update, -1);
20
20
  rb_define_method(rb_cFaststepCollection, "remove", faststep_collection_remove, -1);
21
21
  rb_define_method(rb_cFaststepCollection, "drop", faststep_collection_drop, 0);
@@ -103,9 +103,12 @@ void build_collection_ns(char* ns, const char* database, const char* collection)
103
103
  return;
104
104
  }
105
105
 
106
- static VALUE faststep_collection_insert(const VALUE self, const VALUE documents) {
106
+ static VALUE faststep_collection_insert(int argc, VALUE* argv, const VALUE self) {
107
107
  mongo_connection* conn = GetFaststepConnectionForCollection(self);
108
108
 
109
+ VALUE documents, options;
110
+ rb_scan_args(argc, argv, "11", &documents, &options);
111
+
109
112
  VALUE ns = faststep_collection_ns(self);
110
113
 
111
114
  if(TYPE(documents) == T_ARRAY) {
@@ -114,7 +117,7 @@ static VALUE faststep_collection_insert(const VALUE self, const VALUE documents)
114
117
  _faststep_collection_insert_one(conn, RSTRING_PTR(ns), documents);
115
118
  }
116
119
 
117
- return Qtrue;
120
+ return _faststep_safe_operation(self, options);
118
121
  }
119
122
 
120
123
  static VALUE faststep_collection_update(int argc, VALUE* argv, VALUE self) {
@@ -145,12 +148,12 @@ static VALUE faststep_collection_update(int argc, VALUE* argv, VALUE self) {
145
148
  bson_destroy(bson_query);
146
149
  bson_destroy(bson_operations);
147
150
 
148
- return Qtrue;
151
+ return _faststep_safe_operation(self, options);
149
152
  }
150
153
 
151
154
  static VALUE faststep_collection_remove(int argc, VALUE* argv, VALUE self) {
152
- VALUE query;
153
- rb_scan_args(argc, argv, "01", &query);
155
+ VALUE query, options;
156
+ rb_scan_args(argc, argv, "02", &query, &options);
154
157
 
155
158
  bson* bson_query = create_bson_from_ruby_hash(query);
156
159
 
@@ -158,7 +161,8 @@ static VALUE faststep_collection_remove(int argc, VALUE* argv, VALUE self) {
158
161
  RSTRING_PTR(faststep_collection_ns(self)),
159
162
  bson_query);
160
163
  bson_destroy(bson_query);
161
- return Qnil;
164
+
165
+ return _faststep_safe_operation(self, options);
162
166
  }
163
167
 
164
168
  static VALUE faststep_collection_drop(const VALUE self) {
@@ -244,3 +248,21 @@ mongo_connection* GetFaststepConnectionForCollection(const VALUE collection) {
244
248
 
245
249
  return GetFaststepConnection(connection);
246
250
  }
251
+
252
+ static VALUE _faststep_safe_operation(const VALUE self, const VALUE options) {
253
+ int safe_mode = 0;
254
+
255
+ if(TYPE(options) == T_HASH) {
256
+ if(rb_indiff_hash_aref(options, rb_str_new2("safe")) == Qtrue) {
257
+ safe_mode = 1;
258
+ }
259
+ }
260
+
261
+ if(safe_mode) {
262
+ VALUE document = rb_funcall(rb_iv_get(self, "@db"), rb_intern("get_last_error"), 0);
263
+ ensure_document_ok(document);
264
+ return document;
265
+ } else {
266
+ return Qtrue;
267
+ }
268
+ }
@@ -9,7 +9,7 @@ static VALUE faststep_collection_init(VALUE, const VALUE, const VALUE);
9
9
  static VALUE faststep_collection_find(int, VALUE*, const VALUE);
10
10
  static VALUE faststep_collection_find_one(int, VALUE*, const VALUE);
11
11
  static VALUE faststep_collection_count(int, VALUE*, VALUE);
12
- static VALUE faststep_collection_insert(const VALUE, const VALUE);
12
+ static VALUE faststep_collection_insert(int, VALUE*, const VALUE);
13
13
  static VALUE faststep_collection_update(int, VALUE*, const VALUE);
14
14
  static VALUE faststep_collection_remove(int, VALUE*, VALUE);
15
15
  static VALUE faststep_collection_drop(const VALUE);
@@ -20,6 +20,7 @@ static void _faststep_collection_insert_one(mongo_connection*, const char*, cons
20
20
  static void _faststep_collection_insert_batch(mongo_connection*, const char*, const VALUE);
21
21
  mongo_connection* GetFaststepConnectionForCollection(const VALUE);
22
22
  static void _faststep_collection_destroy(bson**, const int);
23
+ static VALUE _faststep_safe_operation(const VALUE, const VALUE);
23
24
 
24
25
  void build_collection_ns(char*, const char*, const char*);
25
26
  static char* _ivar_name(const VALUE);
@@ -8,13 +8,10 @@ void faststep_support_main() {
8
8
  }
9
9
 
10
10
  static VALUE faststep_support_ok(VALUE self, VALUE document) {
11
- VALUE ok_value = rb_hash_aref(document, rb_str_new2("ok"));
12
-
13
- bson_bool_t result = 0;
14
-
15
- switch(TYPE(ok_value)) {
16
- case T_FLOAT: result = FIX2INT(ok_value); break;
17
- case T_TRUE: result = 1; break;
11
+ bson_bool_t result = 1;
12
+ if(RTEST(rb_hash_aref(document, rb_str_new2("err"))) ||
13
+ RTEST(rb_hash_aref(document, rb_str_new2("errmsg")))) {
14
+ result = 0;
18
15
  }
19
16
 
20
17
  return bool_to_ruby(result);
@@ -1,3 +1,3 @@
1
1
  module Faststep
2
- VERSION = "0.0.4"
2
+ VERSION = "0.0.5"
3
3
  end
@@ -17,16 +17,6 @@ describe Faststep::Collection do
17
17
  db["something"].find_one(BSON::ObjectId.new).should be_nil
18
18
  end
19
19
 
20
- it "removes documents" do
21
- db["something"].insert(5.times.map { {:foo => "bar", :something => "fun"} })
22
- db["something"].insert(:foo => "bar", :baz => "what!")
23
-
24
- db["something"].remove(:baz => "what!")
25
- db["something"].count.should == 5
26
- db["something"].remove
27
- db["something"].count.should be_zero
28
- end
29
-
30
20
  it "drops collections" do
31
21
  db["something"].insert(:foo => "bar")
32
22
  db["something"].drop
@@ -105,6 +95,20 @@ describe Faststep::Collection, "#insert" do
105
95
  db["another.thing"].count(:baz => "qux").should == 1
106
96
  end
107
97
 
98
+ it "inserts documents in safe mode" do
99
+ document_id = BSON::ObjectId.new
100
+ db["something"].insert({ :_id => document_id, :something => "great" }, { :safe => true })
101
+
102
+ expect {
103
+ db["something"].insert({ :_id => document_id, :something => "great" })
104
+ }.to_not raise_error
105
+
106
+ expect {
107
+ db["something"].insert({ :_id => document_id, :something => "great" },
108
+ { :safe => true })
109
+ }.to raise_error(Faststep::OperationFailure, /Error \(11000\): .*duplicate key error index/)
110
+ end
111
+
108
112
  it "supports batch inserting" do
109
113
  db["something"].insert([small_document] * document_count)
110
114
  db["something"].count("foo" => "bar").should == document_count
@@ -144,4 +148,33 @@ describe Faststep::Collection, "#update" do
144
148
  db["something"].count.should == 1
145
149
  db["something"].find_one["count"].should == 2
146
150
  end
151
+
152
+ it "updates documents in safe mode" do
153
+ expect {
154
+ db["something"].update({},
155
+ { "$set" => { "invalid." => 1 } },
156
+ { :safe => true })
157
+ }.to raise_error(Faststep::OperationFailure, /Error \(10149\): Invalid mod field name/)
158
+ end
159
+ end
160
+
161
+ describe Faststep::Collection, "#remove" do
162
+ let(:db) { $faststep_test_db }
163
+
164
+ before do
165
+ db["something"].insert(5.times.map { {:foo => "bar", :something => "fun"} })
166
+ db["something"].insert(:foo => "bar", :baz => "what!")
167
+
168
+ end
169
+
170
+ it "removes documents" do
171
+ db["something"].remove(:baz => "what!")
172
+ db["something"].count.should == 5
173
+ db["something"].remove
174
+ db["something"].count.should be_zero
175
+ end
176
+
177
+ it "removes documents in safe mode" do
178
+ db["something"].remove({}, { :safe => true })["n"].should == 6
179
+ end
147
180
  end
@@ -28,8 +28,7 @@ describe Faststep::Connection, "getting a database" do
28
28
  subject { Faststep::Connection.new }
29
29
 
30
30
  it "uses a database" do
31
- subject[$faststep_test_db.name]["something"].insert(:foo => "bar")
32
- $faststep_test_db["something"].count.should == 1
31
+ subject[$faststep_test_db.name].should be_a(Faststep::Db)
33
32
  end
34
33
  end
35
34
 
data/spec/db_spec.rb CHANGED
@@ -13,7 +13,10 @@ describe Faststep::Db do
13
13
 
14
14
  it "runs specific commands" do
15
15
  expect { subject.command(:dbstats => 1) }.to_not raise_error
16
- expect { subject.command(:totally_bogus => 1) }.to raise_error(Faststep::OperationFailure)
16
+ expect {
17
+ subject.command(:totally_bogus => 1)
18
+ }.to raise_error(Faststep::OperationFailure,
19
+ %{Invalid command ({"totally_bogus"=>1}): no such cmd: totally_bogus})
17
20
  end
18
21
 
19
22
  it "drops the database" do
data/spec/support_spec.rb CHANGED
@@ -1,14 +1,13 @@
1
1
  require "spec_helper"
2
2
 
3
3
  describe Faststep::Support, "ok?" do
4
- it "returns true when response is ok" do
4
+ it "returns true when no err or errmsg key is present" do
5
5
  Faststep::Support.ok?({ "ok" => true }).should be_true
6
6
  Faststep::Support.ok?({ "ok" => 1.0 }).should be_true
7
7
  end
8
8
 
9
9
  it "returns false when response is not ok" do
10
- Faststep::Support.ok?({ "ok" => false }).should be_false
11
- Faststep::Support.ok?({ "ok" => 0.0 }).should be_false
12
- Faststep::Support.ok?({ "ok" => nil }).should be_false
10
+ Faststep::Support.ok?({ "err" => "something broke" }).should be_false
11
+ Faststep::Support.ok?({ "errmsg" => "something else broke" }).should be_false
13
12
  end
14
13
  end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: faststep
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.0.4
5
+ version: 0.0.5
6
6
  platform: ruby
7
7
  authors:
8
8
  - Josh Clayton
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-04-18 00:00:00 -04:00
13
+ date: 2011-04-23 00:00:00 -04:00
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency