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

Add an attributes parameter to toJSON on model, which returns whitelisted properties. #573

Closed
wants to merge 1 commit into from
Closed

Add an attributes parameter to toJSON on model, which returns whitelisted properties. #573

wants to merge 1 commit into from

Conversation

keithamus
Copy link
Contributor

Add an attributes parameter to toJSON method which, when passed, runs a whitelist filter on returned attributes

Example Use:
model.toJSON(['one', 'two']) == {one: 1, two: 2}

Use Case:

When getting JSON representations of the model we want to send certain attributes to certain endpoints, and other attributes to other endpoints

… a whitelist filter on returned attributes

Example Use:
    model.toJSON(['one', 'two']) == {one: 1, two: 2}

Use Case:

  When getting JSON representations of the model we want to send certain attributes to certain endpoints, and other attributes to other endpoints

Co Authors:
  Keith Cirkel
  Lenny Martin
@bruth
Copy link

bruth commented Aug 19, 2011

I like the idea and could also make use of differentiating data being sent to various endpoints. The one issue here (though one could say it's out of scope) is that nested data (a key points to an object) cannot be whitelisted. That is relatively minor though and for API simplicity sake, it probably shouldn't be added.

From a endpoint perspective, what are your thoughts on using names to reference either an array of whitelisted properties or to handle more dynamic requirements (nested data), a function that returns acts as the pre-processor for the toJSON method.

The typical answer is to override toJSON, but if written correctly, models can be reused (DRY) to target various endpoints depending on the context. I envision something like this contrived example:

var Model = Backbone.Model.extend({
    ...
    endpoint1: ['id', 'foo', 'bar'],
    endpoint2: function() {
        var attrs = _.clone(this.attributes);
        delete attrs['something']['uninteresting']
        attrs['something']['interesting'] = { ... }
        return attrs;
    }
});

var model = new Model;
model.toJSON(); // typical behavior
model.toJSON('endpoint1'); // only 'id', 'foo', 'bar'
model.toJSON('endpoint2'); // uses the endpoint2 method to get the data

Of course the power of this can be coupled with extending the toJSON method to alter the data for all endpoints.

@tbranyen
Copy link
Collaborator

@bruth re: endedpoint2 why would you not just call it explicity?

var model = new Model;
model.endpoint2(); // uses the endpoint2 method to get the data

@bruth
Copy link

bruth commented Aug 19, 2011

Sorry I didn't finish my thought. I could imagine it becoming an option that is passed in to the various CRUD methods specifying the pre-processor/white listed attributes since Backbkne.sync calls toJSON.

model.save({preproc: 'endpoint2'});

(disclaimer: the names I am using are kind of terrible..)

@jashkenas
Copy link
Owner

Yep -- by all means, the right thing to do here is to override toJSON().

@jashkenas jashkenas closed this Aug 19, 2011
@keithamus
Copy link
Contributor Author

I still think the original pull request has validity. Could you tell me why it has been declined?

@jashkenas
Copy link
Owner

Sure -- because it's just as easy, and more flexible, to override toJSON to provide this feature ... either just returning the appropriate attributes, or adding the functionality in this ticket.

90% of the time, you don't need to filter model attributes because you just ignore the ones you don't care about.

@dmitry
Copy link

dmitry commented Oct 14, 2011

What do you think about the case, when there are some dirty attributes that have been changed, but should not be sent to the server after the save method invoke. Right now I've just created method that selects only these attributes that need to be sent right now.

saveAttributes: (attributes, options={}) ->
  data = {}
  _(attributes).each (attribute) =>
    data[attribute] = @get(attribute)

  params =
    data: $.param(data)

  _.extend(params, options)

  Backbone.sync('update', @, params)

But the same method I need to use in other models too. So actually easy to extend other models, but it feels a little dirty, and I guess there are must have something similar like that.

Please let me know any thoughts on that.

Thanks!

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

Successfully merging this pull request may close these issues.

None yet

5 participants