active_model_serializers: Can not filter attributes dymically?

In version 0.8.x it was possible to dynamically exclude certain attributes by implementing include_<name>? and returning false. In 0.9.x the same could be achieved with the filter(keys) method. For 0.10.0.rc3 this SO answer suggests overwriting the attributes method but that requires the attribute to exist anyway (and it is fetched always, even when excluded, which is not ideal from a performance point of view).

What is the recommended way to filter attributes (e.g. based on the current user, or options passed from the view) in 0.10.0.rc3 using the standard attributes adapter?

About this issue

  • Original URL
  • State: closed
  • Created 9 years ago
  • Comments: 16 (11 by maintainers)

Most upvoted comments

Hi @bf4, sure! One example would be to exclude attributes the current_user does not have access to.

Could be something like this:

class PostSerializer < ActiveModel::Serializer
  attributes :id, :name
  attributes :secret_token, :average_score, :if => :admin?

  def average_score
    # time consuming operation, which should only be executed if really needed
    object.scores.joins(...).average("SQRT(score * weight)")
  end

  def admin?
    scope.admin
  end
end

Or to exclude things which are not required, depending on the given params in the HTTP request:

class PostsController < ApplicationController
  def index
    @posts = Post.all
    render json: @posts, extra_columns: params[:extra_columns].split(",")
  end
end

class PostSerializer < ActiveModel::Serializer
  attributes :id
  attributes :name, :if => Proc.new { options[:extra_columns].include?("name") }
  attributes :content, :if => Proc.new { options[:extra_columns].include?("content") }
end

And another example would be to depend on the object itself:

class PostSerializer < ActiveModel::Serializer
  attributes :id, :name
  attributes :url, :if => :published?

  def published?
    object.published_at.present?
  end
end

In my current app the JSON in fact would depend on all of these: current_user (which is scope in AMS), params (which is options in AMS), as well as the object itself.

The DSL using :if is just a suggestion but I think it would be pretty idiomatic.

Let me know if I can help! Would be great to see this feature in 0.10.0 again!