0

In my app I had BlogPost model and User model that are related through relation named author. To serve data from my Rails app I use active_model_serializers with definition:

class Blog::PostSerializer < ActiveModel::Serializer
  embed :ids, include: true

  attributes :id, :title, :text, :created_at, :updated_at

  has_one :author
  has_many :assets
end

When I fetch this using Ember model:

Admin.BlogPost = DS.Model.extend({
  author:     DS.belongsTo('User'),

  title:      DS.attr('string'),
  text:       DS.attr('string'),
  createdAt:  DS.attr('date'),
  updatedAt:  DS.attr('date')
});

There is an error:

Uncaught Error: Assertion Failed: You looked up the 'author' relationship on a 'blog.post' with id 1 but some of the associated records were not loaded. Either make sure they are all loaded together with the parent record, or specify that the relationship is async (`DS.belongsTo({ async: true })`)

Which is caused by that my response looks like:

{
  'blog_posts': [
    {
      id: 1,
      author_id: 1
    },
    // …
  ],
  'authors': [
    { id: 1, /* … */ }
  ]
}

Is there any way to change 'authors' in response to 'users' or use 'authors' as alias to 'users' in serializer?

artych
  • 3,669
  • 1
  • 17
  • 30
Hauleth
  • 22,873
  • 4
  • 61
  • 112

2 Answers2

1

From active_model_serializers 0.8 description: https://github.com/rails-api/active_model_serializers/tree/0-8-stable

You can also specify a different root for the embedded objects than the key used to reference them:

class PostSerializer < ActiveModel::Serializer
  embed :ids, :include => true

  attributes :id, :title, :body
  has_many :comments, :key => :comment_ids, :root => :comment_objects
end

This would generate JSON that would look like this:

{"post": {
    "id": 1,
    "title": "New post",
    "body": "A body!",
    "comment_ids": [ 1 ]
 },
 "comment_objects": [
  { "id": 1, "body": "what a dumb post" }
 ]
}
artych
  • 3,669
  • 1
  • 17
  • 30
  • I know, but why making additionals fetch when everything can be fetched in just one. I send that data, but Ember doesn't recognise it as it use another key than expected. – Hauleth Jun 09 '15 at 14:20
  • You are mixing different questions. Async doesn't mean to fetch in just one or not. And in your payload `authors` **after** `blog_posts` looks good. But **inside** `blog_posts` you use `author_id` (not embed full `author`), so you must set {async: true}. – artych Jun 09 '15 at 14:25
  • I've checked that, and it isn't what I mean. `async` mean that it will make subrequest for each requested item (when and if needed). What I want is that Ember will use data that currently is in payload to fetch info about `User`s. – Hauleth Jun 09 '15 at 14:30
  • Oh, I understand you. I will delete answer. Sorry about that. – artych Jun 09 '15 at 14:53
0

Just define a method in your serializer named users and return authors in it I.e.

attributes :id, :title, :text, :created_at, :updated_at, :users

def users
  object.authors
end
nesiseka
  • 1,268
  • 8
  • 22
  • Article has one author, also I want it to be named `author` (as article has author not user). – Hauleth Jun 09 '15 at 13:27
  • Well, whatever structure you want you can do it in a method: `def author ... end` or `def author_id ... end`, just add the method to attributes and you'll have whatever namespace you want. – nesiseka Jun 09 '15 at 13:30
  • But then response will have invalid structure. I just want to use data that is in payload to load `User`s. – Hauleth Jun 09 '15 at 15:01