Ok, so this is driving me crazy. I have read the Associations article and example and been trying to work this out for the las three days and I’m tired of this making me feel dumb, so…
How does one set up associations with DataMapper?
(I am using DM with Sinatra with SQLite3. Everything word fine for single tables with multiple values etc. It’s when I start to try to associate them that I start getting errors.)
Let’s say I have an Orchard full of Apple Trees. Each Tree has many Apples. Each Apple has many Seeds. Therefore each tree has many Seeds through its Apples
require 'sinatra'
require 'datamapper'
DataMapper::setup(:default, "sqlite3://#{Dir.pwd}/orchard.db")
# Trees in the orchard.
class Tree
include DataMapper::Resource
property :id, Serial
has n, :apples
has n, :seeds, :through => :apples
end
# Apples on a Tree.
class Apple
include DataMapper::Resource
property :id, Serial
belongs_to :tree
belongs_to :seed
end
# Seeds in an Apple
class Seed
include DataMapper::Resource
property :id, Serial
has n, :apple
has n, :tree, :through => apple
end
DataMapper.finalize.auto_upgrade!
Is that correct? I keep getting various errors when I try to run this. Mostly along the lines of invalid association or cannot create column NULL with value NULL etc. What am I not understanding about this relationship?
Further, Once I have a working model how do I go about getting information from it?
If there are 3 trees:
Tree.all.count
=> 3
If there are 2 apples:
Apple.all
=>[#<Apple @id=1>, #<Apple @id=2>]
Ok cool.
But how many Apples does Tree #2 have?
How many Seeds does Tree #4 have?
How many Apples in total?
How many Seeds in total?
Any help would be greatly appreciated.
Your model seems a bit confused:
So a tree has many apples, an apple belongs to a tree and has many seeds, and a seed belongs to an apple (and ultimately a single tree).
We can almost (but not quite) take that language as it is and use it to create the associations. After a little translation to get the syntax right we get this:
In your code you have seeds having multiple apples and trees, which doesn’t really make any sense.
As for querying:
Assuming you mean the
Treewithid == 2:The association we added to the
Treemodelhas n, :seeds, :through => :applesmeans we have aseedsmethod available inTreeobjects.Simply:
Try loading this new model into irb (you might need to delete your
orchard.dbfile when you change the model), and then playing around with some of the queries and creation methods, hopefully that’ll give you a better idea of what’s going on.Creating associations
(See the section "Adding To Associations" on the Associations page.)
To add an existing
Appleto aTree:Note that a
Treeisn’t associated with a singleApplebut a collection (ithas nApples), so the method created isapples(i.e. it’s pluralized), and there’s no methodapplewhich is why you’re seeing the no method error.You can also create a new
Appleassociated with aTreedirectly:You can also create the association the other way round, from the
Appleside:but you need to be careful doing it this way, as the new apple won’t show up in the
a_trees collection ofApples(a_tree.appleswon’t includean_other_apple). In order for it to appear you need to save the apple, and then callreloadon theTree:You need to watch out with this, as you can end up with an
Applethat appears to be in twoTrees at the same time if you’re not careful.