Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Updated has() to accept a cardinality of 0..1

* Added specs for exceptions
  • Loading branch information...
commit abeeeba5af7a809910476177dcbae64766852413 1 parent 4e9a279
Dan Kubb authored
Showing with 62 additions and 38 deletions.
  1. +23 −23 lib/data_mapper/associations.rb
  2. +39 −15 spec/unit/associations_spec.rb
View
46 lib/data_mapper/associations.rb
@@ -19,7 +19,7 @@ def relationships
def n
1.0/0
end
-
+
#
# A shorthand, clear syntax for defining one-to-one, one-to-many and many-to-many resource relationships.
#
@@ -32,7 +32,7 @@ def n
# * has 3, :friends, :through=>:friendships # one_to_many :friends, :through => :friendships
#
# ==== Parameters
- # cardinality<Fixnum, Bignum, Infinity, Range>:: Defines the association type & constraints
+ # cardinality<Fixnum, Bignum, Infinity, Range>:: Defines the association type & constraints
# name<Symbol>:: The name that the association will be referenced by
# opts<Hash>:: An options hash (see below)
#
@@ -48,21 +48,18 @@ def n
#
# @public
def has(cardinality, name, options = {})
- case cardinality
- when Range
- min, max = cardinality.first, cardinality.last
- # 1..n or 3..5
- one_to_many(name, extract_min_max(cardinality).merge(options))
- when 1
- one_to_one(name, options)
- when Fixnum, Bignum, n # n or 2 - shorthand form of n..n or 2..2
- one_to_many(name, extract_min_max(cardinality).merge(options))
- end || raise(ArgumentError, "Cardinality #{cardinality.inspect} (#{cardinality.class}) not handled")
+ options = extract_min_max(cardinality).merge(options)
+
+ if options[:max] == 1
+ one_to_one(name, options)
+ else
+ one_to_many(name, options)
+ end
end
-
+
#
# A shorthand, clear syntax for defining many-to-one resource relationships.
- #
+ #
# ==== Usage Examples...
# * belongs_to :user # many_to_one, :friend
# * belongs_to :friend, :classname => 'User' # many_to_one :friends
@@ -81,22 +78,25 @@ def has(cardinality, name, options = {})
def belongs_to(name, options={})
many_to_one(name, options)
end
-
-
- private
-
+
+
+ private
+
# A support method form converting Fixnum, Range or Infinity values into a {:min=>x, :max=>y} hash.
#
# @private
- def extract_min_max(contraints)
- case contraints
+ def extract_min_max(constraints)
+ case constraints
when Range
- {:min=>contraints.first, :max=>contraints.last}
+ raise ArgumentError, "Constraint min (#{constraints.first}) cannot be larger than the max (#{constraints.last})" if constraints.first > constraints.last
+ { :min => constraints.first, :max => constraints.last }
when Fixnum, Bignum
- {:min=>contraints, :max=>contraints}
+ { :min => constraints, :max => constraints }
when n
{}
- end || raise(ArgumentError, "Contraint #{contraints.inspect} (#{contraints.class}) not handled must be one of Range, Fixnum, Bignum, Infinity(n)")
+ else
+ raise ArgumentError, "Constraint #{constraints.inspect} (#{constraints.class}) not handled must be one of Range, Fixnum, Bignum, Infinity(n)"
+ end
end
end # module Associations
end # module DataMapper
View
54 spec/unit/associations_spec.rb
@@ -10,7 +10,7 @@
end
describe ".has" do
-
+
it "should allow a declaration" do
lambda do
class Manufacturer
@@ -18,7 +18,24 @@ class Manufacturer
end
end.should_not raise_error
end
-
+
+ it "should not allow a constraint that is not a Range, Fixnum, Bignum or Infinity" do
+ lambda do
+ class Manufacturer
+ has '1', :halo_car
+ end
+ end.should raise_error(ArgumentError)
+ end
+
+ it "should not allow a constraint where the min is larger than the max" do
+ lambda do
+ class Manufacturer
+ has 1..0, :halo_car
+ end
+ end.should raise_error(ArgumentError)
+ end
+
+ # FIXME: perhaps this shouldn't be allowed?
it "should allow overwriting of the auto assigned min/max values with keys" do
Manufacturer.should_receive(:one_to_many).
with(:vehicles, {:min=>1, :max=>10}).
@@ -29,27 +46,35 @@ class Manufacturer
end
describe "one-to-one syntax" do
- it "should create a basic one-to-one association" do
+ it "should create a basic one-to-one association with fixed constraint" do
Manufacturer.should_receive(:one_to_one).
- with(:halo_car,{}).
+ with(:halo_car, { :min => 1, :max => 1 }).
and_return(@relationship)
class Manufacturer
has 1, :halo_car
end
end
+ it "should create a basic one-to-one association with min/max constraints" do
+ Manufacturer.should_receive(:one_to_one).
+ with(:halo_car, { :min => 0, :max => 1 }).
+ and_return(@relationship)
+ class Manufacturer
+ has 0..1, :halo_car
+ end
+ end
+
it "should create a one-to-one association with options" do
Manufacturer.should_receive(:one_to_one).
- with(:halo_car, {:class_name => 'Car', :repository_name => 'other'}).
+ with(:halo_car, {:class_name => 'Car', :min => 1, :max => 1 }).
and_return(@relationship)
class Manufacturer
- has 1, :halo_car,
- :class_name => 'Car',
- :repository_name => 'other'
+ has 1, :halo_car,
+ :class_name => 'Car'
end
end
end
-
+
describe "one-to-many syntax" do
it "should create a basic one-to-many association with no constraints" do
Manufacturer.should_receive(:one_to_many).
@@ -59,7 +84,7 @@ class Manufacturer
has n, :vehicles
end
end
-
+
it "should create a one-to-many association with fixed constraint" do
Manufacturer.should_receive(:one_to_many).
with(:vehicles,{:min=>4, :max=>4}).
@@ -68,7 +93,7 @@ class Manufacturer
has 4, :vehicles
end
end
-
+
it "should create a one-to-many association with min/max constraints" do
Manufacturer.should_receive(:one_to_many).
with(:vehicles,{:min=>2, :max=>4}).
@@ -87,13 +112,13 @@ class Manufacturer
:class_name => 'Car'
end
end
-
+
it "should create a many-to-many relationship if references are circular" do
# ================
pending
# ================
end
-
+
it "should create one-to-many association and pass the :through option if specified" do
Vehicle.should_receive(:one_to_many).
with(:suppliers,{:through => :manufacturers}).
@@ -104,7 +129,7 @@ class Vehicle
end
end
end
-
+
describe ".belongs_to" do
it "should create a basic many-to-one association" do
Manufacturer.should_receive(:many_to_one).
@@ -126,4 +151,3 @@ class Manufacturer
end
end
end
-
Please sign in to comment.
Something went wrong with that request. Please try again.