Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Different keys for lookup and relation referencing #144

Open
soswow opened this issue Jul 17, 2014 · 3 comments
Open

Different keys for lookup and relation referencing #144

soswow opened this issue Jul 17, 2014 · 3 comments

Comments

@soswow
Copy link

soswow commented Jul 17, 2014

I am thinking about similar attributes Relational has key and keySource
This perfectly matched our data/server communication before.

Example. Here is project object

{"id": 10, "name": "Project"}

And this is task:

{"id": 20, "name": "Task", "pid": 10}

pid - is id of a project this task belongs to. So I naturally do something like this

class Task extends Backbone.AssociatedModel
  relations: [{
    type: Backbone.One
    relatedModel: 'model.Project'
    key: 'pid'
    map: (pid) ->
      someGlobalScope.projects.get pid
  }]

But now, I can access project from Task only by task.get('pid') - But this is wrong. pid is Project Id, not project itself. I would like to task.get('project')

Is there a way?

@soswow
Copy link
Author

soswow commented Jul 17, 2014

Don't know if this is should be requested here, but ...
In the example above, when we want to store Task back to the server, we want to send information about project it belongs to. And this is also defined with pid property.
Right now I can define serialize: ['id'], but this will make

{"id": 20, "name": "Task", "pid": {"id": 10}}

which is not what I wanted =\ I thought what if serialize could be not only Array, but a string also. In case of string it could make what I want for example. Also this will makes IN and OUT to be consisted (Which is logical I think) (I mean what was passed as raw JSON string in the beginning will come back the same)

@soswow
Copy link
Author

soswow commented Jul 17, 2014

Something like this would work maybe?

===================================================================
--- app/components/backbone-associations/backbone-associations.js   (revision )
+++ app/components/backbone-associations/backbone-associations.js   (revision )
@@ -260,21 +259,22 @@
                 // if `relations` are available.
                 _.each(this.relations, function (relation) {
                     var relationKey = relation.key,
+                        referenceKey = relation.referenceKey || relation.key,
                         activationContext = relation.scope || root,
                         relatedModel = this._transformRelatedModel(relation, attributes),
                         collectionType = this._transformCollectionType(relation, relatedModel, attributes),
                         map = _.isString(relation.map) ? map2Scope(relation.map, activationContext) : relation.map,
-                        currVal = this.attributes[relationKey],
+                        currVal = this.attributes[referenceKey],
                         idKey = currVal && currVal.idAttribute,
                         val, relationOptions, data, relationValue, newCtx = false;

                     // Merge in `options` specific to this relation.
                     relationOptions = relation.options ? _.extend({}, relation.options, options) : options;

-                    if (attributes[relationKey]) {
+                    if (attributes[referenceKey]) {

                         // Get value of attribute with relation key in `val`.
-                        val = _.result(attributes, relationKey);
+                        val = _.result(attributes, referenceKey);

                         // Map `val` if a transformation function is provided.
                         val = map ? map.call(this, val, collectionType ? collectionType : relatedModel) : val;

And now my relation definition looks like

relations: [{
    type: Backbone.One
    relatedModel: 'Project'
    key: 'project'
    referenceKey: 'pid'
    isTransient: true
    map: (id) ->
      toggl.model.Projects.get id
  }]

In result. I get project on .get('project') I get id on .get('pid') and this id still in the JSON response

Looks like if I set new project task.set 'pid', 'test2' it also works well.

@vinnymac
Copy link

I ran into a similar situation. Without modifying Backbone Associations, you could do this more easily. In your original example you wrote this:

class Task extends Backbone.AssociatedModel
  relations: [{
    type: Backbone.One
    relatedModel: 'model.Project'
    key: 'pid'
    map: (pid) ->
      someGlobalScope.projects.get pid
  }]

You could do the following to get your desired result without any modifications to the lib.

class Task extends Backbone.AssociatedModel
  relations: [{
    type: Backbone.One
    relatedModel: 'model.Project'
    key: 'project'
    map: ->
      someGlobalScope.projects.get @get 'pid'
  }]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants