Trying to get an value from a DataMapper join table and association
开发者_运维知识库I have 3 classes - Mix, MixClip, and Clip.
class Mix
include DataMapper::Resource
property :id, Serial
# <removed other code for brevity>
has n, :mix_clips
has n, :clips, :through => :mix_clips
end
class MixClip
include DataMapper::Resource
property :id, Serial
property :order, Integer
belongs_to :mix
belongs_to :clip
end
class Clip
include DataMapper::Resource
property :id, Serial
property :title, String
property :description, Text
has n, :mix_clips
has n, :mixes, :through => :mix_clips
end
MixClip joins the Mix/Clip tables and includes an extra property to describe the clip (order). I would like to know if it's possible to have a clip object and be able to reference the current clip in the context it was loaded in.
So let's say I load a Mix and a Clip like so:
mix = Mix.first
clip = mix.clips.first
Is there a way to get the MixClip that is associated with that specific Clip?
clip.mix_clip.order
It was loaded through join between the table, so I would think there would be a way to do it.
I know I can just get all the mix->mix->clips-> and and drill down, but was wondering if I would be able to go back up levels... it would be simpler.
For those wondering, I'm trying to use this because dm-serializer doesn't have full support for nested associations when returning json/xml and I'd like to be able to just define a method that returns the data.
Thanks.
Without changing any of your code, you should be able to do:
mix_clip = clip.mix_clips.first(:mix => mix, :clip => clip)
to get at the join record associated with your specific mix
and clip
resources.
Currently, there's a bug in DM that makes it kinda unreliable to do the following without any additional measures:
mix_clip = clip.mix_clips.get(mix.id, clip.id)
This is because DM forgets the order in which relationships have been defined, and thus cannot currently know reliably in which order the .get
method should accept the primary key components.
You can work around this by defining the foreign key properties explicitly in your join model, like so (note that you still have to declare the relationships explicitly, of course):
class MixClip
include DataMapper::Resource
property :id, Serial
property :order, Integer
property :mix_id, Integer, :key => true
property :clip_id, Integer, :key => true
belongs_to :mix
belongs_to :clip
end
This will make sure that DM knows that .get
accepts the primary key as (mix_id, clip_id)
so you're now able to call
mix_clip = clip.mix_clips.get(mix.id, clip.id)
A reason for wanting to do that is that calls to .get
take the identity map into account, which, based on your access characteristics, might be able to yield better performance.
精彩评论