Skip to content

Commit

Permalink
Merge pull request #1 from truenorth/use-adapter
Browse files Browse the repository at this point in the history
Use ember-data adapter for ajaxOptions and ajax
  • Loading branch information
mike-north committed Jul 6, 2015
2 parents f7a3cc3 + 5c1dc9a commit be3e3c2
Show file tree
Hide file tree
Showing 8 changed files with 80 additions and 44 deletions.
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,18 @@ myRecord.ripen({

```

## Customization

ember-api-actions generates URLs and ajax configuration via ember-data adapters. It will identify the appropriate adapter, and call the `buildURL` and `ajaxOptions` methods to send a JSON request similar to way conventional ember-data usage works.

Customizing your adapter should customize requests sent out via this library, along with any other ember-data requests.

**ember-api-actions uses the following methods on DS.Adapter**

* [buildURL](http://emberjs.com/api/data/classes/DS.RESTAdapter.html#method_buildURL) - for generating an action's URL
* [ajaxOptions](https://github.com/emberjs/data/blob/v1.13.4/packages/ember-data/lib/adapters/rest-adapter.js#L928-L950) (private) - so that consumers may customize ajax options (i.e., `xhrFields`) in a single place
* [ajax](https://github.com/emberjs/data/blob/v1.13.4/packages/ember-data/lib/adapters/rest-adapter.js#L836-L859) (private) - to actually make the API request and return a promise

## Installation

* `git clone` this repository
Expand Down
23 changes: 8 additions & 15 deletions addon/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import Ember from 'ember';
import ajax from 'ic-ajax';

const buildOperationUrl = function buildOperationUrl(record, opPath, requestType, intance=true) {
Ember.assert('You must provide a path for instanceOp', opPath);
Expand All @@ -13,28 +12,22 @@ const buildOperationUrl = function buildOperationUrl(record, opPath, requestType
export const instanceOp = function instanceOp(options) {
return function(payload) {
let requestType = options.type || 'PUT';
let modelName = this.constructor.modelName;
let adapter = this.store.adapterFor(modelName);
let fullUrl = buildOperationUrl(this, options.path, requestType);
return ajax(Ember.$.extend(options.ajaxOptions || {}, {
type: requestType,
url: fullUrl,
contentType: 'application/json',
dataType: 'json',
data: JSON.stringify(payload)
}));
let ajaxOptions = adapter.ajaxOptions(fullUrl, requestType, { data: payload });
return adapter.ajax(fullUrl, requestType, Ember.$.extend(options.ajaxOptions || {}, ajaxOptions));
};
};

export const classOp = function instanceOp(options) {
return function(payload) {
let requestType = options.type || 'PUT';
let modelName = this.constructor.modelName;
let adapter = this.store.adapterFor(modelName);
let fullUrl = buildOperationUrl(this, options.path, requestType, false);
return ajax(Ember.$.extend(options.ajaxOptions || {}, {
type: requestType,
url: fullUrl,
contentType: 'application/json',
dataType: 'json',
data: JSON.stringify(payload)
}));
let ajaxOptions = adapter.ajaxOptions(fullUrl, requestType, { data: payload });
return adapter.ajax(fullUrl, requestType, Ember.$.extend(options.ajaxOptions || {}, ajaxOptions));
};
};

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ember-api-actions",
"version": "0.0.1",
"version": "0.0.2",
"description": "Trigger remote actions that don't fit into CRUD, in your Ember.js apps",
"directories": {
"doc": "doc",
Expand Down
2 changes: 2 additions & 0 deletions tests/dummy/app/controllers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export default Ember.Controller.extend({
this._super(...arguments);
this.set('requests', Ember.A());
},
// BEGIN-SNIPPET controller
actions: {
ripenFruit(fruit) {
fruit.ripen({
Expand All @@ -17,4 +18,5 @@ export default Ember.Controller.extend({
});
}
}
// END-SNIPPET
});
4 changes: 4 additions & 0 deletions tests/dummy/app/styles/app.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
.payload {
margin-left: 30px;
}

.m-t-40 {
margin-top: 40px;
}
10 changes: 9 additions & 1 deletion tests/dummy/app/templates/application.hbs
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@

<div class="container">
<h2 id="title">Ember api actions</h2>
<div class="row">
<div class="col m8 s12">
<h2 id="title">Ember api actions</h2>
</div>
<div class="col m4 s12">
<a href="https://github.com/truenorth/ember-api-actions" class="btn btn-flat black white-text m-t-40" target="_blank">Go to Github</a>
</div>
</div>

{{outlet}}
</div>
56 changes: 33 additions & 23 deletions tests/dummy/app/templates/index.hbs
Original file line number Diff line number Diff line change
@@ -1,23 +1,33 @@
<h3>API actions on an individual resource</h3>
{{#each content as |fruit|}}
<p class='fruit-thing' {{bind-attr id=fruit.name}}>
{{fruit.id}} {{fruit.name}}
<button class='btn ripen-instance-button' {{action 'ripenFruit' fruit}}>Ripen</button> - calls <code>fruit.ripen()</code>
</p>

{{/each}}
<h3>API action on a collection of resources</h3>
<p class='all-fruit'>
{{content.constructor.modelName}}
<button class='btn ripen-type-button' {{action 'ripenAllFruit' content.firstObject}}>Ripen All</button> - calls <code>fruit.ripenAll()</code>
</p>


{{code-snippet name='fruit-model.js'}}

<h5>Outgoing API Requests:</h5>
<ul>
{{#each requests as |req|}}
<li> <code>{{req.url}}</code> <code class='payload'>{{json-string req.data}}</code></li>
{{/each}}
</ul>
<div class="row">
<div class="col m6 s12">
<h4>API actions on an individual resource</h4>
{{#each content as |fruit|}}
<p class='fruit-thing' {{bind-attr id=fruit.name}}>
<button class='btn ripen-instance-button' {{action 'ripenFruit' fruit}}>Ripen</button>
{{fruit.name}} (id = {{fruit.id}})
- calls <code>fruit.ripen()</code>
</p>
{{/each}}
<h4>API action on a collection of resources</h4>
<p class='all-fruit'>
{{content.constructor.modelName}}
<button class='btn ripen-type-button' {{action 'ripenAllFruit' content.firstObject}}>Ripen All</button> - calls <code>fruit.ripenAll()</code>
</p>
</div>
<div class="col m6 s12">
<h4>Outgoing API Requests:</h4>
<ul>
{{#each requests as |req|}}
<li> <code>{{req.url}}</code> </li>
{{/each}}
</ul>
</div>
</div>
<div class="row">
<div class="col s12">
<b>app/models/fruit.js</b>
{{code-snippet name='fruit-model.js'}}
<b>app/controllers/index.js</b>
{{code-snippet name='controller.js'}}
</div>
</div>
15 changes: 11 additions & 4 deletions tests/dummy/config/environment.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@ module.exports = function(environment) {
// e.g. 'with-controller': true
}
},
contentSecurityPolicy: {
'img-src': '*',
'connect-src': '*',
'font-src': '*',
'script-src': '\'unsafe-inline\' *',
'style-src': '\'unsafe-inline\' *'
},

APP: {
// Here you can pass flags/options to your application instance
Expand Down Expand Up @@ -39,10 +46,10 @@ module.exports = function(environment) {
ENV.APP.rootElement = '#ember-testing';
}

if (environment === 'development') {
ENV.locationType = 'hash';
ENV.baseURL = 'ember-api-actions/';
}
// if (environment === 'development') {
// ENV.locationType = 'hash';
// ENV.baseURL = 'ember-api-actions/';
// }

return ENV;
};

0 comments on commit be3e3c2

Please sign in to comment.