Question

let's say my config/models file looks like this:

Pet
    name Text
    owner OwnerId
Owner
    name Text

I can get the pet's name like this:

 $forall Entity key pet <- pets
     <span>#{petName pet} 

but how would I get an owner's name from a pet entity?

in other words, what should foo be in the following:

 <span>#{ownerName $ foo $ petOwner pet}
Was it helpful?

Solution

Yesod doesn't build functions for relations the way (e.g.) rails might, so you've got to just write this sort of thing yourself.

-- just one naive example
petOwnerName :: Pet -> Handler (Maybe Text)
petOwnerName p = do
    mo <- runDB $ get (petOwner p)
    return $ fmap ownerName mo

Notice this returns in Handler (and it must due to the DB query required), that means you couldn't use it directly as your foo in an interpolation.

Taking your example literally, executing that action from within a template is exactly what you expect to be able to do. I'd stress that this is usually a design smell and I would recommend you restructure things so that you do all your db querying up front in the Handler then pass whatever (pure) values the template needs directly to it. You could build and pass in a [(Pet,Owner)] or [(Owner, [Pet])] for example.

I've got some helpers in one of my sites which abstract common ways to query the DB for one-to-many relations and get back a list of tuples like (parent, child) I find that to be the most useful method.

Hope this helps.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top