In a Ruby 2/Rails 4 app, I am trying to use acts-as-taggable-on in conjunction with active_model_serializers in order to create a JSON API that would output my tags along with other model parameters.
First some background/motivation for this issue: The JSON is being fed into ember/ember-data, which as of the time of this writing has removed support for embedded records in JSON. There is a supposed fix in the documentation about this, but I find it clumsy and also haven't actually gotten it to work. Since I'm an Ember newbie and am a little more comfortable with Rails, I figure I'll try to solve the problem another way, by sideloading the tag record alongside the document record. I like this solution better because it makes more sense for my application, but I can't get this to work either.
Here's an example: Let's say I have a Document model that is using acts-as-taggable-on:
class Document < ActiveRecord::Base
acts_as_taggable
# other code omitted
I've set up the database with one document with one tag. Now we consider the following cases:
1. Full Object Embed: With the following serializer:
class DocumentSerializer < ActiveModel::Serializer
attributes :id
has_many :tags
My JSON has the following format (using Rails 4 UUIDs):
{
"documents": [
{
"id": "c41460fa-2427-11e3-8702-0800270f33f4",
"tags": [
{
"id": "a33fc396-2428-11e3-8eeb-0800270f33f4",
"name": "test"
}
]
}
]
}
2. ID Embed: Using the serializer
class DocumentSerializer < ActiveModel::Serializer
attributes :id
has_many :tags, embed: :id
My JSON now looks like:
{
"documents": [
{
"id": "c41460fa-2427-11e3-8702-0800270f33f4",
"tag_ids": [
"a33fc396-2428-11e3-8eeb-0800270f33f4"
]
}
]
}
3. ID Embed with Tags Sideloaded: According to active_model_serializers documentation, I should be able to do
class DocumentSerializer < ActiveModel::Serializer
attributes :id
has_many :tags, embed: :id, include: true
but this doesn't work. Instead, I get a NoMethodError:
undefined method `object' for #<ActsAsTaggableOn::Tag:0x007f258cf1db38>
I've tried searching for this problem but haven't found anything useful so far. I also couldn't find any documentation on either gem regarding usage with the other gem. My suspicion right now that it has something to do with how acts-as-taggable-on is implemented, that it's not a straightforward has_many relationship? Is anybody able to offer some input on this issue? Thanks in advance!
Fixed! Turns out to sideload the tags, the corresponding serializer must be defined. I did not know this, because the documentation seems to imply that having a serializer is optional, and some default will be used in the absence of one. Apparently this is not the case if you wish to use the include: true
option. Key in sight came from here, thanks very much!
For completeness, I'll show what I did. I created tag_serializer.rb
with the following code:
module ActsAsTaggableOn
class TagSerializer < ActiveModel::Serializer
attributes :id, :name
end
end
and now my JSON:
{
"tags": [
{
"id": "a33fc396-2428-11e3-8eeb-0800270f33f4",
"name": "test"
}
],
"documents": [
{
"id": "c41460fa-2427-11e3-8702-0800270f33f4",
"tag_ids": [
"a33fc396-2428-11e3-8eeb-0800270f33f4"
]
}
]
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With