最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Non CRUD actions with ember-data - Stack Overflow

programmeradmin3浏览0评论

Say I have the following ember-data model:

App.Person = DS.Model.extend({
    firstName: DS.attr('string'),
    lastName:  DS.attr('string'),
    starred:   DS.attr('boolean')
});

This municates with a Rails app with the following pretty standard CRUD API:

GET    /people    - get a list of people
POST   /people    - create a new person
GET    /people/id - get a specific person
PUT    /people/id - update a specific person
DELETE /people/id - delete a specific person

This all maps to Ember-Data with the standard Store/Adapter.

However, lets say that in order to "star" or "unstar" a person, the API doesn't let us do this by the standard update action. There's a specific API endpoint for this action:

POST   /people/id/star   - mark a person as "starred"
POST   /people/id/unstar - mark a person as "unstarred"

How do I fit this API in with Ember Data?

It looks like I'd need to extend DS.Store and DS.RESTAdapter somehow, but I'm not sure of the best approach to make them aware of these different actions. It also feels a bit wrong that a generic Adapter for the app has to be aware of starring people.

Note that I have no control over the API, so I can't make POST /people/id aware of "starring" so that it would fit in with a standard update.

Say I have the following ember-data model:

App.Person = DS.Model.extend({
    firstName: DS.attr('string'),
    lastName:  DS.attr('string'),
    starred:   DS.attr('boolean')
});

This municates with a Rails app with the following pretty standard CRUD API:

GET    /people    - get a list of people
POST   /people    - create a new person
GET    /people/id - get a specific person
PUT    /people/id - update a specific person
DELETE /people/id - delete a specific person

This all maps to Ember-Data with the standard Store/Adapter.

However, lets say that in order to "star" or "unstar" a person, the API doesn't let us do this by the standard update action. There's a specific API endpoint for this action:

POST   /people/id/star   - mark a person as "starred"
POST   /people/id/unstar - mark a person as "unstarred"

How do I fit this API in with Ember Data?

It looks like I'd need to extend DS.Store and DS.RESTAdapter somehow, but I'm not sure of the best approach to make them aware of these different actions. It also feels a bit wrong that a generic Adapter for the app has to be aware of starring people.

Note that I have no control over the API, so I can't make POST /people/id aware of "starring" so that it would fit in with a standard update.

Share Improve this question edited Feb 26, 2015 at 17:14 Kalman 8,1311 gold badge28 silver badges45 bronze badges asked Mar 14, 2012 at 16:17 rlivseyrlivsey 2,1342 gold badges18 silver badges21 bronze badges 1
  • Could you accept my answer? The currently accepted one is no longer accurate – andorov Commented Mar 5, 2015 at 23:37
Add a ment  | 

5 Answers 5

Reset to default 10

Been a while and it may not have been possible at the time, but you can call the ajax method of your adapter directly:

YourApp.Store.prototype.adapter.ajax(url, action, {data: hashOfParams})

For example:

YourApp.Store.prototype.adapter.ajax('/products', 'GET', {data: {ids: [1,2,3]}})

For your question:

YourApp.Store.prototype.adapter.ajax('/people' + id + '/star','POST')

Edit - using buildURL is useful, particularly if you've set a namespace on your adapter:

url = YourApp.Store.prototype.adapter.buildURL('people',id) + '/star'

Edit 2 - You can also get the adapter with container.lookup('adapter:application'), which is useful if you don't have global access to the app (ex ES6 modules / ember-cli)

Edit 3 - The above refers to an outdated version of Ember / Ember-CLI. Now I define this function in a mixin -

  customAjax: (method, type, id, action, hash = null) ->
    #note that you can now also get the adapter from the store -
    #adapter = @store.adapterFor('application')
    adapter = @container.lookup('adapter:application')
    url = adapter.buildURL(type, id) + '/' + action
    hash['data'] = $.extend({}, hash) if hash #because rails
    adapter.ajax(url, method, hash).then (result) =>
      return result

And call it like so -

@customAjax('PUT', 'modelClass', modelId, 'nonCRUDActionName', optionalHashOfAdditionalData).then (response) =>
  #do something with response

I went through the same issue, and solved it using a modified version of what is explained in here: Non-crud rails actions in Ember.js

Basically, you need to use a Jquery AJAX call, the important part for me was to change the contentType in order to get the auth data to be sent in the request headers, rather than in form-data (the default, if you include data in your call). Also, make sure to give the proper context in the AJAX part, otherwise 'this' won't work in the 'success' callback:

App.ItemController = Ember.ObjectController.extend
    actions:
        starItem: ->
            controller = this
            item = @get 'model'
            id = item.id
            token = @auth.get 'authToken'
            $.ajax
                type: 'PUT'
                context: controller
                data: '{ "auth_token": "' + token + '"}'
                url: '/api/v1/items/' + id + '/star'
                contentType: 'application/json; charset=UTF-8'
                dataType: 'json'
                success: ->
                    if @get 'item.starred_by_user'
                        @set 'model.starred_by_user', false
                        item.decrementProperty('total_stars') 
                    else 
                        @set 'model.starred_by_user', true
                        item.incrementProperty('total_stars')

Maybe a good start: https://github./beautifulnode/ember.request

Did not tryed it yet, but seems promising in your case...

I think, that in CQRS therms star and unstar are mands. So you should declare model PersonStar and work with it.

In the discussion group, Yehuda mentioned this isn't possible yet.

发布评论

评论列表(0)

  1. 暂无评论