So, I've been generating different scaffolds trying to use the One-to-Many relationship features of Tower, but I can't figure out how to actually link up the related instances to make use of the relationship. For instance, my most recent scaffolds were generated like this:
tower generate scaffold User email:string firstName:string lastName:string hasMany:posts
tower generate scaffold Post title:string body:text userId:integer belongsTo:user
Now, in rails, that userId field, on the post model, would form a connection with the user sharing that id, and then you could use that to access the relationship. But here it doesn't seem to do anything. Trying to use any of the code from here: https://github.com/viatropos/tower/wiki/1-n just gives me errors.
In the tower console, I was able to create an example user and post (I can also do this easily enough by running the server and using the forms on the web page), like so:
tower> user = new App.User
tower> user.attributes = { email: "[email protected]", firstName: "bill", lastName: "billiams" }
tower> post = new App.Post
tower> post.attributes = { title: "A Post", body: "This is a short post.", userId: "4fbf23224503fe670e000006" }
And these instances are persisted to the database, but when I try code like:
tower> user.get('posts').exists()
I get "TypeError: Cannot call method 'exists' of undefined". Similarly, calling:
tower> user.get('posts').create(title: 'Berlin never sleeps.')
produces "TypeError: Cannot call method 'create' of undefined". The same sort of thing happens if I try anything like this in the models or controllers. I'm really stuck here, and have been trying for several days to figure out how this works, but I don't know where else to look. If anyone has example code I could peek at, that would be awesome, otherwise an explanation of sorts would be helpful also. Thanks.
[Edit: My working example, along with detailed README explaining the steps, can be found here: https://github.com/edubkendo/demoApp ]
Right now relations are accessed through methods rather than getters:
the
posts()
method returns aTower.Model.Relation.HasMany.Scope
object, which is a subclass ofTower.Model.Scope
. The "scope" is what allows you to do queries on the database:Just for reference, here's how the relations are built. First, when you do something like:
that
@hasMany 'posts'
goes to /tower/model/relations.coffee#L50, which constructs aTower.Model.Relation.HasMany
object, which extendsTower.Model.Relation
. TheTower.Model.Relation
class defines the association methods/getters on theowner
class, theApp.User
: /tower/model/relation.coffee#L85.When you do
user.posts()
, it constructs a newTower.Model.Relation.HasMany.Scope
: /tower/model/relations.coffee#L85, which gives you all the finder/persistence methods, the same as doingApp.User.asc('createdAt').all()
. The relation subclassesTower.Model.Scope
in order to customize find/create/update/delete methods for the association, that's pretty much it.Last thing, the api is going to be changed within the next few weeks as we normalize it with the field methods (i.e.
user.get('email')
). So soon, it will look like this:But for now, use this:
Hope that helps.