Skip to content

Instantly share code, notes, and snippets.

@cadwallion
Created April 30, 2012 01:37
Show Gist options
  • Save cadwallion/2554747 to your computer and use it in GitHub Desktop.
Save cadwallion/2554747 to your computer and use it in GitHub Desktop.
ActiveModel::Serializer Observations/edge-cases

Observation #1 (see included code):

App has 4 keys in a hash property called stats: '10s', '1min', '5min', 'day'. Each are arrays of Stat objects In order to create a stats attribute in AppSerializer, we have to create an intermediary Serializer with the attributes in order to re-use StatSerializer for each of those four Stat collections, and the syntax within that Serializer is pretty kludgy to make the association work.

Observation #2:

Using ActiveModel::Serializer outside of ActiveRecord requires an inclusion of ActiveModel::SerializerSupport, but the documentation does not state this, so there was some head-scratching as to why it wasn't magically working on our Mongoid models.

Observation #3 (see settings_serializer.rb):

I find instances where I have a hash attribute that I need to specify keys of the hash that I either need to write a filtered hash object or its own Serializer object. That may or may not be working-as-intended as this has some feeling of hash-driven mentality, but it surprised me.

Observation #4:

I cannot find a way to make the serializer data be the root of the JSON response, instead of being the data in a key. For example, if instead of wanting { 'app': { 'foo': 'bar' } } I want { 'foo': 'bar' }, there does not seem to be a way for that. I can change 'app' to 'foo' by passing the :root option, but I do not see a way to cause it to be the root of the JSON response itself.

class AppSerializer < ActiveModel::Serializer
attributes :id, :name
has_one :stats, :serializer => AppStatsSerializer
def stats
app.stats
end
end
class AppStatsSerializer < ActiveModel::Serializer
has_many 'ten_stats', key: '10s', serializer: StatSerializer
has_many 'one_stats', key: '1min', serializer: StatSerializer
has_many 'five_stats', key: '5min', serializer: StatSerializer
has_many 'day_stats', key: 'day', serializer: StatSerializer
def ten_stats
app_stats['10s']
end
def one_stats
app_stats['1min']
end
def five_stats
app_stats['5min']
end
def day_stats
app_stats['day']
end
end
class SettingsSerializer < ActiveModel::Serializer
attributes :app_name
has_one :pusher
has_one :auth_info
# pusher has app_id, key, and secret. we don't want secret passed.
def pusher
{
app_id: settings.pusher.app_id,
key: settings.pusher.key
}
end
# auth_info has data from two properties in Settings we want in a
# nested hash
def auth_info
{
base_url: settings.auth_info.base_url,
oauth: {
client_id: settings.auth_info.oauth.client_id
}
}
end
end
class StatSerializer < ActiveModel::Serializer
attributes :stat, :values, :type, :ts, :date
end
@cadwallion
Copy link
Author

Or failing that, the ability to use the same style of method definition on an attributes key as the has_(one|many) calls. My first instinct when I ran into this was attributes :pusher followed by def pusher ; ... ; end to modify the data getting passed as an attribute, only to see it doesn't work that way.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment