Skip to content
Browse files

has() method re-write to be more sane

- fully specced and all specs passing
- supports 1..n n..1 n..n associations
- support for 1..4  4..1 4..4 style for setting fixed constraints
- no support for constraints within a range yet though, have to fall back to :min=>1, :max=>2 for that
- needs docs
  • Loading branch information...
1 parent e731d35 commit d244cce406b93f6e6cb71c3642791d0a091e603c @andykent andykent committed with Dan Kubb Apr 18, 2008
Showing with 87 additions and 31 deletions.
  1. +28 −14 lib/data_mapper/associations.rb
  2. +59 −17 spec/unit/associations_spec.rb
View
42 lib/data_mapper/associations.rb
@@ -20,26 +20,40 @@ def n
1.0/0
end
- def has(name, cardinality, options = {})
+ def has(cardinality, name, options = {})
case cardinality
when Range
- min, max = cardinality.first, cardinality.last
- case min
- when 0, 1 # 0..n, 1..n
- one_to_many(name, options.merge(:min => min, :max => max))
- when Fixnum, Bignum, n
- case max
- when 0, 1 # n..0, n..1
- many_to_one(name, options.merge(:min => min, :max => max))
- when Fixnum, Bignum, n # n..2, n..n
- many_to_many(name, options.merge(:min => min, :max => max))
- end
+ left, right = cardinality.first, cardinality.last
+ case 1
+ when left #1..n or 1..2
+ one_to_many(name, options.merge(extract_min_max(right)))
+ when right # n..1 or 2..1
+ many_to_one(name, options.merge(extract_min_max(left)))
+ else # n..n or 2..2
+ many_to_many(name, options.merge(extract_min_max(cardinality)))
end
when 1
one_to_one(name, options)
- when Fixnum, Bignum, n
- one_to_many(name, options.merge(:min => cardinality, :max => cardinality))
+ when Fixnum, Bignum, n # n or 2 - shorthand form of 1..n or 1..2
+ one_to_many(name, options.merge(extract_min_max(cardinality)))
end || raise(ArgumentError, "Cardinality #{cardinality.inspect} (#{cardinality.class}) not handled")
end
+
+ private
+ def extract_min_max(contraints)
+ case contraints
+ when Range
+ left = extract_min_max(contraints.first)
+ right = extract_min_max(contraints.last)
+ conditions = {}
+ conditions.merge!(:left=>left) if left.any?
+ conditions.merge!(:right=>right) if right.any?
+ conditions
+ when Fixnum, Bignum
+ {:min=>contraints, :max=>contraints}
+ when n
+ {}
+ end || raise(ArgumentError, "Contraint #{contraints.inspect} (#{contraints.class}) not handled must be one of Range, Fixnum, Bignum, Infinity(n)")
+ end
end # module Associations
end # module DataMapper
View
76 spec/unit/associations_spec.rb
@@ -13,7 +13,7 @@
it "should allow a declaration" do
lambda do
class Manufacturer
- has :halo_car, 1
+ has 1, :halo_car
end
end.should_not raise_error
end
@@ -24,7 +24,7 @@ class Manufacturer
with(:halo_car,{}).
and_return(@relationship)
class Manufacturer
- has :halo_car, 1
+ has 1, :halo_car
end
end
@@ -33,7 +33,7 @@ class Manufacturer
with(:halo_car, {:class_name => 'Car', :repository_name => 'other'}).
and_return(@relationship)
class Manufacturer
- has :halo_car, 1,
+ has 1, :halo_car,
:class_name => 'Car',
:repository_name => 'other'
end
@@ -43,28 +43,32 @@ class Manufacturer
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).
- with(:vehicles,{:min=>0, :max=>@n}).
+ with(:vehicles,{}).
and_return(@relationship)
class Manufacturer
- has :vehicles, 0..n
+ has 1..n, :vehicles
end
end
- it "should create a one-to-many association with constraints" do
+ it "should create a one-to-many association with fixed constraint" do
Manufacturer.should_receive(:one_to_many).
- with(:vehicles,{:min=>2, :max=>4}).
+ with(:vehicles,{:min=>4, :max=>4}).
and_return(@relationship)
class Manufacturer
- has :vehicles, 2..4
+ has 1..4, :vehicles
end
end
+
+ it "should create a one-to-many association with min/max constraints" do
+ pending
+ end
it "should create a one-to-many association with options" do
Manufacturer.should_receive(:one_to_many).
- with(:vehicles,{:min=>1, :max=>@n, :class_name => 'Car'}).
+ with(:vehicles,{:class_name => 'Car'}).
and_return(@relationship)
class Manufacturer
- has :vehicles, 1..n,
+ has 1..n, :vehicles,
:class_name => 'Car'
end
end
@@ -73,28 +77,66 @@ class Manufacturer
describe "many-to-one syntax" do
it "should create a basic many-to-one association with no constraints" do
Manufacturer.should_receive(:many_to_one).
- with(:vehicles,{:min=>0, :max=>@n}).
+ with(:vehicles,{}).
and_return(@relationship)
class Manufacturer
- has :vehicles, n..0
+ has n..1, :vehicles
end
end
- it "should create a many-to-one association with constraints" do
+ it "should create a many-to-one association with fixed constraint" do
Manufacturer.should_receive(:many_to_one).
- with(:vehicles,{:min=>2, :max=>4}).
+ with(:vehicles,{:min=>4, :max=>4}).
and_return(@relationship)
class Manufacturer
- has :vehicles, 4..2
+ has 4..1, :vehicles
end
end
+ it "should create a many-to-one association with min/max constraints" do
+ pending
+ end
+
it "should create a many-to-one association with options" do
Manufacturer.should_receive(:many_to_one).
- with(:vehicles,{:min=>1, :max=>@n, :class_name => 'Car'}).
+ with(:vehicles,{:class_name => 'Car'}).
+ and_return(@relationship)
+ class Manufacturer
+ has n..1, :vehicles,
+ :class_name => 'Car'
+ end
+ end
+ end
+
+ describe "many-to-many syntax" do
+ it "should create a basic many-to-one association with no constraints" do
+ Manufacturer.should_receive(:many_to_many).
+ with(:vehicles,{}).
+ and_return(@relationship)
+ class Manufacturer
+ has n..n, :vehicles
+ end
+ end
+
+ it "should create a many-to-many association with fixed constraints" do
+ Manufacturer.should_receive(:many_to_many).
+ with(:vehicles, :left=>{:min=>4, :max=>4}, :right=>{:min=>4, :max=>4}).
+ and_return(@relationship)
+ class Manufacturer
+ has 4..4, :vehicles
+ end
+ end
+
+ it "should create a many-to-many association with min/max constraints" do
+ pending
+ end
+
+ it "should create a many-to-many association with options" do
+ Manufacturer.should_receive(:many_to_many).
+ with(:vehicles,{:class_name => 'Car'}).
and_return(@relationship)
class Manufacturer
- has :vehicles, n..1,
+ has n..n, :vehicles,
:class_name => 'Car'
end
end

0 comments on commit d244cce

Please sign in to comment.
Something went wrong with that request. Please try again.