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.
Files changed (6) hide show
  1. data/.gitignore +2 -0
  2. data/Rakefile +21 -0
  3. data/VERSION +1 -0
  4. data/lib/attribute_serializer.rb +86 -0
  5. data/test.rb +100 -0
  6. metadata +68 -0
data/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ *.gemspec
2
+ pkg
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
+