yard doc updates; deprecated legacy objectid byte encoding support

This commit is contained in:
Kyle Banker 2010-01-13 13:11:09 -05:00
parent f9ec4eca1d
commit 5864e4c776
8 changed files with 105 additions and 50 deletions

View File

@ -56,7 +56,7 @@ That's all there is to it!
For extensive examples, see the MongoDB Ruby Tutorial For extensive examples, see the MongoDB Ruby Tutorial
(http://www.mongodb.org/display/DOCS/Ruby+Tutorial). (http://www.mongodb.org/display/DOCS/Ruby+Tutorial).
Bundled with the dirver are many examples in the "examples" subdirectory. Samples include using Bundled with the driver are many examples, located in the "examples" subdirectory. Samples include using
the driver and using the GridFS class GridStore. MongoDB must be running for the driver and using the GridFS class GridStore. MongoDB must be running for
these examples to work, of course. these examples to work, of course.
@ -90,7 +90,7 @@ Example code:
end end
# Output "Hello, world!" # Output "Hello, world!"
GridStore.open(database, 'filename, 'r') do |f| GridStore.open(database, 'filename', 'r') do |f|
puts f.read puts f.read
end end
@ -100,7 +100,7 @@ Example code:
end end
# Retrieve everything, outputting "Hello, world!\nBut wait, there's more!\n" # Retrieve everything, outputting "Hello, world!\nBut wait, there's more!\n"
GridStore.open(database, 'filename, 'r') do |f| GridStore.open(database, 'filename', 'r') do |f|
puts f.read puts f.read
end end
@ -128,7 +128,7 @@ A pooled connection to a paired instance would look like this:
:right => ["db2.example.com", 27017]}, nil, :right => ["db2.example.com", 27017]}, nil,
:pool_size => 20, :timeout => 5) :pool_size => 20, :timeout => 5)
Though the pooling architecure will undoubtedly evolve, it currently owes much credit Though the pooling architecture will undoubtedly evolve, it currently owes much credit
to the connection pooling implementations in ActiveRecord and PyMongo. to the connection pooling implementations in ActiveRecord and PyMongo.
== Using with Phusion Passenger == Using with Phusion Passenger
@ -191,8 +191,8 @@ hash and return a hash which merges the original hash with any primary key
fields the factory wishes to inject. fields the factory wishes to inject.
NOTE: if the object already has a primary key, the factory should not inject NOTE: if the object already has a primary key, the factory should not inject
a new key; this means that the object is being used in a repsert but it already a new key; this means that the object may already exist in the database.
exists. The idea here is that whenever a record is inserted, The idea here is that whenever a record is inserted,
the :pk_factory object's +create_pk+ method will be called and the :pk_factory object's +create_pk+ method will be called and
the new hash returned will be inserted. the new hash returned will be inserted.
@ -277,7 +277,7 @@ These will run both unit and functional tests. To run these tests alone:
$ rake test:unit $ rake test:unit
$ rake test:functional $ rake test:functional
To run any individual rake tasks with the C extenson enabled, just pass C_EXT=true to the task: To run any individual rake tasks with the C extension enabled, just pass C_EXT=true to the task:
$ rake test:unit C_EXT=true $ rake test:unit C_EXT=true
@ -327,9 +327,9 @@ validator script.
This documentation is available online at http://api.mongodb.org/ruby. You can This documentation is available online at http://api.mongodb.org/ruby. You can
generate the documentation if you have the source by typing generate the documentation if you have the source by typing
$ rake rdoc $ rake ydoc
Then open the file html/index.html. Then open the file +ydoc/index.html+.
= Release Notes = Release Notes

View File

@ -6,8 +6,8 @@
# The c-extension, mongo_ext, will be used if installed. # The c-extension, mongo_ext, will be used if installed.
require 'rubygems' require 'rubygems'
require 'benchmark'
require 'mongo' require 'mongo'
require 'benchmark'
include Mongo include Mongo

View File

