Skip to content

Commit

Permalink
added support for optional_attributes
Browse files Browse the repository at this point in the history
  • Loading branch information
GavinJoyce committed Feb 4, 2015
1 parent 5fea5c8 commit de78503
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 7 deletions.
17 changes: 15 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ end
class AlbumSerializer
include RestPack::Serializer
attributes :id, :title, :year, :artist_id, :extras
optional :score

can_include :artists, :songs
can_filter_by :year

Expand All @@ -78,6 +80,18 @@ end
AlbumSerializer.as_json(album, { admin?: true })
```

All `attributes` are serialized by default. If you'd like to skip an attribute, you can pass an option in the `@context` as follows:

```ruby
AlbumSerializer.as_json(album, { include_title?: false })
```

You can also define `optional` attributes which aren't included by default. To include:

```ruby
AlbumSerializer.as_json(album, { include_score?: true })
```

## Exposing an API

The `AlbumSerializer` provides `page` and `resource` methods which provide paged collection and singular resource GET endpoints.
Expand Down Expand Up @@ -114,8 +128,7 @@ AlbumSerializer.page(params, Albums.where("year < 1950"), { admin?: true })
```

Other features:
* [Dynamically Include/Exclude Attributes](https://github.com/RestPack/restpack_serializer/blob/master/spec/serializable/serializer_spec.rb#L42)
* [Custom Attributes Hash](https://github.com/RestPack/restpack_serializer/blob/master/spec/serializable/serializer_spec.rb#L46)
* [Custom Attributes Hash](https://github.com/RestPack/restpack_serializer/blob/master/spec/serializable/serializer_spec.rb#L55)

## Paging

Expand Down
26 changes: 23 additions & 3 deletions lib/restpack_serializer/serializable/attributes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ def attributes(*attrs)
attrs.each { |attr| attribute attr }
end

def optional(*attrs)
attrs.each { |attr| optional_attribute attr }
end

def transform(attrs = [], transform_lambda)
attrs.each { |attr| transform_attribute(attr, transform_lambda) }
end
Expand All @@ -34,6 +38,12 @@ def attribute(name, options={})
define_include_method name
end

def optional_attribute(name, options={})
add_to_serializable(name, options)
define_attribute_method name
define_optional_include_method name
end

def define_attribute_method(name)
unless method_defined?(name)
define_method name do
Expand All @@ -45,12 +55,22 @@ def define_attribute_method(name)
end
end

def define_include_method(name)
def define_optional_include_method(name)
define_include_method(name, false)
end

def define_include_method(name, include_by_default=true)
method = "include_#{name}?".to_sym

unless method_defined?(method)
define_method method do
@context[method].nil? || @context[method]
if include_by_default
define_method method do
@context[method].nil? || @context[method]
end
else
define_method method do
@context[method].present?
end
end
end
end
Expand Down
26 changes: 24 additions & 2 deletions spec/serializable/attributes_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,20 @@
class CustomSerializer
include RestPack::Serializer
attributes :a, :b, :c
attributes :d, :e
optional :sometimes, :maybe
attribute :old_attribute, :key => :new_key
transform [:gonzaga], lambda { |name, model| model.send(name).downcase }
end

subject(:attributes) { CustomSerializer.serializable_attributes }

it "correctly models specified attributes" do
expect(attributes.length).to be(5)
expect(attributes.length).to be(9)
end

it "correctly maps normal attributes" do
[:a, :b, :c].each do |attr|
[:a, :b, :c, :d, :e].each do |attr|
expect(attributes[attr]).to eq(attr)
end
end
Expand All @@ -24,6 +26,26 @@ class CustomSerializer
expect(attributes[:new_key]).to eq(:old_attribute)
end

describe "optional attributes" do
let(:model) { OpenStruct.new(a: 'A', sometimes: 'SOMETIMES', gonzaga: 'GONZAGA') }
let(:context) { {} }
subject(:as_json) { CustomSerializer.as_json(model, context) }

context 'with no includes context' do
it "excludes by default" do
expect(as_json[:sometimes]).to eq(nil)
end
end

context 'with an includes context' do
let(:context) { { include_sometimes?: true } }

it "allows then to be included" do
expect(as_json[:sometimes]).to eq('SOMETIMES')
end
end
end

describe '#transform_attributes' do
let(:model) { OpenStruct.new(gonzaga: 'IS A SCHOOL') }

Expand Down

0 comments on commit de78503

Please sign in to comment.