0

From my Emberjs I am making a custom request to an explore route on my Rails server:

GET http://localhost:3000/explore

I see my JSON response in my Google Chrome network inspector, however, my page isn't rendering anything.

To make the custom request, I have a book adapter:

Book Adapter

import ApplicationAdapter from './application';
import Ember from 'ember';

export default ApplicationAdapter.extend({
  apiManager: Ember.inject.service(),

  findPublishedBooks: function(store, type) {
    let jwt = this.get('apiManager').get('jwt');

    return Ember.RSVP.resolve(
      Ember.$.ajax({
        type: "GET",
        url: this.get('apiManager').requestURL('explore'),
        dataType: 'json',
        headers: {"Authorization": "Bearer " + jwt}
      })
    );
  }
});

Explore Route

model() {
  const adapter = this.get('store').adapterFor('book');
  return adapter.findPublishedBooks();
}

On my Rails side, I have this for my Explore action:

Rails Explore Action

def explore
  books = Book.where(published: true)

  if books.count > 0
    render json: books
  else
    return nil
  end
end

I know I must be doing something wrong, probably on my Ember side.

Update

Explore template

<div class="explore">
  {{#search-field searchAction=(action "searchBooks") clearAction=(action "clearSearchBooks")}}{{/search-field}}
  {{#book-grid books=model class="book-grid" isSearching=isSearching}}{{/book-grid}}
</div>

Book-Grid Template

{{#each books as |book|}}
  {{#link-to "books.book" book}}
    <div class="book">
      <div class="book-cover">
        <img src={{book.cover.cover.url}} alt="{{book.title}} book cover image" width=173 height=231>
      </div>
      <div class="caption">
        {{book.title}}<br>
        <label>by {{book.author.username}}</label>
      </div>
    </div>
  {{/link-to}}
{{else}}
  {{#if isSearching}}
    <label>No search results.</label>
  {{else}}
    <label>There are no published books at the moment.</label>
  {{/if}}
{{/each}}
4
  • Show your template. Also you realize that you never push the data to the store? Have you considered to use query instead? Usually you shouldn't manually call functions on your adapter. Commented Dec 15, 2016 at 14:20
  • I have updated my question with the template. Sorry, new to Ember, not sure what I am doing. I have to push to store ? Maybe you know of a better way to achieve what I need? Commented Dec 15, 2016 at 14:29
  • Hm, what exactly should findPublishedBooks do? Return like a filtered list of books? Like all books with published:true? Commented Dec 15, 2016 at 14:37
  • Yes, findPublishedBooks should ask my Rails server to return all books that are published. My Rails route for that is http://localhost:3000/explore which returns a list of books that are published. Commented Dec 15, 2016 at 14:38

1 Answer 1

1

I think you need to understand that with your code you basically work around the ember-data store. For ember-data to work you have to keep all your data in the store, which means you can't just manually call your adapter. You always have to call the store, and the store will call the adapter.

So this is an anti pattern:

const adapter = this.get('store').adapterFor('book');
return adapter.findPublishedBooks();

Because it won't push the data to the store, or serialize them.

What you instead should do is to use the query function on the store.

You can call store.query('myModel', anything) if you want a server-side filtered list. The second variable will directly be passed to the adapter.

So you would call return store.query('book', { published:true }) in your route, and then implement it in your BookAdapter with something like this:

apiManager: Ember.inject.service(),

query: function(store, type, query) {
  if(query.published) {
    let jwt = this.get('apiManager').get('jwt');

    return Ember.RSVP.resolve(
      Ember.$.ajax({
        type: "GET",
        url: this.get('apiManager').requestURL('explore'),
        dataType: 'json',
        headers: {"Authorization": "Bearer " + jwt}
      })
    );
  }
}

Also make sure you return the right data structure. ember-data expects a JSONAPI response, unless you changed that in your serializer.

Sign up to request clarification or add additional context in comments.

2 Comments

Well that certainly works. It seems like when overriding the adapter methods, they do more than what's visible in the above code block. I previously assumed I could just apply the same code to whatever adapter function I happen to define and call the return adapter.customFunction(); and it would magically work, I guess that was an incorrect assumption.
Yes. Well, the point is that you don't call the adapter but the store, and the store processes the result of the adapter function with the serializer, then stores it, and finally returns instances of models. when you manually call the adapter you loose this layer, so you just get the plain AJAX-response. Even when the functions on the store and the adapter are named identically because of sanity, they are not the same! The don't even have the same parameters.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.