Backbone-relational: Association key won't work unless it's the same as the foreign key
Asked Answered
S

2

6

I'm trying to get the backbone-relational plugin working with an association between tasks and messages. (A task has many messages).

The information is pulled from a standard rails/activerecord site, which has a task_id field as the foreign key.

The problem is, backbone-relational won't populate the 'messages' field with any messages on teh Task model unless I set the key as "task_id" in the reverse relation...but that means that, when accessing the task from the Message model, the task_id field is populated with the actual task object, not the 'task_id' integer, which is overwritten.

I'm guessing there's a simple way to specify task_id as the foreign key with which to determine the parent task, yet have the object that key represents placed in a different field (eg 'task' on the messages object)...but I can't figure out how. Any ideas appreciated. Code below

class Backbonescaffolddemo.Models.Task extends Backbone.RelationalModel
  paramRoot: 'task'

  relations: [{
    type: Backbone.HasMany,
    key: "messages",
    relatedModel: "Backbonescaffolddemo.Models.Message",
    collectionType: "Backbonescaffolddemo.Collections.MessagesCollection",
    includeInJSON: true
    reverseRelation: {
      key: "task_id"
      includeInJSON: true
    }
  }]
Saturnalia answered 2/1, 2012 at 18:27 Comment(1)
Please, how did you fix your issue? I opened the following issue on github because of the same reason. thanks. Foreign key populated with an objectCausal
H
3

You may be able to use keySource or keyDestination to address your particular problem.

Example

In the following example, suppose we are getting data from an old-school relational database, where there is a one-to-many relationship between Monster and Loot_Item. This relationship is expressed by a Monster_Id foreign key in the Loot_Item table. Let us also suppose that our REST service doesn't do any fancy-pants data nesting for us, since that seems to match the situation in your question fairly closely.

keySource

Now, let's set set "keySource" to my foreign key ("Monster_Id") and "key" to the name of the attribute where I want the actual data to go (say, "Monster"). If you break in the debugger, you will see in the attributes object that there is, in fact, a field called "Monster", and that it does point to the monster model data. Hey, cool!

includeInJSON

However, if you toJSON that puppy, guess what? It has put all the monster data in Monster_Id, just like you didn't want! GAH! We can fix that by setting "includeInJSON" to "Monster_Id". Now, when it is converted to JSON, it puts the proper ID back into the Monster_Id field, when it is serializing your data to JSON, to send up to the server.

Problem solved? Er, well, actually, not necessarily...

CAVEAT: This all sounds super-useful, but there's one fairly glaring problem that I have found with this scenario. If you are using a templating engine (such as the one in Underscore.js) that requires you to convert your model to JSON, before passing it into the template, whoops -- you don't have access to your relational data. Alas, the JSON that we want for our messages is not necessarily the same JSON that we want to feed into our templates.

Homophonous answered 21/5, 2012 at 21:13 Comment(2)
Please, how did you fix this issue? Maybe I missed something. I opened the following issue on github. Foreign key populated with an objectCausal
Smokefoot, RDBMSes have been around since the early 70s (at least). In computing terms, that's pretty "old-school." However, that is not a value-judgement about their usefulness. They are robust, their use cases are very well understood, and there is a great deal of technology that is compatible with them. Unfortunately, a lot of REALLY NEW technology has been dismissive about compatibility with properly designed relational databases, and that is why we are relying on third-party add-ons like Backbone-relational, and why it is STILL not solving our problems very well.Homophonous
R
0

If you want the "task_id" in the message JSON to be the id, not the full JSON for the task, then set the "includeInJSON" to be the Task's ID property ("task_id")

class Backbonescaffolddemo.Models.Task extends Backbone.RelationalModel
  paramRoot: 'task'

  relations: [{
    type: Backbone.HasMany,
    key: "messages",
    relatedModel: "Backbonescaffolddemo.Models.Message",
    collectionType: "Backbonescaffolddemo.Collections.MessagesCollection",
    includeInJSON: true
    reverseRelation: {
      key: "task_id"
      includeInJSON: "task_id"
    }
  }]

The "true" value for includeInJSON says to use the full JSON for the related model.

Edit: After re-reading your question, I'm not sure my answer relates to your issue.

My original answer is for posting a message back to the server where you want the JSON to be something like:

{
  "message_title": "My Title",
  "message_body": "Blah blah blah...",
  "task_id": 12345
}

I'm not sure what exactly you're looking to happen, but the way that Backbone Relational is supposed to work is that the Task's collection of messages will be a collection of the full models, so you can iterate over them and pass them to views for rendering, etc.

If you want to output one of the Message's id's in a template or something, then you'd take the Message model's "id":

myTask.get('messages').first().id  ->  returns the first message's id
Royden answered 2/1, 2012 at 22:48 Comment(1)
Please, how did you fix this issue? Maybe I missed something. I opened the following issue on github. Foreign key populated with an objectCausal

© 2022 - 2024 — McMap. All rights reserved.