active_serializer 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +4 -0
- data/Gemfile +9 -0
- data/Gemfile.lock +49 -0
- data/LICENSE.txt +22 -0
- data/README.md +77 -0
- data/Rakefile +1 -0
- data/active_serializer.gemspec +24 -0
- data/lib/active_serializer.rb +13 -0
- data/lib/active_serializer/serializable.rb +35 -0
- data/lib/active_serializer/serializable_hash.rb +25 -0
- data/lib/active_serializer/serializable_object.rb +44 -0
- data/lib/active_serializer/serialization_rules_validator.rb +35 -0
- data/lib/active_serializer/serializers.rb +2 -0
- data/lib/active_serializer/serializers/hash_serializer.rb +64 -0
- data/lib/active_serializer/serializers/ignore_blank_hash_serializer.rb +9 -0
- data/lib/active_serializer/serializers/object_serializer.rb +97 -0
- data/lib/active_serializer/serializers/restrict_fields_object_serializer.rb +40 -0
- data/lib/active_serializer/support/args_validator.rb +46 -0
- data/lib/active_serializer/support/fake_object.rb +9 -0
- data/lib/active_serializer/version.rb +3 -0
- data/spec/active_serializer/serializable_hash_spec.rb +89 -0
- data/spec/active_serializer/serializable_object_spec.rb +159 -0
- data/spec/spec_helper.rb +8 -0
- metadata +128 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
active_serializer (0.1.0)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
activesupport (4.0.1)
|
10
|
+
i18n (~> 0.6, >= 0.6.4)
|
11
|
+
minitest (~> 4.2)
|
12
|
+
multi_json (~> 1.3)
|
13
|
+
thread_safe (~> 0.1)
|
14
|
+
tzinfo (~> 0.3.37)
|
15
|
+
atomic (1.1.14)
|
16
|
+
columnize (0.3.6)
|
17
|
+
debugger (1.6.2)
|
18
|
+
columnize (>= 0.3.1)
|
19
|
+
debugger-linecache (~> 1.2.0)
|
20
|
+
debugger-ruby_core_source (~> 1.2.3)
|
21
|
+
debugger-linecache (1.2.0)
|
22
|
+
debugger-ruby_core_source (1.2.3)
|
23
|
+
diff-lcs (1.2.4)
|
24
|
+
i18n (0.6.5)
|
25
|
+
minitest (4.7.5)
|
26
|
+
multi_json (1.8.2)
|
27
|
+
rake (10.1.0)
|
28
|
+
rspec (2.14.1)
|
29
|
+
rspec-core (~> 2.14.0)
|
30
|
+
rspec-expectations (~> 2.14.0)
|
31
|
+
rspec-mocks (~> 2.14.0)
|
32
|
+
rspec-core (2.14.7)
|
33
|
+
rspec-expectations (2.14.4)
|
34
|
+
diff-lcs (>= 1.1.3, < 2.0)
|
35
|
+
rspec-mocks (2.14.4)
|
36
|
+
thread_safe (0.1.3)
|
37
|
+
atomic
|
38
|
+
tzinfo (0.3.38)
|
39
|
+
|
40
|
+
PLATFORMS
|
41
|
+
ruby
|
42
|
+
|
43
|
+
DEPENDENCIES
|
44
|
+
active_serializer!
|
45
|
+
activesupport
|
46
|
+
bundler (~> 1.3)
|
47
|
+
debugger
|
48
|
+
rake
|
49
|
+
rspec
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Albert Gazizov
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
# ActiveSerializer
|
2
|
+
|
3
|
+
Active Serializer is a simple objects to hash serializer.
|
4
|
+
|
5
|
+
## Usage
|
6
|
+
|
7
|
+
Here's an example serializer:
|
8
|
+
```ruby
|
9
|
+
class ContactSerializer
|
10
|
+
include ActiveSerializer::SerializableObject
|
11
|
+
|
12
|
+
serialization_rules do |contact, home_address, contact_emails|
|
13
|
+
attributes :first_name, :last_name, contact
|
14
|
+
|
15
|
+
attribute :full_name do
|
16
|
+
"#{contact.first_name} #{contact.last_name}"
|
17
|
+
end
|
18
|
+
|
19
|
+
resource :address, home_address do |address|
|
20
|
+
attributes :country, :city, :street, address
|
21
|
+
end
|
22
|
+
|
23
|
+
resources :emails, contact_emails do |email|
|
24
|
+
attributes :email
|
25
|
+
attribute :type do
|
26
|
+
'home'
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
```
|
32
|
+
|
33
|
+
Let's use it:
|
34
|
+
```ruby
|
35
|
+
ContactSerializer.serialize(contact, home_address, contact_emails)
|
36
|
+
```
|
37
|
+
|
38
|
+
And we get a result:
|
39
|
+
```ruby
|
40
|
+
{
|
41
|
+
first_name: "John",
|
42
|
+
last_name: "Smith",
|
43
|
+
full_name: "John Smith",
|
44
|
+
address: {
|
45
|
+
country: "Russia",
|
46
|
+
city: "Kazan",
|
47
|
+
street: "Kosmonavton"
|
48
|
+
},
|
49
|
+
emails: [
|
50
|
+
{ email: "test@test.com", type: "home" },
|
51
|
+
{ email: "test2@test.com", type: "home" }
|
52
|
+
]
|
53
|
+
}
|
54
|
+
```
|
55
|
+
|
56
|
+
## Installation
|
57
|
+
|
58
|
+
Add this line to your application's Gemfile:
|
59
|
+
|
60
|
+
gem 'active_serializer'
|
61
|
+
|
62
|
+
And then execute:
|
63
|
+
|
64
|
+
$ bundle
|
65
|
+
|
66
|
+
Or install it yourself as:
|
67
|
+
|
68
|
+
$ gem install active_serializer
|
69
|
+
|
70
|
+
## Contributing
|
71
|
+
|
72
|
+
1. Fork it
|
73
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
74
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
75
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
76
|
+
5. Create new Pull Request
|
77
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'active_serializer/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "active_serializer"
|
8
|
+
spec.version = ActiveSerializer::VERSION
|
9
|
+
spec.authors = ["Albert Gazizov", "Ruslan Gatiyatov"]
|
10
|
+
spec.email = ["deeper4k@gmail.com", "ruslan.gatiyatov@gmail.com"]
|
11
|
+
spec.description = %q{Object to Hash serializer}
|
12
|
+
spec.summary = %q{Adds simple DSL to convert ruby objects to hash}
|
13
|
+
spec.homepage = "http://github.com/droidlabs/active_serializer"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(spec)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
spec.add_development_dependency "activesupport"
|
24
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'active_support/concern.rb'
|
2
|
+
require 'active_support/core_ext/array/wrap.rb'
|
3
|
+
require 'active_serializer/version'
|
4
|
+
require 'active_serializer/support/fake_object'
|
5
|
+
require 'active_serializer/support/args_validator'
|
6
|
+
require 'active_serializer/serialization_rules_validator'
|
7
|
+
require 'active_serializer/serializers'
|
8
|
+
require 'active_serializer/serializable'
|
9
|
+
require 'active_serializer/serializable_hash'
|
10
|
+
require 'active_serializer/serializable_object'
|
11
|
+
|
12
|
+
module ActiveSerializer
|
13
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module ActiveSerializer::Serializable
|
2
|
+
|
3
|
+
def serialize(*objects)
|
4
|
+
serialization_options = self.class_variable_get(:@@serialization_options)
|
5
|
+
serialization_rules = self.class_variable_get(:@@serialization_rules)
|
6
|
+
ActiveSerializer::Support::ArgsValidator.not_nil!(serialization_rules, :serialization_rules)
|
7
|
+
|
8
|
+
serialized_data = run_serialization(objects, serialization_rules, serialization_options)
|
9
|
+
|
10
|
+
if serialization_options[:no_root_node]
|
11
|
+
serialized_data.first[1]
|
12
|
+
else
|
13
|
+
serialized_data
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def serialize_all(collection, options = {})
|
18
|
+
collection.map do |object|
|
19
|
+
serialize(object, options)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def serialization_rules(options = {}, &block)
|
24
|
+
self.class_variable_set(:@@serialization_options, options)
|
25
|
+
ActiveSerializer::SerializationRulesValidator.validate!(&block)
|
26
|
+
self.class_variable_set(:@@serialization_rules, block)
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def run_serialization(objects, serialization_rules, serialization_options)
|
32
|
+
raise NotImplementedError, "should be implemented in derived class"
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'active_serializer/serializers/hash_serializer'
|
2
|
+
require 'active_serializer/serializers/ignore_blank_hash_serializer'
|
3
|
+
|
4
|
+
module ActiveSerializer::SerializableHash
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
include ActiveSerializer::Serializable
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def run_serialization(objects, serialization_rules, serialization_options)
|
13
|
+
if serialization_options[:ignore_blank]
|
14
|
+
serializer = ActiveSerializer::Serializers::IgnoreBlankHashSerializer.new(objects.first, serialization_options)
|
15
|
+
else
|
16
|
+
serializer = ActiveSerializer::Serializers::HashSerializer.new(objects.first, serialization_options)
|
17
|
+
end
|
18
|
+
instance_exec do
|
19
|
+
serializer.instance_exec(*objects, &serialization_rules)
|
20
|
+
end
|
21
|
+
serializer.serialized_data
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'active_serializer/serializers/object_serializer'
|
2
|
+
require 'active_serializer/serializers/restrict_fields_object_serializer'
|
3
|
+
|
4
|
+
module ActiveSerializer::SerializableObject
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
def serialize(*objects)
|
9
|
+
first_object = objects.first
|
10
|
+
options = objects.last.is_a?(Hash) ? objects.last : {}
|
11
|
+
|
12
|
+
serialization_options = self.class_variable_get(:@@serialization_options)
|
13
|
+
serialization_rules = self.class_variable_get(:@@serialization_rules)
|
14
|
+
|
15
|
+
if options[:serializable_fields]
|
16
|
+
serializer = ActiveSerializer::Serializers::RestrictFieldsObjectSerializer.new(first_object, options)
|
17
|
+
else
|
18
|
+
serializer = ActiveSerializer::Serializers::ObjectSerializer.new(first_object, options)
|
19
|
+
end
|
20
|
+
instance_exec do
|
21
|
+
serializer.instance_exec(*objects, &serialization_rules)
|
22
|
+
end
|
23
|
+
if serialization_options[:no_root_node]
|
24
|
+
serializer.attrs.first[1]
|
25
|
+
else
|
26
|
+
serializer.attrs
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def serialize_all(collection, options = {})
|
31
|
+
collection.map do |object|
|
32
|
+
serialize(object, options)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def serialization_rules(options = {}, &block)
|
37
|
+
self.class_variable_set(:@@serialization_options, options)
|
38
|
+
self.class_variable_set(:@@serialization_rules, block)
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
class ActiveSerializer::SerializationRulesValidator
|
2
|
+
private :initialize
|
3
|
+
|
4
|
+
def self.validate!(&rules)
|
5
|
+
fake_objects = rules.arity.times.map do
|
6
|
+
ActiveSerializer::Support::FakeObject.new
|
7
|
+
end
|
8
|
+
validator = self.new
|
9
|
+
validator.instance_exec(*fake_objects, &rules)
|
10
|
+
end
|
11
|
+
|
12
|
+
def attribute(name, value = nil, &block)
|
13
|
+
ActiveSerializer::Support::ArgsValidator.is_symbol!(name, 'attributes')
|
14
|
+
end
|
15
|
+
|
16
|
+
def attributes(*attrs)
|
17
|
+
attrs.delete_at(-1)
|
18
|
+
ActiveSerializer::Support::ArgsValidator.is_array_of_symbols!(attrs, 'attributes')
|
19
|
+
end
|
20
|
+
|
21
|
+
def namespace(name, &block)
|
22
|
+
ActiveSerializer::Support::ArgsValidator.is_symbol!(name, 'namespace name')
|
23
|
+
ActiveSerializer::Support::ArgsValidator.block_given!(block, 'namespace block')
|
24
|
+
end
|
25
|
+
|
26
|
+
def resource(name, object = nil, &block)
|
27
|
+
ActiveSerializer::Support::ArgsValidator.is_symbol!(name, 'resource name')
|
28
|
+
ActiveSerializer::Support::ArgsValidator.block_given!(block, 'resource block')
|
29
|
+
end
|
30
|
+
|
31
|
+
def resources(name, objects = nil, &block)
|
32
|
+
ActiveSerializer::Support::ArgsValidator.is_symbol!(name, 'resources name')
|
33
|
+
ActiveSerializer::Support::ArgsValidator.block_given!(block, 'resources block')
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
class ActiveSerializer::Serializers::HashSerializer
|
2
|
+
attr_reader :serialized_data
|
3
|
+
|
4
|
+
def initialize(root_hash, options = {})
|
5
|
+
@root_hash = root_hash
|
6
|
+
@options = options
|
7
|
+
@serialized_data = {}
|
8
|
+
end
|
9
|
+
|
10
|
+
def attribute(name, value = nil, &block)
|
11
|
+
if block_given?
|
12
|
+
value = yield
|
13
|
+
elsif !value
|
14
|
+
value = @root_hash[name]
|
15
|
+
end
|
16
|
+
set_value(name, value)
|
17
|
+
end
|
18
|
+
|
19
|
+
def attributes(*serialized_data, &block)
|
20
|
+
if !serialized_data.last.is_a?(Symbol)
|
21
|
+
source_hash = serialized_data.delete_at(-1)
|
22
|
+
else
|
23
|
+
source_hash = @root_hash
|
24
|
+
end
|
25
|
+
|
26
|
+
serialized_data.each do |attr_name|
|
27
|
+
set_value(attr_name, source_hash[attr_name])
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def namespace(name, &block)
|
32
|
+
serializer = self.class.new(@root_hash, @options)
|
33
|
+
serializer.instance_exec(@root_hash, &block)
|
34
|
+
set_value(name, serializer.serialized_data)
|
35
|
+
end
|
36
|
+
|
37
|
+
def resource(name, source_hash = nil, &block)
|
38
|
+
source_hash ||= @root_hash[name]
|
39
|
+
set_value(name, serialize_resource(source_hash, &block))
|
40
|
+
end
|
41
|
+
|
42
|
+
def resources(name, source_hashes = nil, &block)
|
43
|
+
source_hashes ||= @root_hash[name]
|
44
|
+
|
45
|
+
self.serialized_data[name] = (source_hashes || []).inject([]) do |result, source_hash|
|
46
|
+
data = serialize_resource(source_hash, &block)
|
47
|
+
data.empty? ? result : (result << data)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
protected
|
52
|
+
|
53
|
+
def serialize_resource(source_hash, &block)
|
54
|
+
return nil unless source_hash
|
55
|
+
serializer = self.class.new(source_hash, @options)
|
56
|
+
serializer.instance_exec(source_hash, &block)
|
57
|
+
serializer.serialized_data
|
58
|
+
end
|
59
|
+
|
60
|
+
def set_value(name, value)
|
61
|
+
self.serialized_data[name] = value
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
class ActiveSerializer::Serializers::ObjectSerializer
|
2
|
+
attr_reader :attrs
|
3
|
+
|
4
|
+
def initialize(object, options = {})
|
5
|
+
@object, @options = object, options
|
6
|
+
@attrs = {}
|
7
|
+
end
|
8
|
+
|
9
|
+
def namespace(name, &block)
|
10
|
+
serializer = self.class.new(@object, @options)
|
11
|
+
serializer.instance_exec(@object, &block)
|
12
|
+
self.attrs[name] = serializer.attrs
|
13
|
+
end
|
14
|
+
|
15
|
+
def resource(name, object = nil, &block)
|
16
|
+
raise "You should set name for resource" unless name
|
17
|
+
raise "You should specify object" if @object.nil? && object.nil?
|
18
|
+
nested_name = name
|
19
|
+
nested_object = object || @object.send(nested_name)
|
20
|
+
unless nested_object
|
21
|
+
self.attrs[nested_name] = {}
|
22
|
+
else
|
23
|
+
if block_given?
|
24
|
+
self.attrs[nested_name] = nested_resource(nested_name, nested_object, @options, &block)
|
25
|
+
elsif nested_object.respond_to?(:to_hash)
|
26
|
+
self.attrs[nested_name] = nested_object.to_hash
|
27
|
+
elsif nested_object.is_a?(String)
|
28
|
+
self.attrs[nested_name] = nested_object
|
29
|
+
else
|
30
|
+
raise "You should specify block or declare 'to_hash' method"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def resources(name, objects = nil, &block)
|
36
|
+
raise "You should specify object" if @object.nil? && objects.nil?
|
37
|
+
objects = objects.flatten unless objects.nil?
|
38
|
+
nested_objects = objects || @object.send(name.to_s)
|
39
|
+
unless nested_objects
|
40
|
+
self.attrs[name] = []
|
41
|
+
else
|
42
|
+
self.attrs[name] = (nested_objects || []).inject([]) do |result, obj|
|
43
|
+
resource = nested_resource(name, obj, @options, &block)
|
44
|
+
resource.empty? ? result : (result << resource)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def attributes(*attrs, &block)
|
50
|
+
if !attrs.last.is_a?(Symbol) && !attrs.last.is_a?(String)
|
51
|
+
object = attrs.last
|
52
|
+
attrs.delete(attrs.last)
|
53
|
+
end
|
54
|
+
if !@object && !object
|
55
|
+
raise ArgumentError, "Object was not specified"
|
56
|
+
end
|
57
|
+
|
58
|
+
target = object || @object
|
59
|
+
Array.wrap(attrs).flatten.each do |attribute|
|
60
|
+
serialize_attribute(attribute, target)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def attribute(attr, val = nil, &block)
|
65
|
+
if block_given?
|
66
|
+
self.attrs[attr] = yield
|
67
|
+
return
|
68
|
+
end
|
69
|
+
|
70
|
+
if @object.blank?
|
71
|
+
raise ArgumentError, "Neither object was specified nor block was given"
|
72
|
+
end
|
73
|
+
self.attrs[attr] = val || @object.send(attr.to_s)
|
74
|
+
end
|
75
|
+
|
76
|
+
protected
|
77
|
+
|
78
|
+
def serialize_attribute(attribute, target)
|
79
|
+
self.attrs[attribute] = target.send(attribute.to_s)
|
80
|
+
end
|
81
|
+
|
82
|
+
def nested_resource(name, object, options, serializer_class = self.class, &block)
|
83
|
+
return nil if !object
|
84
|
+
serializer = serializer_class.new(object, options)
|
85
|
+
if block_given?
|
86
|
+
serializer.instance_exec(object, &block)
|
87
|
+
serializer.attrs
|
88
|
+
else
|
89
|
+
if object.respond_to?(:to_hash)
|
90
|
+
object.to_hash
|
91
|
+
elsif object.is_a?(String)
|
92
|
+
object
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
class ActiveSerializer::Serializers::RestrictFieldsObjectSerializer < ActiveSerializer::Serializers::ObjectSerializer
|
2
|
+
def initialize(object, options)
|
3
|
+
raise ArgumentError, 'serializable_fields should be specified' unless options[:serializable_fields]
|
4
|
+
super
|
5
|
+
@serializable_fields = options[:serializable_fields].keys
|
6
|
+
end
|
7
|
+
|
8
|
+
def resource(name, object = nil, &block)
|
9
|
+
super if @serializable_fields.include?(name)
|
10
|
+
end
|
11
|
+
|
12
|
+
def resources(name, objects = nil, &block)
|
13
|
+
super if @serializable_fields.include?(name)
|
14
|
+
end
|
15
|
+
|
16
|
+
def attribute(name, val = nil, &block)
|
17
|
+
super if @serializable_fields.include?(name)
|
18
|
+
end
|
19
|
+
|
20
|
+
protected
|
21
|
+
|
22
|
+
def serialize_attribute(attribute, target)
|
23
|
+
super if @serializable_fields.include?(attribute)
|
24
|
+
end
|
25
|
+
|
26
|
+
def nested_resource(name, object, root_options, serializer_class = self.class, &block)
|
27
|
+
options = root_options.dup
|
28
|
+
serializable_fields = root_options[:serializable_fields][name]
|
29
|
+
if !serializable_fields
|
30
|
+
return
|
31
|
+
elsif serializable_fields == true
|
32
|
+
super(name, object, options, ActiveSerializer::Serializers::ObjectSerializer, &block)
|
33
|
+
elsif serializable_fields.is_a?(Hash)
|
34
|
+
options[:serializable_fields] = serializable_fields
|
35
|
+
super(name, object, options, &block)
|
36
|
+
else
|
37
|
+
raise ArgumentError, "serializable_fields' values should be boolean or hash"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module ActiveSerializer::Support::ArgsValidator
|
2
|
+
class << self
|
3
|
+
def is_symbol!(obj, obj_name)
|
4
|
+
unless obj.is_a?(Symbol)
|
5
|
+
raise ArgumentError, "#{obj_name} should be a Symbol"
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
def is_array!(obj, obj_name)
|
10
|
+
unless obj.is_a?(Array)
|
11
|
+
raise ArgumentError, "#{obj_name} should be an Array"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def is_hash!(obj, obj_name)
|
16
|
+
unless obj.is_a?(Hash)
|
17
|
+
raise ArgumentError, "#{obj_name} should be a Hash"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def has_key!(hash, key)
|
22
|
+
unless hash.has_key?(key)
|
23
|
+
raise ArgumentError, "#{hash} should has #{key} key"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def is_array_of_symbols!(array, obj_name)
|
28
|
+
is_array!(array, obj_name)
|
29
|
+
unless array.all? { |item| item.is_a?(Symbol) }
|
30
|
+
raise ArgumentError, "#{obj_name} elements should be a symbols"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def block_given!(block, obj_name)
|
35
|
+
unless block
|
36
|
+
raise ArgumentError, "Block should be given to #{obj_name}"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def not_nil!(obj, obj_name)
|
41
|
+
unless obj
|
42
|
+
raise ArgumentError, "#{obj_name} can not be nil"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module SerializableHashTest
|
4
|
+
describe ActiveSerializer::SerializableHash do
|
5
|
+
class ContactSerializer
|
6
|
+
include ActiveSerializer::SerializableHash
|
7
|
+
|
8
|
+
serialization_rules do |contact, home_address, contact_emails|
|
9
|
+
attributes :first_name, :last_name, contact
|
10
|
+
|
11
|
+
attribute :full_name do
|
12
|
+
"#{contact[:first_name]} #{contact[:last_name]}"
|
13
|
+
end
|
14
|
+
|
15
|
+
resource :address, home_address do |address|
|
16
|
+
attributes :country, :city, :street, address
|
17
|
+
end
|
18
|
+
|
19
|
+
resources :emails, contact_emails do |email|
|
20
|
+
attributes :email
|
21
|
+
attribute :type do
|
22
|
+
'home'
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "#serialize" do
|
29
|
+
it "should serialize object" do
|
30
|
+
contact = {
|
31
|
+
first_name: 'John',
|
32
|
+
last_name: 'Smith',
|
33
|
+
}
|
34
|
+
|
35
|
+
contact_emails = [
|
36
|
+
{ email: 'test@test.com'},
|
37
|
+
{ email: 'test2@test.com'},
|
38
|
+
]
|
39
|
+
|
40
|
+
home_address = {
|
41
|
+
country: 'Russia',
|
42
|
+
city: 'Kazan',
|
43
|
+
street: 'Kosmonavton',
|
44
|
+
}
|
45
|
+
|
46
|
+
serialized_contact = ContactSerializer.serialize(contact, home_address, contact_emails)
|
47
|
+
serialized_contact.should == {
|
48
|
+
first_name: "John",
|
49
|
+
last_name: "Smith",
|
50
|
+
full_name: "John Smith",
|
51
|
+
address: {
|
52
|
+
country: "Russia",
|
53
|
+
city: "Kazan",
|
54
|
+
street: "Kosmonavton"
|
55
|
+
},
|
56
|
+
emails: [
|
57
|
+
{ email: "test@test.com", type: "home" },
|
58
|
+
{ email: "test2@test.com", type: "home" }
|
59
|
+
]
|
60
|
+
}
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
class ContactIgnoreBlankSerializer
|
65
|
+
include ActiveSerializer::SerializableHash
|
66
|
+
|
67
|
+
serialization_rules ignore_blank: true do |contact|
|
68
|
+
attributes :first_name, :last_name
|
69
|
+
|
70
|
+
attribute :full_name
|
71
|
+
attribute(:address) if contact[:full_name]
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe "#serialize" do
|
76
|
+
it "should not return blank values" do
|
77
|
+
contact = {
|
78
|
+
first_name: nil,
|
79
|
+
last_name: nil,
|
80
|
+
full_name: nil,
|
81
|
+
}
|
82
|
+
|
83
|
+
serialized_contact = ContactIgnoreBlankSerializer.serialize(contact)
|
84
|
+
serialized_contact.should == {}
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
@@ -0,0 +1,159 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module SerializableObjectTest
|
4
|
+
describe ActiveSerializer::SerializableObject do
|
5
|
+
class Contact
|
6
|
+
attr_accessor :first_name, :last_name
|
7
|
+
end
|
8
|
+
|
9
|
+
class Address
|
10
|
+
attr_accessor :country, :city, :street
|
11
|
+
end
|
12
|
+
|
13
|
+
class Email
|
14
|
+
attr_accessor :email
|
15
|
+
end
|
16
|
+
|
17
|
+
class ContactSerializer
|
18
|
+
include ActiveSerializer::SerializableObject
|
19
|
+
|
20
|
+
serialization_rules do |contact, home_address, contact_emails|
|
21
|
+
attributes :first_name, :last_name, contact
|
22
|
+
|
23
|
+
attribute :full_name do
|
24
|
+
"#{contact.first_name} #{contact.last_name}"
|
25
|
+
end
|
26
|
+
|
27
|
+
resource :address, home_address do |address|
|
28
|
+
attributes :country, :city, :street, address
|
29
|
+
end
|
30
|
+
|
31
|
+
resources :emails, contact_emails do |email|
|
32
|
+
attributes :email
|
33
|
+
attribute :type do
|
34
|
+
'home'
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "#serialize" do
|
41
|
+
it "should serialize object" do
|
42
|
+
contact = Contact.new
|
43
|
+
contact.first_name = 'John'
|
44
|
+
contact.last_name = 'Smith'
|
45
|
+
|
46
|
+
home_email1 = Email.new
|
47
|
+
home_email1.email = 'test@test.com'
|
48
|
+
home_email2 = Email.new
|
49
|
+
home_email2.email = 'test2@test.com'
|
50
|
+
contact_emails = [home_email1, home_email2]
|
51
|
+
|
52
|
+
home_address = Address.new
|
53
|
+
home_address.country = 'Russia'
|
54
|
+
home_address.city = 'Kazan'
|
55
|
+
home_address.street = 'Kosmonavton'
|
56
|
+
|
57
|
+
serialized_contact = ContactSerializer.serialize(contact, home_address, contact_emails)
|
58
|
+
serialized_contact.should == {
|
59
|
+
first_name: "John",
|
60
|
+
last_name: "Smith",
|
61
|
+
full_name: "John Smith",
|
62
|
+
address: {
|
63
|
+
country: "Russia",
|
64
|
+
city: "Kazan",
|
65
|
+
street: "Kosmonavton"
|
66
|
+
},
|
67
|
+
emails: [
|
68
|
+
{ email: "test@test.com", type: "home" },
|
69
|
+
{ email: "test2@test.com", type: "home" }
|
70
|
+
]
|
71
|
+
}
|
72
|
+
end
|
73
|
+
|
74
|
+
class ContactsSerializer
|
75
|
+
include ActiveSerializer::SerializableObject
|
76
|
+
|
77
|
+
serialization_rules no_root_node: true do |contacts, home_address|
|
78
|
+
resources :contacts, contacts do |contact|
|
79
|
+
attributes :first_name, :last_name, contact
|
80
|
+
resource :address, home_address do |address|
|
81
|
+
attributes :country, :city, :street, address
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should return Array when no_root_node: true specified" do
|
88
|
+
contact1 = Contact.new
|
89
|
+
contact1.first_name = 'John'
|
90
|
+
contact1.last_name = 'Smith'
|
91
|
+
contact2 = Contact.new
|
92
|
+
contact2.first_name = 'John'
|
93
|
+
contact2.last_name = 'Smith'
|
94
|
+
home_address = Address.new
|
95
|
+
home_address.country = 'Russia'
|
96
|
+
home_address.city = 'Kazan'
|
97
|
+
home_address.street = 'Kosmonavton'
|
98
|
+
|
99
|
+
serialized_contacts = ContactsSerializer.serialize([contact1, contact2], home_address)
|
100
|
+
serialized_contacts.should be_an_instance_of(Array)
|
101
|
+
end
|
102
|
+
|
103
|
+
|
104
|
+
class Company
|
105
|
+
attr_accessor :name, :emails, :address
|
106
|
+
end
|
107
|
+
class CompanySerializer
|
108
|
+
include ActiveSerializer::SerializableObject
|
109
|
+
|
110
|
+
serialization_rules do |company|
|
111
|
+
attributes :name
|
112
|
+
resource :address do |address|
|
113
|
+
attributes :country, :city, :street
|
114
|
+
end
|
115
|
+
resources :emails do |email|
|
116
|
+
attribute :email do
|
117
|
+
email.email
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
it "should serialize only fields spefied in serializable_fields option" do
|
124
|
+
company = Company.new
|
125
|
+
company.name = "MyCo"
|
126
|
+
|
127
|
+
email1 = Email.new
|
128
|
+
email1.email = 'test@test.com'
|
129
|
+
email2 = Email.new
|
130
|
+
email2.email = 'test2@test.com'
|
131
|
+
company.emails = [email1, email2]
|
132
|
+
|
133
|
+
address = Address.new
|
134
|
+
address.country = 'Russia'
|
135
|
+
address.city = 'Kazan'
|
136
|
+
address.street = 'Kosmonavton'
|
137
|
+
company.address = address
|
138
|
+
|
139
|
+
serialized_company = CompanySerializer.serialize(company, serializable_fields: { name: true, emails: { email: true}, address: { country: true }})
|
140
|
+
serialized_company.should =={
|
141
|
+
name: "MyCo",
|
142
|
+
address: {country: "Russia"},
|
143
|
+
emails: [
|
144
|
+
{ email: "test@test.com" },
|
145
|
+
{ email: "test2@test.com" }
|
146
|
+
]
|
147
|
+
}
|
148
|
+
serialized_company = CompanySerializer.serialize(company, serializable_fields: { emails: true})
|
149
|
+
serialized_company.should == {
|
150
|
+
emails: [
|
151
|
+
{ email: "test@test.com" },
|
152
|
+
{ email: "test2@test.com" }
|
153
|
+
]
|
154
|
+
}
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,128 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: active_serializer
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.1.0
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Albert Gazizov
|
9
|
+
- Ruslan Gatiyatov
|
10
|
+
autorequire:
|
11
|
+
bindir: bin
|
12
|
+
cert_chain: []
|
13
|
+
date: 2014-04-08 00:00:00.000000000 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
prerelease: false
|
17
|
+
name: bundler
|
18
|
+
type: :development
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ~>
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: '1.3'
|
24
|
+
none: false
|
25
|
+
requirement: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '1.3'
|
30
|
+
none: false
|
31
|
+
- !ruby/object:Gem::Dependency
|
32
|
+
prerelease: false
|
33
|
+
name: rake
|
34
|
+
type: :development
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ! '>='
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0'
|
40
|
+
none: false
|
41
|
+
requirement: !ruby/object:Gem::Requirement
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
none: false
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
prerelease: false
|
49
|
+
name: activesupport
|
50
|
+
type: :development
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ! '>='
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
none: false
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
none: false
|
63
|
+
description: Object to Hash serializer
|
64
|
+
email:
|
65
|
+
- deeper4k@gmail.com
|
66
|
+
- ruslan.gatiyatov@gmail.com
|
67
|
+
executables: []
|
68
|
+
extensions: []
|
69
|
+
extra_rdoc_files: []
|
70
|
+
files:
|
71
|
+
- .gitignore
|
72
|
+
- Gemfile
|
73
|
+
- Gemfile.lock
|
74
|
+
- LICENSE.txt
|
75
|
+
- README.md
|
76
|
+
- Rakefile
|
77
|
+
- active_serializer.gemspec
|
78
|
+
- lib/active_serializer.rb
|
79
|
+
- lib/active_serializer/serializable.rb
|
80
|
+
- lib/active_serializer/serializable_hash.rb
|
81
|
+
- lib/active_serializer/serializable_object.rb
|
82
|
+
- lib/active_serializer/serialization_rules_validator.rb
|
83
|
+
- lib/active_serializer/serializers.rb
|
84
|
+
- lib/active_serializer/serializers/hash_serializer.rb
|
85
|
+
- lib/active_serializer/serializers/ignore_blank_hash_serializer.rb
|
86
|
+
- lib/active_serializer/serializers/object_serializer.rb
|
87
|
+
- lib/active_serializer/serializers/restrict_fields_object_serializer.rb
|
88
|
+
- lib/active_serializer/support/args_validator.rb
|
89
|
+
- lib/active_serializer/support/fake_object.rb
|
90
|
+
- lib/active_serializer/version.rb
|
91
|
+
- spec/active_serializer/serializable_hash_spec.rb
|
92
|
+
- spec/active_serializer/serializable_object_spec.rb
|
93
|
+
- spec/spec_helper.rb
|
94
|
+
homepage: http://github.com/droidlabs/active_serializer
|
95
|
+
licenses:
|
96
|
+
- MIT
|
97
|
+
post_install_message:
|
98
|
+
rdoc_options: []
|
99
|
+
require_paths:
|
100
|
+
- lib
|
101
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
102
|
+
requirements:
|
103
|
+
- - ! '>='
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
segments:
|
106
|
+
- 0
|
107
|
+
hash: 3700777157026269907
|
108
|
+
version: '0'
|
109
|
+
none: false
|
110
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
111
|
+
requirements:
|
112
|
+
- - ! '>='
|
113
|
+
- !ruby/object:Gem::Version
|
114
|
+
segments:
|
115
|
+
- 0
|
116
|
+
hash: 3700777157026269907
|
117
|
+
version: '0'
|
118
|
+
none: false
|
119
|
+
requirements: []
|
120
|
+
rubyforge_project:
|
121
|
+
rubygems_version: 1.8.23
|
122
|
+
signing_key:
|
123
|
+
specification_version: 3
|
124
|
+
summary: Adds simple DSL to convert ruby objects to hash
|
125
|
+
test_files:
|
126
|
+
- spec/active_serializer/serializable_hash_spec.rb
|
127
|
+
- spec/active_serializer/serializable_object_spec.rb
|
128
|
+
- spec/spec_helper.rb
|