Skip to content

Commit

Permalink
Merge 20823ff into 2e31a14
Browse files Browse the repository at this point in the history
  • Loading branch information
netoneko committed Jun 20, 2014
2 parents 2e31a14 + 20823ff commit e149027
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 16 deletions.
27 changes: 20 additions & 7 deletions README.md
@@ -1,5 +1,5 @@
[![Build Status](https://api.travis-ci.org/rails-api/active_model_serializers.png)](https://travis-ci.org/rails-api/active_model_serializers)
[![Code Climate](https://codeclimate.com/github/rails-api/active_model_serializers.png)](https://codeclimate.com/github/rails-api/active_model_serializers)
[![Build Status](https://api.travis-ci.org/rails-api/active_model_serializers.png)](https://travis-ci.org/rails-api/active_model_serializers)
[![Code Climate](https://codeclimate.com/github/rails-api/active_model_serializers.png)](https://codeclimate.com/github/rails-api/active_model_serializers)
[![Coverage Status](https://coveralls.io/repos/rails-api/active_model_serializers/badge.png?branch=master)](https://coveralls.io/r/rails-api/active_model_serializers)

# ActiveModel::Serializers
Expand All @@ -14,8 +14,8 @@ If you want to read the stable documentation visit [0.8 README](https://github.c

## Purpose

`ActiveModel::Serializers` encapsulates the JSON serialization of objects.
Objects that respond to read\_attribute\_for\_serialization
`ActiveModel::Serializers` encapsulates the JSON serialization of objects.
Objects that respond to read\_attribute\_for\_serialization
(including `ActiveModel` and `ActiveRecord` objects) are supported.

Serializers know about both a model and the `current_user`, so you can
Expand Down Expand Up @@ -71,7 +71,7 @@ $ rails g serializer post

Currently `ActiveModel::Serializers` expects objects to implement
read\_attribute\_for\_serialization. That's all you need to do to have
your POROs supported.
your POROs supported.

# render :json

Expand Down Expand Up @@ -302,6 +302,19 @@ class PostSerializer < ActiveModel::Serializer
end
```

Also you can use `if` parameter to `attributes` like this:

```ruby
class PostSerializer < ActiveModel::Serializer
attributes :id, :title
attributes :body, :author, :if => :shows_body_and_author?

def shows_body_and_author?
[true, false].sample # Confuse client side developers with randomly absent attributes
end
end
```

And it's also safe to mutate keys argument by doing keys.delete(:author)
in case you want to avoid creating two extra arrays. Note that if you do an
in-place modification, you still need to return the modified array.
Expand Down Expand Up @@ -573,8 +586,8 @@ this:
}
```

When side-loading data, your serializer cannot have the `{ root: false }` option,
as this would lead to invalid JSON. If you do not have a root key, the `include`
When side-loading data, your serializer cannot have the `{ root: false }` option,
as this would lead to invalid JSON. If you do not have a root key, the `include`
instruction will be ignored

You can also specify a different root for the embedded objects than the key
Expand Down
41 changes: 37 additions & 4 deletions lib/active_model/serializer.rb
Expand Up @@ -16,6 +16,7 @@ def inherited(base)
base._root = _root
base._attributes = (_attributes || []).dup
base._associations = (_associations || {}).dup
base._conditions = (@_conditions || {}).dup
end

def setup
Expand Down Expand Up @@ -60,17 +61,28 @@ def serializer_for(resource)
end
end

attr_accessor :_root, :_attributes, :_associations
attr_accessor :_root, :_attributes, :_associations, :_conditions
alias root _root=
alias root= _root=

def root_name
name.demodulize.underscore.sub(/_serializer$/, '') if name
end

def attributes(*attrs)
def attributes(*args)
attrs, options = if args.last.kind_of? Hash
[args[0, args.size - 1], args.last]
else
[args, {}]
end

@_attributes.concat attrs

if condition = options[:if]
attrs_list = @_conditions[condition]
@_conditions[condition] = (attrs_list || []).concat(attrs).compact
end

attrs.each do |attr|
define_method attr do
object.read_attribute_for_serialization attr
Expand Down Expand Up @@ -110,8 +122,16 @@ def initialize(object, options={})
@wrap_in_array = options[:_wrap_in_array]
@only = Array(options[:only]) if options[:only]
@except = Array(options[:except]) if options[:except]
@conditions_cache = {}

self.class._conditions.map do |condition, attrs|
condition = {resolved: false, method: condition}
attrs.each do |attr|
conditions_cache[attr] = condition
end
end
end
attr_accessor :object, :scope, :root, :meta_key, :meta
attr_accessor :object, :scope, :root, :meta_key, :meta, :conditions_cache

def json_key
if root == true || root.nil?
Expand Down Expand Up @@ -142,9 +162,11 @@ def associations
end

def filter(keys)
@except = (@except || []).concat check_conditions

if @only
keys & @only
elsif @except
elsif @except.any?
keys - @except
else
keys
Expand Down Expand Up @@ -197,5 +219,16 @@ def serializable_object(options={})
@wrap_in_array ? [hash] : hash
end
alias_method :serializable_hash, :serializable_object

def check_conditions
conditions_cache.map do |attr, condition|
unless condition[:resolved]
condition[:resolved] = true
condition[:result] = send(condition[:method])
end

attr unless condition[:result]
end.compact
end
end
end
16 changes: 15 additions & 1 deletion test/fixtures/poro.rb
Expand Up @@ -50,7 +50,21 @@ def description
scope ? "#{description} - #{scope}" : description
end

attributes :name, :description
def show_me
raise "No way!"
end

def should_show_me
false
end

def should_show_description
true
end

attributes :name
attributes :description, :if => :should_show_description
attributes :show_me, :if => :should_show_me
end

class PostSerializer < ActiveModel::Serializer
Expand Down
6 changes: 3 additions & 3 deletions test/unit/active_model/serializer/attributes_test.rb
Expand Up @@ -9,7 +9,7 @@ def setup
end

def test_attributes_definition
assert_equal([:name, :description],
assert_equal([:name, :description, :show_me],
@profile_serializer.class._attributes)
end

Expand All @@ -31,9 +31,9 @@ def test_attributes_inheritance
end
another_inherited_serializer_klass = Class.new(ProfileSerializer)

assert_equal([:name, :description, :comments],
assert_equal([:name, :description, :show_me, :comments],
inherited_serializer_klass._attributes)
assert_equal([:name, :description],
assert_equal([:name, :description, :show_me],
another_inherited_serializer_klass._attributes)
end
end
Expand Down
2 changes: 1 addition & 1 deletion test/unit/active_model/serializer/filter_test.rb
Expand Up @@ -28,7 +28,7 @@ def setup
@profile_serializer = ProfileSerializer.new(@profile)
@profile_serializer.instance_eval do
def filter(keys)
keys - [:description]
keys - [:description, :show_me]
end
end
end
Expand Down

0 comments on commit e149027

Please sign in to comment.