attribute_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 +2 -0
- data/Rakefile +21 -0
- data/VERSION +1 -0
- data/lib/attribute_serializer.rb +86 -0
- data/test.rb +100 -0
- metadata +68 -0
data/.gitignore
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
task :default => [:test]
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'jeweler'
|
5
|
+
Jeweler::Tasks.new do |gs|
|
6
|
+
gs.name = "attribute_serializer"
|
7
|
+
gs.homepage = "http://github.com/quackingduck/attribute_serializer"
|
8
|
+
gs.summary = "Takes an object, serializes the attributes to an ordered hash based on a pre-defined schema"
|
9
|
+
gs.email = "myles@myles.id.au"
|
10
|
+
gs.authors = ["Myles Byrne"]
|
11
|
+
gs.add_development_dependency('riot', '>= 0.10.13')
|
12
|
+
gs.files.include %(lib/attribute_serializer.rb) # jewler used to include files in lib automatically, what happened?
|
13
|
+
end
|
14
|
+
Jeweler::GemcutterTasks.new
|
15
|
+
rescue LoadError
|
16
|
+
puts "Install jeweler to build gem"
|
17
|
+
end
|
18
|
+
|
19
|
+
task :test do
|
20
|
+
ruby '-rubygems', "test.rb"
|
21
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'delegate'
|
2
|
+
require 'active_support/ordered_hash'
|
3
|
+
|
4
|
+
# Implementation
|
5
|
+
module AttributeSerializer
|
6
|
+
|
7
|
+
extend self # check it out, singleton
|
8
|
+
|
9
|
+
class Context
|
10
|
+
|
11
|
+
def initialize(klass, attribs, &delegate_methods)
|
12
|
+
@attribs = attribs
|
13
|
+
@delegate_class = DelegateClass(klass)
|
14
|
+
@delegate_class.class_eval do
|
15
|
+
def formatee; __getobj__ end
|
16
|
+
def id; formatee.id end # DelegateClass was written before object_id became the new world order
|
17
|
+
end
|
18
|
+
@delegate_class.class_eval(&delegate_methods) if delegate_methods
|
19
|
+
end
|
20
|
+
|
21
|
+
def generate(object)
|
22
|
+
@delegate = @delegate_class.new(object)
|
23
|
+
ActiveSupport::OrderedHash.new.tap do |h|
|
24
|
+
@attribs.each do |attrib|
|
25
|
+
h[attrib.to_s] = @delegate.send(attrib)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
def contexts
|
33
|
+
@contexts ||= {}
|
34
|
+
end
|
35
|
+
|
36
|
+
def add_context_set(klass, context_name, attribs, &delegate_methods)
|
37
|
+
key = [klass, context_name]
|
38
|
+
contexts[key] = Context.new klass, attribs, &delegate_methods
|
39
|
+
end
|
40
|
+
|
41
|
+
def generate(context_name, object)
|
42
|
+
if object.is_a?(Array)
|
43
|
+
object.map { |o| generate_single(o.class, context_name, o) }
|
44
|
+
else
|
45
|
+
generate_single(object.class, context_name, object)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def generate_single(klass, context_name, object)
|
50
|
+
key = [klass, context_name]
|
51
|
+
raise ArgumentError, "no contextual attributes setup for #{klass}:#{context_name}" unless contexts.keys.include?(key)
|
52
|
+
contexts[key].generate(object)
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
# The interface
|
58
|
+
#
|
59
|
+
# A default formatter:
|
60
|
+
#
|
61
|
+
# AttributeSerializer BlogPost, %w(id created_at title body) do
|
62
|
+
# def body
|
63
|
+
# Rdiscount.new(formateee.body).to_html
|
64
|
+
# end
|
65
|
+
# end
|
66
|
+
#
|
67
|
+
# Then call with:
|
68
|
+
#
|
69
|
+
# AttributeSerializer @post
|
70
|
+
#
|
71
|
+
# You can also define other formatters
|
72
|
+
#
|
73
|
+
# AttributeSerializer BlogPost, :summary, %w(id created_at title)
|
74
|
+
#
|
75
|
+
# And you AttributeSerializer can produce formatted collections:
|
76
|
+
#
|
77
|
+
# AttributeSerializer @posts, :summary
|
78
|
+
#
|
79
|
+
def AttributeSerializer(*args, &blk)
|
80
|
+
if args.first.is_a?(Class)
|
81
|
+
klass, context_name, attribs = (args.size == 3) ? args : [args[0], :default, args[1]]
|
82
|
+
AttributeSerializer.add_context_set klass, context_name, attribs, &blk
|
83
|
+
else
|
84
|
+
AttributeSerializer.generate(args[1] || :default, args[0])
|
85
|
+
end
|
86
|
+
end
|
data/test.rb
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
require 'riot'
|
2
|
+
require 'lib/attribute_serializer'
|
3
|
+
|
4
|
+
def OHash &blk
|
5
|
+
ActiveSupport::OrderedHash.new.tap(&blk)
|
6
|
+
end
|
7
|
+
|
8
|
+
Class.class_eval do
|
9
|
+
def create(hash)
|
10
|
+
self.new.tap do |o| hash.each { |k,v| o.send("#{k}=", v) } end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class Author
|
15
|
+
attr_accessor :name, :email
|
16
|
+
end
|
17
|
+
|
18
|
+
class BlogPost
|
19
|
+
attr_accessor :id, :title, :body, :author
|
20
|
+
end
|
21
|
+
|
22
|
+
context "Formatable object, default formator" do
|
23
|
+
setup do
|
24
|
+
AttributeSerializer BlogPost, %w(id title body)
|
25
|
+
|
26
|
+
BlogPost.create(
|
27
|
+
:id => 1,
|
28
|
+
:title => "Contextual Attributes",
|
29
|
+
:body => "The layer you've always wanted for generating your json"
|
30
|
+
)
|
31
|
+
end
|
32
|
+
|
33
|
+
asserts('produces the correct hash') do
|
34
|
+
AttributeSerializer topic # equivanlent to AttributeSerializer(topic,:default)
|
35
|
+
end.equals(OHash { |h|
|
36
|
+
h['id'] = 1
|
37
|
+
h['title'] = "Contextual Attributes"
|
38
|
+
h['body'] = "The layer you've always wanted for generating your json"
|
39
|
+
})
|
40
|
+
end
|
41
|
+
|
42
|
+
context "Nested formatable attrib" do
|
43
|
+
setup do
|
44
|
+
AttributeSerializer Author, %w(name email)
|
45
|
+
|
46
|
+
AttributeSerializer BlogPost, %w(id author) do
|
47
|
+
# no implicit support for nesting, intentionally
|
48
|
+
def author
|
49
|
+
AttributeSerializer formatee.author
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
BlogPost.create(
|
54
|
+
:id => 1,
|
55
|
+
:author => Author.create(
|
56
|
+
:name => "Myles",
|
57
|
+
:email => "myles@"
|
58
|
+
)
|
59
|
+
)
|
60
|
+
end
|
61
|
+
|
62
|
+
asserts('produces the correct hash') { AttributeSerializer(topic, :default) }.
|
63
|
+
equals(OHash { |h|
|
64
|
+
h['id'] = 1
|
65
|
+
h['author'] = OHash do |h|
|
66
|
+
h['name'] = "Myles"
|
67
|
+
h['email'] = "myles@"
|
68
|
+
end
|
69
|
+
})
|
70
|
+
end
|
71
|
+
|
72
|
+
context "Array of formatable objects" do
|
73
|
+
setup do
|
74
|
+
AttributeSerializer Author, %w(name email)
|
75
|
+
[ Author.create(:name => "Myles", :email => 'myles@'),
|
76
|
+
Author.create(:name => "Gabriel", :email => 'gabriel@') ]
|
77
|
+
end
|
78
|
+
|
79
|
+
asserts('produces the correct hash') { AttributeSerializer(topic, :default) }.
|
80
|
+
equals([
|
81
|
+
OHash { |h| h['name'] = "Myles"; h['email'] = 'myles@' },
|
82
|
+
OHash { |h| h['name'] = "Gabriel"; h['email'] = 'gabriel@' }
|
83
|
+
])
|
84
|
+
end
|
85
|
+
|
86
|
+
context "A non-default formatter" do
|
87
|
+
setup do
|
88
|
+
AttributeSerializer BlogPost, :summary, %w(id title)
|
89
|
+
BlogPost.create(
|
90
|
+
:id => 1,
|
91
|
+
:title => "Contextual Attributes",
|
92
|
+
:body => "The layer you've always wanted for generating your json"
|
93
|
+
)
|
94
|
+
end
|
95
|
+
|
96
|
+
asserts('produces the correct hash') { AttributeSerializer(topic, :summary) }.
|
97
|
+
equals(
|
98
|
+
OHash { |h| h['id'] = 1; h['title'] = "Contextual Attributes" }
|
99
|
+
)
|
100
|
+
end
|
metadata
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: attribute_serializer
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Myles Byrne
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2010-03-17 00:00:00 -05:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: riot
|
17
|
+
type: :development
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.10.13
|
24
|
+
version:
|
25
|
+
description:
|
26
|
+
email: myles@myles.id.au
|
27
|
+
executables: []
|
28
|
+
|
29
|
+
extensions: []
|
30
|
+
|
31
|
+
extra_rdoc_files: []
|
32
|
+
|
33
|
+
files:
|
34
|
+
- .gitignore
|
35
|
+
- Rakefile
|
36
|
+
- VERSION
|
37
|
+
- lib/attribute_serializer.rb
|
38
|
+
- test.rb
|
39
|
+
has_rdoc: true
|
40
|
+
homepage: http://github.com/quackingduck/attribute_serializer
|
41
|
+
licenses: []
|
42
|
+
|
43
|
+
post_install_message:
|
44
|
+
rdoc_options:
|
45
|
+
- --charset=UTF-8
|
46
|
+
require_paths:
|
47
|
+
- lib
|
48
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
49
|
+
requirements:
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: "0"
|
53
|
+
version:
|
54
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
55
|
+
requirements:
|
56
|
+
- - ">="
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
version: "0"
|
59
|
+
version:
|
60
|
+
requirements: []
|
61
|
+
|
62
|
+
rubyforge_project:
|
63
|
+
rubygems_version: 1.3.5
|
64
|
+
signing_key:
|
65
|
+
specification_version: 3
|
66
|
+
summary: Takes an object, serializes the attributes to an ordered hash based on a pre-defined schema
|
67
|
+
test_files: []
|
68
|
+
|