Skip to content

Commit

Permalink
Allow casting of foreign keys where appropriate in serialization to n…
Browse files Browse the repository at this point in the history
…on object ids. Fixes #1399
  • Loading branch information
durran committed Nov 6, 2011
1 parent daa22e8 commit fe1472c
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 25 deletions.
7 changes: 6 additions & 1 deletion CHANGELOG.md
Expand Up @@ -8,7 +8,12 @@ For instructions on upgrading to newer versions, visit
* Ranges can now be passed to #where criteria to create a $gte/$lte query under the
covers. `Person.where(dob: start_date...end_date)`

## 2.3.3 \[ In Development \] \[ Branch: 2.3.0-stable \]
## 2.3.4 \[ In Development \] \[ Branch: 2.3.0-stable \]

* \#1399 Allow conversion of strings to integers in foreign keys where the
id is defined as an int.

## 2.3.3

### Resolved Issues

Expand Down
24 changes: 12 additions & 12 deletions lib/mongoid/extensions/object_id/conversions.rb
Expand Up @@ -22,36 +22,36 @@ module Conversions
# BSON::ObjectId.convert(Person, { :_id => "4c52c439931a90ab29000003" })
#
# @param [ Class ] klass The class to convert the ids for.
# @param [ Object, Array, Hash ] args The object to convert.
# @param [ Object, Array, Hash ] object The object to convert.
#
# @raise BSON::InvalidObjectId If using object ids and passed bad
# strings.
#
# @return [ BSON::ObjectId, Array, Hash ] The converted object ids.
#
# @since 2.0.0.rc.7
def convert(klass, args, reject_blank = true)
return args if args.is_a?(BSON::ObjectId) || !klass.using_object_ids?
case args
def convert(klass, object, reject_blank = true)
return object if object.is_a?(BSON::ObjectId) || !klass.using_object_ids?
case object
when ::String
return nil if args.blank?
if args.unconvertable_to_bson?
args
return nil if object.blank?
if object.unconvertable_to_bson?
object
else
BSON::ObjectId.legal?(args) ? BSON::ObjectId.from_string(args) : args
BSON::ObjectId.legal?(object) ? BSON::ObjectId.from_string(object) : object
end
when ::Array
args.delete_if { |arg| arg.blank? } if reject_blank
args.replace(args.map { |arg| convert(klass, arg, reject_blank) })
object.delete_if { |arg| arg.blank? } if reject_blank
object.replace(object.map { |arg| convert(klass, arg, reject_blank) })
when ::Hash
args.tap do |hash|
object.tap do |hash|
hash.each_pair do |key, value|
next unless klass.object_id_field?(key)
hash[key] = convert(klass, value, reject_blank)
end
end
else
args
object
end
end
end
Expand Down
7 changes: 6 additions & 1 deletion lib/mongoid/fields/serializable/foreign_keys/object.rb
Expand Up @@ -33,7 +33,12 @@ def object_id_field?
#
# @since 2.1.0
def serialize(object)
object.blank? ? nil : constraint.convert(object)
return nil if object.blank?
if object_id_field?
constraint.convert(object)
else
metadata.klass.fields["_id"].serialize(object)
end
end
end
end
Expand Down
22 changes: 21 additions & 1 deletion spec/functional/mongoid/relations/referenced/in_spec.rb
Expand Up @@ -4,7 +4,8 @@

before do
[ Person, Game, Post, Bar, Agent,
Comment, Movie, Account, User, Book, Series ].map(&:delete_all)
Comment, Movie, Account, User, Book,
Series, Cookie, Jar ].map(&:delete_all)
end

let(:person) do
Expand Down Expand Up @@ -896,4 +897,23 @@
end
end
end

context "when creating with a reference to an integer id parent" do

let!(:jar) do
Jar.create(:_id => 1)
end

let(:cookie) do
Cookie.create(:jar_id => "1")
end

it "allows strings to be passed as the id" do
cookie.jar.should eq(jar)
end

it "persists the relation" do
cookie.reload.jar.should eq(jar)
end
end
end
41 changes: 31 additions & 10 deletions spec/unit/mongoid/fields/serializable/foreign_keys/object_spec.rb
Expand Up @@ -37,20 +37,41 @@

context "when not using object ids" do

let(:object_id) do
BSON::ObjectId.new
end
context "when using strings" do

before do
Person.identity :type => String
end
let(:object_id) do
BSON::ObjectId.new
end

before do
Person.identity :type => String
end

after do
Person.identity :type => BSON::ObjectId
after do
Person.identity :type => BSON::ObjectId
end

it "does not convert" do
field.serialize(object_id.to_s).should == object_id.to_s
end
end

it "does not convert" do
field.serialize(object_id.to_s).should == object_id.to_s
context "when using integers" do

context "when provided a string" do

before do
Person.identity :type => Integer
end

after do
Person.identity :type => BSON::ObjectId
end

it "does not convert" do
field.serialize("1").should eq(1)
end
end
end
end
end
Expand Down

0 comments on commit fe1472c

Please sign in to comment.