Skip to content

Commit

Permalink
feat(service): adds support for custom relation url name transformation.
Browse files Browse the repository at this point in the history
Closes #159
  • Loading branch information
iobaixas committed Dec 10, 2014
1 parent f787576 commit 5a08092
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 23 deletions.
61 changes: 45 additions & 16 deletions docs/guides/integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ Make sure you read all of the following Q&A before you start integrating your AP
* [Are there any other conventions related to naming I should be aware of?](#q6)
* [How can I set a common url prefix for every resource?](#q7)
* [How can I add a trailing slash or extension to the url sent to server?](#q8)
* [How can I add Ia custom header or parameter to every request?](#q9)
* [How can I add a custom header or parameter to every request?](#q9)
* [I'm getting a 'No API style base was included' warning, what does it mean?](#q10)
* [Can I change the way url names are generated for relations?](#q11)

### <a name="q1"></a> How can I change the property used for the primary key

Expand Down Expand Up @@ -191,22 +192,24 @@ bike = Bike.$find(1).$then(function() {
});
```

To change the property where the inlined resources are located set the JSON_LINKS configuration property or set it to '.' to extract links from root.
To change the property where the inlined resources are located set the `jsonLinks` configuration property or set it to '.' to extract links from root.

```javascript
module.config(function(restmodProvider) {
restmodProvider.rebase(function() {
this.setProperty('jsonLinks', 'links'); // or set JSON_LINKS: 'links' in a definition object.
this.setProperty('jsonLinks', 'links'); // or set jsonLinks: 'links' in a definition object.
});
});
```

Take a look at the default naming stardards, inlined resources are expected to use the **pluralized** names for their respective model names. See. By default the name is extracted from the url, you can change a model's name and plural name by setting the `NAME` and `PLURAL` configuration variables:
Take a look at the default naming stardards, inlined resources are expected to use the **pluralized** names for their respective model names. See. By default the name is extracted from the url, you can change a model's name and plural name by setting the `name` and `plural` configuration variables:

```javascript
restmod.model().$mix(function() {
NAME: 'mouse', // if you only set NAME, then plural is infered from it.
PLURAL: 'mice'
$config: {
name: 'mouse', // if you only set name, then plural is infered from it.
plural: 'mice'
}
});
```

Expand All @@ -219,8 +222,12 @@ You can disable or modify renaming by overriding the following methods:
```javascript
module.config(function(restmodProvider) {
restmodProvider.rebase({
'^encodeName': function(_name) { return _newName; }, // or null to disable renaming.
'^decodeName': function(_name) { return _newName; } // or null to disable renaming.
$extend: {
Model: {
encodeName: function(_name) { return _newName; }, // or null to disable renaming.
decodeName: function(_name) { return _newName; } // or null to disable renaming.
}
}
});
});
```
Expand All @@ -238,14 +245,18 @@ To handle API's that require '$' prefixed properies you have two posibilities:
```javascript
module.config(function(restmodProvider) {
restmodProvider.rebase({
'^decodeName': function(_name) {
// change prefix to '_'
return _name.charAt(0) == '$' ? '_' + inflector.camelize(_name.substr(1), true) : inflector.camelize(_name);
},

'^encodeName': function(_name) {
// change prefix back to '$'
return _name.charAt(0) == '_' ? '$' + inflector.parameterize(_name.substr(1), '_') : inflector.parameterize(_name, '_');
$extend: {
Model: {
decodeName: function(_name) {
// change prefix to '_'
return _name.charAt(0) == '$' ? '_' + inflector.camelize(_name.substr(1), true) : inflector.camelize(_name);
},

encodeName: function(_name) {
// change prefix back to '$'
return _name.charAt(0) == '_' ? '$' + inflector.parameterize(_name.substr(1), '_') : inflector.parameterize(_name, '_');
}
}
}
});
});
Expand Down Expand Up @@ -337,4 +348,22 @@ module.config(function(restmodProvider) {

To see available styles or colaborate with a new one, take a look at the [Style listing](https://github.com/platanus/angular-restmod/blob/master/docs/guides/styles.md).

### <a name="q11"></a> Can I change the way url names are generated for relations?

Yes you can, just override the `Model.encodeUrlName` method to provide custom name transformation, like this:

```javascript
module.config(function(restmodProvider) {
restmodProvider.rebase({
$extend: {
Model: {
encodeUrlName: function(_name) {
return _name.toLowerCase();
}
}
}
});
});
```

Transformations will be applied to relations where the extended model is referenced.
4 changes: 2 additions & 2 deletions src/module/extended/builder-relations.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ RMModule.factory('RMBuilderRelations', ['$injector', 'inflector', '$log', 'RMUti
}
}

var scope = this.$buildScope(_model, _url || inflector.parameterize(_attr)), col; // TODO: name to url transformation should be a Model strategy
var scope = this.$buildScope(_model, _url || _model.encodeUrlName(_attr)), col;

// setup collection
col = _model.$collection(_params || null, scope);
Expand Down Expand Up @@ -140,7 +140,7 @@ RMModule.factory('RMBuilderRelations', ['$injector', 'inflector', '$log', 'RMUti
}
}

var scope = this.$buildScope(_model, _url || inflector.parameterize(_attr)), inst;
var scope = this.$buildScope(_model, _url || _model.encodeUrlName(_attr)), inst;

// setup record
inst = _model.$new(null, scope);
Expand Down
24 changes: 21 additions & 3 deletions src/module/factory.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use strict';

RMModule.factory('RMModelFactory', ['$injector', 'inflector', 'RMUtils', 'RMScopeApi', 'RMCommonApi', 'RMRecordApi', 'RMListApi', 'RMCollectionApi', 'RMExtendedApi', 'RMSerializer', 'RMBuilder',
function($injector, inflector, Utils, ScopeApi, CommonApi, RecordApi, ListApi, CollectionApi, ExtendedApi, Serializer, Builder) {
RMModule.factory('RMModelFactory', ['$injector', '$log', 'inflector', 'RMUtils', 'RMScopeApi', 'RMCommonApi', 'RMRecordApi', 'RMListApi', 'RMCollectionApi', 'RMExtendedApi', 'RMSerializer', 'RMBuilder',
function($injector, $log, inflector, Utils, ScopeApi, CommonApi, RecordApi, ListApi, CollectionApi, ExtendedApi, Serializer, Builder) {

var NAME_RGX = /(.*?)([^\/]+)\/?$/,
extend = Utils.extendOverriden;
Expand Down Expand Up @@ -334,7 +334,25 @@ RMModule.factory('RMModelFactory', ['$injector', 'inflector', 'RMUtils', 'RMScop
* @params {string} _name Record name
* @return {string} Response (raw) name
*/
encodeName: null
encodeName: null,

/**
* @memberof StaticApi#
*
* @description The model name to url encoding strategy
*
* This method is called when translating a name into an url fragment (mainly by relations).
*
* By default it uses the `inflector.parameterize` method, in 1.2 this will change and the default
* behaviour will be to do nothing.
*
* @params {string} _name local name
* @return {string} url fragment
*/
encodeUrlName: function(_name) {
$log.warn('Default paremeterization of urls will be disabled in 1.2, override Model.encodeUrlName with inflector.parameterize in your base model to keep the same behaviour.');
return inflector.parameterize(_name);
}

}, ScopeApi);

Expand Down
3 changes: 2 additions & 1 deletion src/styles/ams.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ angular.module('restmod').factory('AMSApi', ['restmod', 'inflector', function(re
// special snakecase to camelcase renaming
Model: {
decodeName: inflector.camelize,
encodeName: function(_v) { return inflector.parameterize(_v, '_'); }
encodeName: function(_v) { return inflector.parameterize(_v, '_'); },
encodeUrlName: inflector.parameterize
}
}
});
Expand Down
7 changes: 6 additions & 1 deletion test/styles/ams-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ describe('Style: AMS', function() {
restmodProvider.rebase('AMSApi');
$provide.factory('Bike', function(restmod) {
return restmod.model('/api/bikes', {
user: { belongsTo: restmod.model('/api/users') }
user: { belongsTo: restmod.model('/api/users') },
allUsers: { hasMany: restmod.model('/api/users') }
});
});
}));
Expand All @@ -33,6 +34,10 @@ describe('Style: AMS', function() {
expect(bike.$pk).toEqual(1);
});

it('should properly encode url names using lowercase and dashes', function() {
expect(bike.$decode({ id: 1 }).allUsers.$url()).toEqual('/api/bikes/1/all-users');
});

it('should extract metadata from "meta" property', function() {
bike.$unwrap({ bike: { id: 1 }, meta: { date: '2014-05-01' } });
expect(bike.$metadata).toBeDefined();
Expand Down

0 comments on commit 5a08092

Please sign in to comment.