Skip to content

Commit

Permalink
Mongoid now raises an error when defining a field with a conflicting …
Browse files Browse the repository at this point in the history
…name on a document (Github: 69)
  • Loading branch information
durran committed Apr 19, 2010
1 parent 8ac8a00 commit faa5036
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 0 deletions.
19 changes: 19 additions & 0 deletions lib/mongoid/config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,25 @@ def slaves
@slaves
end

# Return field names that could cause destructive things to happen if
# defined in a Mongoid::Document
#
# Example:
#
# <tt>Config.destructive_fields</tt>
#
# Returns:
#
# An array of bad field names.
def destructive_fields
@destructive_fields ||= lambda {
klass = Class.new do
include Mongoid::Document
end
klass.instance_methods(true)
}.call
end

protected
def check_database!(database)
raise Errors::InvalidDatabase.new(database) unless database.kind_of?(Mongo::DB)
Expand Down
17 changes: 17 additions & 0 deletions lib/mongoid/errors.rb
Original file line number Diff line number Diff line change
Expand Up @@ -87,5 +87,22 @@ def message
end
end

# This error is raised when trying to create a field that conflicts with
# a Mongoid internal attribute or method.
#
# Example:
#
# <tt>InvalidField.new('collection')</tt>
class InvalidField < RuntimeError
def initialize(name)
@name = name
end
def message
"Defining a field named '#{@name}' is not allowed. " +
"Do not define fields that conflict with Mongoid internal attributes " +
"or method names. Use Document#instance_methods to see what " +
"names this includes."
end
end
end
end
6 changes: 6 additions & 0 deletions lib/mongoid/field.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ def default
#
# <tt>Field.new(:score, :default => 0)</tt>
def initialize(name, options = {})
check_name!(name)
@name, @default = name, options[:default]
@copyable = (@default.is_a?(Array) || @default.is_a?(Hash))
@type = options[:type] || String
Expand All @@ -55,5 +56,10 @@ def get(object)
def copy
@copyable ? @default.dup : @default
end

# Check if the name is valid.
def check_name!(name)
raise Errors::InvalidField.new(name) if Mongoid.destructive_fields.include?(name.to_s)
end
end
end
7 changes: 7 additions & 0 deletions spec/unit/mongoid/config_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@
end
end

describe "#destructive_fields" do

it "returns an array of bad field names" do
config.destructive_fields.should include("collection")
end
end

describe "#master=" do

context "when object provided is not a Mongo::DB" do
Expand Down
17 changes: 17 additions & 0 deletions spec/unit/mongoid/errors_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -101,4 +101,21 @@
end
end
end

describe Mongoid::Errors::InvalidField do

describe "#message" do

context "default" do

before do
@error = Mongoid::Errors::InvalidField.new("collection")
end

it "contains class is not allowed" do
@error.message.should include("field named 'collection' is not allowed")
end
end
end
end
end
10 changes: 10 additions & 0 deletions spec/unit/mongoid/field_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,16 @@

end

describe "#initialize" do

context "when the field name is invalid" do

it "raises an error" do
lambda { Mongoid::Field.new(:collection) }.should raise_error(Mongoid::Errors::InvalidField)
end
end
end

describe "#name" do

before do
Expand Down

0 comments on commit faa5036

Please sign in to comment.