Security News
Input Validation Vulnerabilities Dominate MITRE's 2024 CWE Top 25 List
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
ampersand-collection
Advanced tools
A way to store/manage objects or models.
Unlike other tools this makes no assumptions about how it's going to be used or what type of models it is going to contain. This makes it a very flexible/useful tool for modeling all kinds of stuff.
It does not require underscore or jQuery, but instead makes it easy to extend with those methods if you'd like.
Part of the Ampersand.js toolkit for building clientside applications.
npm i ampersand-collection
The collection is a fairly low-level tool, in that it's useful for any time you want to be able to store JS objects in an array.
In many ways it's simply an observable array of objects.
It emits add
, remove
events and makes it possible to merge in a set of objects into an existing collection and emit change events appropriately.
If you extend it with a .model
property that contains a constructor, the collection will ensure that objects that don't match that constructor are instantiated before being added to the collection.
For example:
var Collection = require('ampersand-collection');
// can just store plain objects
var basicCollection = new Collection([
{name: 'larry'},
{name: 'curly'},
{name: 'moe'}
]);
Adding ampersand-collection-rest-mixin and ampersand-collection-underscore-mixin.
var Collection = require('ampersand-collection');
var restMixin = require('ampersand-collection-rest-mixin');
var underscoreMixin = require('ampersand-collection-underscore-mixin');
// or we can extend it with underscore and REST methods
// to turn it into something similar to a Backbone Collection
var RestfulCollection = Collection.extend(underscoreMixin, restMixin, {
url: '/mystuff'
});
var collection = new RestfulCollection();
// does ajax request
collection.fetch();
With npm and browserify for module deps you can sometimes end up with a situation where, the same collection
constructor wasn't used to build a collection
object. As a result instanceof
checks will fail.
In order to deal with this (because sometimes this is a legitimate scenario), collection
simply creates a read-only isCollection
property on all collection objects that can be used to check whether or a not a given object is in fact a collection object no matter what its constructor was.
AmpersandCollection.extend([attributes])
Create a collection class of your own by extending AmpersandCollection, providing the required instance properties to be attached instances of your class.
Typically you will specify a model
constructor (if you are storing ampersand-state or ampersand-model objects.
collection.model
Override this property to specify the model class that the collection contains. If defined, you can pass raw attributes objects (and arrays) to add
and reset
, and the attributes will be converted into a model of the proper type.
var Library = AmeprsandCollection.extend({
model: Book
});
A collection can also contain polymorphic models by overriding this property with a function that returns a model.
var Library = Backbone.Collection.extend({
model: function(attrs, options) {
if (condition) {
return new PublicDocument(attrs, options);
} else {
return new PrivateDocument(attrs, options);
}
}
});
new AmpersandCollection([models], [options])
When creating an AmpersandCollection, you may choose to pass in the initial array of models. The collection's comparator may be included as an option. Passing false
as the comparator option will prevent sorting. If you define an initialize function, it will be invoked when the collection is created. There are a couple of options that, if provided, are attached to the collection directly: model
and comparator
.
var people = new AmpersandCollection([{ name: 'phil' }, { name: 'bob' }, { name: 'jane' }], {
model: Person
});
Specify which key on your models should be used as their main unique identifier. Defaults to id
. This is the default key that get
will use to retrieve models by, as well as the key add/set/remove will compare to determine whether a model exists in the collection or not.
If your server does not use id
as the model identifier, you would typically override this when extending AmpersandCollection, like so:
var People = AmpersandColletion.extend({
mainIndex: '_id'
});
collections.indexes
Specify an optional array of keys by which to additionally index the models in your collection (in addition to the mainIndex
. This allows you to quickly retrieve models by specifying the key to use with get.
Note that get
will only ever return a single model, so the values of these indexes should be unique across the models in the collection:
var People = AmpersandCollection.extend({
mainIndex: '_id',
indexes: ['otherId']
});
var people = new People.add([
{ _id: 1, otherId: 'a', name: 'Phil' },
{ _id: 2, otherId: 'b', name: 'Julie' },
{ _id: 3, otherId: 'c', name: 'Henrik' },
{ _id: 4, otherId: 'd', name: 'Jenn' }
]);
people.get(1) //=> { _id: 1, otherId: 'a', name: 'Phil' }
people.get('b', 'otherId') //=> { _id: 2, otherId: 'b', name: 'Julie' },
collection.length
Returns the length of the underlying array.
collection.isCollection
With npm and browserify for module deps you can sometimes end up with a situation where, the same collection
constructor wasn't used to build a collection
object. As a result instanceof
checks will fail.
In order to deal with this (because sometimes this is a legitimate scenario), collection
simply creates a read-only isCollection
property on all collection objects that can be used to check whether or a not a given object is in fact a collection object no matter what its constructor was.
collection.add(modelOrObject, [options])
Add a model (or an array of models) to the collection, firing an "add"
event. If a model property is defined, you may also pass raw attributes objects, and have them be vivified as instances of the model. Returns the added (or preexisting, if duplicate) models.
Options:
{at: index}
to splice the model into the collection at the specified index.{merge: true}
, in which case their attributes will be merged into the corresponding models, firing any appropriate "change"
events.var ships = new AmpersandCollection();
ships.on("add", function(ship) {
console.lg("Ahoy " + ship.name + "!");
});
ships.add([
{name: "Flying Dutchman"},
{name: "Black Pearl"}
]);
//logs:
//- "Ahoy Flying Dutchman!"
//- "Ahoy Black Pearl!"
Note that adding the same model (a model with the same id) to a collection more than once is a no-op.
collection.serialize()
Serialize the collection into a plain javascript array, ready for sending to the server (typically called via toJSON). Will also call serialize()
on each model in the collection.
collection.toJSON()
Returns a plain javascript array of the models in the collection (which are also serialized) ready for sending to the server. The name of this method is a bit confusing, as it doesn't actually return a JSON string — but I'm afraid that it's the way that the JavaScript API for JSON.stringify works.
var collection = new AmpersandCollection([
{name: "Tim", age: 5},
{name: "Ida", age: 26},
{name: "Rob", age: 55}
]);
console.log(JSON.stringify(collection));
//=> "[{\"name\":\"Tim\",\"age\":5},{\"name\":\"Ida\",\"age\":26},{\"name\":\"Rob\",\"age\":55}]"
collection.set(models, [options])
The set method performs a "smart" update of the collection with the passed list of models. If a model in the list isn't yet in the collection it will be added; if the model is already in the collection its attributes will be merged; and if the collection contains any models that aren't present in the list, they'll be removed. All of the appropriate "add"
, "remove"
, and "change"
events are fired as this happens. Returns the touched models in the collection. If you'd like to customize the behavior, you can disable it with options: {add: false}
, {remove: false}
, or {merge: false}
.
var vanHalen = new AmpersandCollection([eddie, alex, stone, roth]);
vanHalen.set([eddie, alex, stone, hagar]);
// Fires a "remove" event for roth, and an "add" event for "hagar".
// Updates any of stone, alex, and eddie's attributes that may have
// changed over the years.
collection.get(query, [indexName])
Retrieve a model from the collection by index.
With an unspecified indexName
(collection.get(123)
) retrieves the model by it's mainIndex attribute.
Or specify an indexName
to retrieve a model by any of the other listed indexes.
var People = AmpersandCollection.extend({
mainIndex: '_id',
indexes: ['otherId']
});
var people = new People.add([
{ _id: 1, otherId: 'a', name: 'Phil' },
{ _id: 2, otherId: 'b', name: 'Julie' },
{ _id: 3, otherId: 'c', name: 'Henrik' },
{ _id: 4, otherId: 'd', name: 'Jenn' }
]);
people.get(1) //=> { _id: 1, otherId: 'a', name: 'Phil' }
people.get('b', 'otherId') //=> { _id: 2, otherId: 'b', name: 'Julie' },
collection.at(index)
Get a model from a collection, specified by index. Useful if your collection is sorted, and if your collection isn't sorted, at will still retrieve models in insertion order.
e.g. collection.at(0)
returns the first model in the collection.
collection.remove(models, [options])
Remove a model (or an array of models) from the collection, and returns them. Fires a "remove"
event, which you can use { silent: true }
to suppress. The model's index before removal is available to listeners as options.index
.
The models object/array can be references to actual models, or just a list of ids to remove.
collection.reset(models, [options])
Adding and removing models one at a time is all well and good, but sometimes you have so many models to change that you'd rather just update the collection in bulk. Use reset to replace a collection with a new list of models (or attribute hashes), triggering a single "reset"
event at the end. Returns the newly-set models. For convenience, within a "reset"
event, the list of any previous models is available as options.previousModels
.
Calling collection.reset()
without passing any models as arguments will empty the entire collection.
collection.sort([options])
Force a collection to re-sort itself. You don't need to call this under normal circumstances, as a collection with a comparator will sort itself whenever a model is added. To disable sorting when adding a model, pass {sort: false}
to add. Calling sort triggers a "sort"
event on the collection.
collection.models
Raw access to the JavaScript array of models inside of the collection. Usually you'll want to use get
, at
, or the proxied array methods to access model objects, but occasionally a direct reference to the array is desired.
The base AmpersandCollection proxies some basic ES5 methods to the underlying model array. Further documentation of these methods is available at MDN
Unlike a backbone collection it does not include underscore and all the array methods from underscore, though if you wish more functions than those built into modern browsers, you can mixin ampersand-collection-underscore-mixin to get them.
var people = People([
{ name: 'Phil', hatColor: 'red' },
{ name: 'Jenn', hatColor: 'green' },
{ name: 'Henrik', hatColor: 'blue' },
{ name: 'Julie', hatColor: 'yellow' }
]);
people.map(function (person) { return person.name; }) //=> ['Phil', 'Jenn', 'Henrik', 'Julie']
people.filter(function (person) {
return person.name[0] === 'J';
}) //=> ['Jenn', 'Julie']
Created by @HenrikJoreteg but many ideas and some code (especially for the set
) methods should be credited to Jeremy Ashkenas and the rest of the Backbone.js authors.
MIT
FAQs
A way to store/manage objects or models.
The npm package ampersand-collection receives a total of 18,295 weekly downloads. As such, ampersand-collection popularity was classified as popular.
We found that ampersand-collection demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 7 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
Security News
In this segment of the Risky Business podcast, Feross Aboukhadijeh and Patrick Gray discuss the challenges of tracking malware discovered in open source softare.
Research
Security News
A threat actor's playbook for exploiting the npm ecosystem was exposed on the dark web, detailing how to build a blockchain-powered botnet.