@ -49,12 +49,6 @@ module Mongo
# The Mongo::Connection instance connecting to the MongoDB server. # The Mongo::Connection instance connecting to the MongoDB server.
attr_reader :connection attr_reader :connection
# An array of [host, port] pairs.
attr_reader :nodes
# The logger instance if :logger is passed to initialize.
attr_reader :logger
# Instances of DB are normally obtained by calling Mongo#db. # Instances of DB are normally obtained by calling Mongo#db.
# #
# @param [String] db_name the database name. # @param [String] db_name the database name.
@ -75,7 +69,7 @@ module Mongo
@pk_factory = options[:pk] @pk_factory = options[:pk]
end end
# Authenticates with the given username and password. Note that mongod # Authenticate with the given username and password. Note that mongod
# must be started with the --auth option for authentication to be enabled. # must be started with the --auth option for authentication to be enabled.
# #
# @param [String] username # @param [String] username
@ -130,7 +124,7 @@ module Mongo
# #
# @param [String] coll_name return info for the specifed collection only. # @param [String] coll_name return info for the specifed collection only.
# #
# @return [Mongo::Cursor<Hash>] # @return [Mongo::Cursor]
def collections_info(coll_name=nil) def collections_info(coll_name=nil)
selector = {} selector = {}
selector[:name] = full_collection_name(coll_name) if coll_name selector[:name] = full_collection_name(coll_name) if coll_name
@ -187,6 +181,8 @@ module Mongo
# @param [String] name the collection name. # @param [String] name the collection name.
# #
# @raise [MongoDBError] if collection does not already exist and we're in +strict+ mode. # @raise [MongoDBError] if collection does not already exist and we're in +strict+ mode.
#
# @return [Mongo::Collection]
def collection(name) def collection(name)
return Collection.new(self, name, @pk_factory) if !strict? || collection_names.include?(name) return Collection.new(self, name, @pk_factory) if !strict? || collection_names.include?(name)
raise MongoDBError, "Collection #{name} doesn't exist. Currently in strict mode." raise MongoDBError, "Collection #{name} doesn't exist. Currently in strict mode."
@ -205,9 +201,10 @@ module Mongo
end end
# Get the error message from the most recently executed database # Get the error message from the most recently executed database
# operation for this connection, or +nil+ if there was no error. # operation for this connection.
# #
# @return [String, Nil] # @return [String, Nil] either the text describing the error or nil if no
# error has occurred.
def error def error
doc = command(:getlasterror => 1) doc = command(:getlasterror => 1)
raise MongoDBError, "error retrieving last error: #{doc}" unless ok?(doc) raise MongoDBError, "error retrieving last error: #{doc}" unless ok?(doc)
@ -234,7 +231,7 @@ module Mongo
# This command only returns errors that have occured since the last call to # This command only returns errors that have occured since the last call to
# DB#reset_error_history - returns +nil+ if there is no such error. # DB#reset_error_history - returns +nil+ if there is no such error.
# #
# @return [String, Nil] # @return [String, Nil] the text of the error or +nil+ if no error has occurred.
def previous_error def previous_error
error = command(:getpreverror => 1) error = command(:getpreverror => 1)
if error["err"] if error["err"]
@ -281,6 +278,8 @@ module Mongo
# @param [String, Code] code a JavaScript expression to evaluate server-side. # @param [String, Code] code a JavaScript expression to evaluate server-side.
# @param [Integer, Hash] args any additional argument to be passed to the +code+ expression when # @param [Integer, Hash] args any additional argument to be passed to the +code+ expression when
# it's run on the server. # it's run on the server.
#
# @return [String] the return value of the function.
def eval(code, *args) def eval(code, *args)
if not code.is_a? Code if not code.is_a? Code
code = Code.new(code) code = Code.new(code)
@ -367,12 +366,14 @@ module Mongo
ok.kind_of?(Numeric) && ok.to_i == 1 ok.kind_of?(Numeric) && ok.to_i == 1
end end
# Send a command to the database. Note that a command has a formal definition in MongoDB: it's # Send a command to the database.
# a kind of overloaded query.
# #
# Note: DB commands must start with the "command" key. For this reason, # Note: DB commands must start with the "command" key. For this reason,
# any selector containing more than one key must be an OrderedHash. # any selector containing more than one key must be an OrderedHash.
# #
# It may be of interest hat a command in MongoDB is technically a kind of query
# that occurs on the system command collection ($cmd).
#
# @param [OrderedHash, Hash] selector an OrderedHash, or a standard Hash with just one # @param [OrderedHash, Hash] selector an OrderedHash, or a standard Hash with just one
# key, specifying the command to be performed. # key, specifying the command to be performed.
# #
@ -434,7 +435,8 @@ module Mongo
@pk_factory = pk_factory @pk_factory = pk_factory
end end
# Return the current database profiling level. # Return the current database profiling level. If profiling is enabled, you can
# get the results using DB#profiling_info.
# #
# @return [Symbol] :off, :slow_only, or :all # @return [Symbol] :off, :slow_only, or :all
def profiling_level def profiling_level
@ -454,7 +456,8 @@ module Mongo
end end
end end
# Set this database's profiling level. # Set this database's profiling level. If profiling is enabled, you can
# get the results using DB#profiling_info.
# #
# @param [Symbol] level acceptable options are +:off+, +:slow_only+, or +:all+. # @param [Symbol] level acceptable options are +:off+, +:slow_only+, or +:all+.
def profiling_level=(level) def profiling_level=(level)

