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

Cannot generate URL correctly #6

Closed
chengyin opened this issue Nov 10, 2011 · 14 comments
Closed

Cannot generate URL correctly #6

chengyin opened this issue Nov 10, 2011 · 14 comments

Comments

@chengyin
Copy link

I am not sure how this is supposed to work, but with the example code showed in the backbone.js document:

var Book = Backbone.Model.extend({urlRoot : '/books'});
var solaris = new Book({id: "1083-lem-solaris"});
alert(solaris.url());

We get '/books' with backbone-tastypie. This is due to the overwritten on idAttribute and url.

@chengyin
Copy link
Author

So the resource_uri is expected to be used as the id and it should be the full URI of the model. I do not understand this design, could you explain? Thank you.

@PaulUithol
Copy link
Owner

Well, that the url is just /books for a new object is entirely correct, isn't it? If you save it, you should do a POST request to /books, and Tastypie will return you an object containing a resource_uri.

@chengyin
Copy link
Author

What if it is a exist object I want to get? Say, the id is from the URL.

@PaulUithol
Copy link
Owner

If it's an existing object, wouldn't that mean you've fetched it from the server, or as a relation from another model? In that case, you'd have it's resource_uri. I've never encountered a situation where I'd have an id, but not the resource_uri?

@nathanborror
Copy link

I do a lot of fetching with just ID's and this works in vanilla Backbone. I ended up removing your url and idAttribute overrides and everything worked just fine.

@chachra
Copy link

chachra commented Dec 22, 2011

I concur with Nathan. just using id is very much helpful in many cases.

@PaulUithol
Copy link
Owner

Could you give me an actual example maybe? Because I think I don't entirely understand the complete use case yet.

My understanding at the moment is that sometimes you have models without a resource_uri (if you did, there wouldn't be a problem fetching it, right?). If that's the case, it's possible you do already have an id in some way that can be used with the urlRoot to construct a complete url from.

If that's correct, that would be pretty easy to add.

@chachra
Copy link

chachra commented Dec 22, 2011

Paul,

See the backbone documentation. It lets you give a new object an id (meaning u have it in the backend, but in the frontend you are giving an id to tell it how to construct url and fetch it) etc.

http://documentcloud.github.com/backbone/#Model-urlRoot

@PaulUithol
Copy link
Owner

Thanks, but I know Backbone quite well ;). I'm just trying to clarify how the behavior for url should be in relation to the model's id attribute and Tastypie's resource_uri. So if the following sounds okay, this should be pretty trivial to fix:

  • Normally (when requesting data from the server), the current behavior (constructing a url from the resource_uri) is fine;
  • however, there are cases where you do have an actual, existing (hopefully ;) id attribute but the model doesn't contain a resource_uri;
  • in these cases, it'd be nice if the url function could just use the id attribute (so, use model.get('id') as opposed to model.id) and attach it to the urlRoot.

@chachra
Copy link

chachra commented Dec 23, 2011

thats correct. Thanks Paul!

PaulUithol added a commit that referenced this issue Jan 2, 2012
…xplicit 'id' attribute, in the absence of a 'resource_uri'. Fixes issue #6.
@nathanborror
Copy link

This doesn't appear to fix the problem. When .url() is called now it just returns the id of the model instead of the full url. What if the override was something like:

Backbone.Model.prototype.url = function() {
  // If there's no idAttribute, use the 'urlRoot'. Fallback to try to have the collection construct a url.
  // Explicitly add the 'id' attribute if the model has one.
  if (!this.id) {
    url = this.urlRoot;
    url = url || this.collection && (_.isFunction(this.collection.url)? this.collection.url(): this.collection.url);

    if (url && this.has('id')) {
      url = addSlash(url) + this.get('id');
    }
    url = url && addSlash(url);
    return url || null;
  }
  else {
    var base = getUrl(this.collection) || this.urlRoot || urlError();
    if (this.isNew()) return base;
    return base + (base.charAt(base.length - 1) == '/' ? '' : '/') + encodeURIComponent(this.id);
  }
};

I just hacked this together, it could probably be optimized :/

@PaulUithol
Copy link
Owner

I don't see how it wouldn't work, as long as you a) set the urlRoot to the proper value, and b) leave idAttribute pointing to resource_uri (as it should be for tastypie?).

(btw, both getUrl and urlError are functions in Backbone's local scope, as far as I know)

@nathanborror
Copy link

Have you tested it yourself?

@PaulUithol
Copy link
Owner

Well, yes? See tests.js:

    test("Model url", function() {
        var person = new Person();
        equal( person.url(), null );

        // If the model doesn't have an 'urlRoot' and no value for it's 'idAttribute', the collection's
        // 'urlRoot' is be used as a fallback ( a POST there creates a resource).
        var coll = new Backbone.Collection();
        coll.urlRoot = '/persons';
        person.collection = coll;
        equal( person.url(), '/persons/' );

        // If present, the model's urlRoot is used as a fallback.
        person.urlRoot = '/person';
        equal( person.url(), '/person/' );

        // The value of the explicit 'id' attribute is added to the 'urlRoot' when available
        person.set( 'id', 2 );
        equal( person.url(), '/person/2/' );

        // If the idAttribute is set, it's used as the uri verbatim.
        person.set( { resource_uri: '/person/1/' } );
        equal( person.url(), '/person/1/' );
    });

Could you check if these tests pass for you? If they do and you have a scenario that does fail, please share the testcase.

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

4 participants