View File

@ -33,7 +33,7 @@ module GridFS
# end # end
# #
# # Output "Hello, world!" # # Output "Hello, world!"
# GridStore.open(database, 'filename, 'r') do |f| # GridStore.open(database, 'filename', 'r') do |f|
# puts f.read # puts f.read
# end # end
# #
@ -43,7 +43,7 @@ module GridFS
# end # end
# #
# # Retrieve everything, outputting "Hello, world!\nBut wait, there's more!\n" # # Retrieve everything, outputting "Hello, world!\nBut wait, there's more!\n"
# GridStore.open(database, 'filename, 'r') do |f| # GridStore.open(database, 'filename', 'r') do |f|
# puts f.read # puts f.read
# end # end
class GridStore class GridStore

View File

@ -18,7 +18,10 @@ require 'mongo/util/byte_buffer'
module Mongo module Mongo
# An array of binary bytes with a Mongo subtype value. # An array of binary bytes with a MongoDB subtype. See the subtype
# constants for reference.
#
# Use this class when storing binary data in documents.
class Binary < ByteBuffer class Binary < ByteBuffer
SUBTYPE_BYTES = 0x02 SUBTYPE_BYTES = 0x02
@ -29,6 +32,13 @@ module Mongo
# One of the SUBTYPE_* constants. Default is SUBTYPE_BYTES. # One of the SUBTYPE_* constants. Default is SUBTYPE_BYTES.
attr_accessor :subtype attr_accessor :subtype
# Create a buffer for storing binary data in MongoDB.
#
# @param [Array] initia_data
# @param [Fixnum] one of four values specifying a BSON binary subtype. Possible values are
# SUBTYPE_BYTES, SUBTYPE_UUID, SUBTYPE_MD5, and SUBTYPE_USER_DEFINED.
#
# @see http://www.mongodb.org/display/DOCS/BSON#BSON-noteondatabinary BSON binary subtypes.
def initialize(initial_data=[], subtype=SUBTYPE_BYTES) def initialize(initial_data=[], subtype=SUBTYPE_BYTES)
super(initial_data) super(initial_data)
@subtype = subtype @subtype = subtype

View File

@ -16,12 +16,17 @@
module Mongo module Mongo
# JavaScript code to be evaluated by MongoDB # JavaScript code to be evaluated by MongoDB.
class Code < String class Code < String
# Hash mapping identifiers to their values # Hash mapping identifiers to their values
attr_accessor :scope attr_accessor :scope
# Wrap code to be evaluated by MongoDB.
#
# @param [String] code the JavaScript code.
# @param [Hash] a document mapping identifiers to values, which
# represent the scope in which the code is to be executed.
def initialize(code, scope={}) def initialize(code, scope={})
super(code) super(code)
@scope = scope @scope = scope

View File

@ -16,13 +16,18 @@
module Mongo module Mongo
# A reference to another object in a MongoDB database.
class DBRef class DBRef
attr_reader :namespace, :object_id attr_reader :namespace, :object_id
# Create a DBRef. Use this class in conjunction with DB#dereference.
#
# @param [String] a collection name
# @param [ObjectID] an object id
def initialize(namespace, object_id) def initialize(namespace, object_id)
@namespace, @object_id = @namespace = namespace
namespace, object_id @object_id = object_id
end end
def to_s def to_s

View File

@ -14,13 +14,13 @@
# limitations under the License. # limitations under the License.
# ++ # ++
require 'mutex_m' require 'thread'
require 'socket' require 'socket'
require 'digest/md5' require 'digest/md5'
module Mongo module Mongo
# Representation of an ObjectId for Mongo. # ObjectID class for documents in MongoDB.
class ObjectID class ObjectID
# This is the legacy byte ordering for Babble. Versions of the Ruby # This is the legacy byte ordering for Babble. Versions of the Ruby
# driver prior to 0.14 used this byte ordering when converting ObjectID # driver prior to 0.14 used this byte ordering when converting ObjectID
@ -30,11 +30,20 @@ module Mongo
# with ObjectID#legacy_string_convert # with ObjectID#legacy_string_convert
BYTE_ORDER = [7, 6, 5, 4, 3, 2, 1, 0, 11, 10, 9, 8] BYTE_ORDER = [7, 6, 5, 4, 3, 2, 1, 0, 11, 10, 9, 8]
LOCK = Object.new @@lock = Mutex.new
LOCK.extend Mutex_m
@@index = 0 @@index = 0
# Create a new object id. If no parameter is given, an id corresponding
# to the ObjectID BSON data type will be created. This is a 12-byte value
# consisting of a 4-byte timestamp, a 3-byte machine id, a 2-byte process id,
# and a 3-byte counter.
#
# @param [Array] data should be an array of bytes. If you want
# to generate a standard MongoDB object id, leave this argument blank.
def initialize(data=nil)
@data = data || generate
end
def self.legal?(str) def self.legal?(str)
len = BYTE_ORDER.length * 2 len = BYTE_ORDER.length * 2
str =~ /([0-9a-f]+)/i str =~ /([0-9a-f]+)/i
@ -43,32 +52,44 @@ module Mongo
end end
# Adds a primary key to the given document if needed. # Adds a primary key to the given document if needed.
#
# @param [Hash] doc a document requiring an _id.
#
# @return [Mongo::ObjectID, Object] returns a newly-created or
# current _id for the given document.
def self.create_pk(doc) def self.create_pk(doc)
doc.has_key?(:_id) || doc.has_key?('_id') ? doc : doc.merge!(:_id => self.new) doc.has_key?(:_id) || doc.has_key?('_id') ? doc : doc.merge!(:_id => self.new)
end end
# +data+ is an array of bytes. If nil, a new id will be generated. # Check equality of this object id with another.
def initialize(data=nil) #
@data = data || generate # @param [Mongo::ObjectID] object_id
end def eql?(object_id)
@data == object_id.instance_variable_get("@data")
def eql?(other)
@data == other.instance_variable_get("@data")
end end
alias_method :==, :eql? alias_method :==, :eql?
# Returns a unique hashcode for the object. # Get a unique hashcode for this object.
# This is required since we've defined an #eql? method. # This is required since we've defined an #eql? method.
#
# @return [Integer]
def hash def hash
@data.hash @data.hash
end end
# Get an array representation of the object id.
#
# @return [Array]
def to_a def to_a
@data.dup @data.dup
end end
# Given a string representation of an ObjectID, return a new ObjectID # Given a string representation of an ObjectID, return a new ObjectID
# with that value. # with that value.
#
# @param [String] str
#
# @return [Mongo::ObjectID]
def self.from_string(str) def self.from_string(str)
raise InvalidObjectID, "illegal ObjectID format" unless legal?(str) raise InvalidObjectID, "illegal ObjectID format" unless legal?(str)
data = [] data = []
@ -78,11 +99,13 @@ module Mongo
self.new(data) self.new(data)
end end
# @deprecated
# Create a new ObjectID given a string representation of an ObjectID # Create a new ObjectID given a string representation of an ObjectID
# using the legacy byte ordering. This method may eventually be # using the legacy byte ordering. This method may eventually be
# removed. If you are not sure that you need this method you should be # removed. If you are not sure that you need this method you should be
# using the regular from_string. # using the regular from_string.
def self.from_string_legacy(str) def self.from_string_legacy(str)
warn "Support for legacy object ids has been DEPRECATED."
raise InvalidObjectID, "illegal ObjectID format" unless legal?(str) raise InvalidObjectID, "illegal ObjectID format" unless legal?(str)
data = [] data = []
BYTE_ORDER.each_with_index { |string_position, data_index| BYTE_ORDER.each_with_index { |string_position, data_index|
@ -91,6 +114,9 @@ module Mongo
self.new(data) self.new(data)
end end
# Get a string representation of this object id.
#
# @return [String]
def to_s def to_s
str = ' ' * 24 str = ' ' * 24
12.times do |i| 12.times do |i|
@ -98,17 +124,18 @@ module Mongo
end end
str str
end end
alias_method :inspect, :to_s
def inspect; to_s; end
def to_json(*args) def to_json(*args)
%Q("#{to_s}") %Q("#{to_s}")
end end
# @deprecated
# Get a string representation of this ObjectID using the legacy byte # Get a string representation of this ObjectID using the legacy byte
# ordering. This method may eventually be removed. If you are not sure # ordering. This method may eventually be removed. If you are not sure
# that you need this method you should be using the regular to_s. # that you need this method you should be using the regular to_s.
def to_s_legacy def to_s_legacy
warn "Support for legacy object ids has been DEPRECATED."
str = ' ' * 24 str = ' ' * 24
BYTE_ORDER.each_with_index { |string_position, data_index| BYTE_ORDER.each_with_index { |string_position, data_index|
str[string_position * 2, 2] = '%02x' % @data[data_index] str[string_position * 2, 2] = '%02x' % @data[data_index]
@ -116,11 +143,13 @@ module Mongo
str str
end end
# @deprecated
# Convert a string representation of an ObjectID using the legacy byte # Convert a string representation of an ObjectID using the legacy byte
# ordering to the proper byte ordering. This method may eventually be # ordering to the proper byte ordering. This method may eventually be
# removed. If you are not sure that you need this method it is probably # removed. If you are not sure that you need this method it is probably
# unnecessary. # unnecessary.
def self.legacy_string_convert(str) def self.legacy_string_convert(str)
warn "Support for legacy object ids has been DEPRECATED."
legacy = ' ' * 24 legacy = ' ' * 24
BYTE_ORDER.each_with_index do |legacy_pos, pos| BYTE_ORDER.each_with_index do |legacy_pos, pos|
legacy[legacy_pos * 2, 2] = str[pos * 2, 2] legacy[legacy_pos * 2, 2] = str[pos * 2, 2]
@ -128,8 +157,11 @@ module Mongo
legacy legacy
end end
# Returns the utc time at which this ObjectID was generated. This may # Return the UTC time at which this ObjectID was generated. This may
# be used in lieu of a created_at timestamp. # be used in lieu of a created_at timestamp since this information
# is always encoded in the object id.
#
# @return [Time] the time at which this object was created.
def generation_time def generation_time
Time.at(@data.pack("C4").unpack("N")[0]) Time.at(@data.pack("C4").unpack("N")[0])
end end
@ -159,9 +191,9 @@ module Mongo
end end
def get_inc def get_inc
LOCK.mu_synchronize { @@lock.synchronize do
@@index = (@@index + 1) % 0xFFFFFF @@index = (@@index + 1) % 0xFFFFFF
} end
end end
end end
end end