cerealizer 0.0.1

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 ADDED
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ coverage
6
+ InstalledFiles
7
+ lib/bundler/man
8
+ pkg
9
+ rdoc
10
+ spec/reports
11
+ test/tmp
12
+ test/version_tmp
13
+ tmp
14
+
15
+ # YARD artifacts
16
+ .yardoc
17
+ _yardoc
18
+ doc/
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in cerealizer.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,24 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ cerealizer (0.0.1)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ diff-lcs (1.1.3)
10
+ rspec (2.12.0)
11
+ rspec-core (~> 2.12.0)
12
+ rspec-expectations (~> 2.12.0)
13
+ rspec-mocks (~> 2.12.0)
14
+ rspec-core (2.12.2)
15
+ rspec-expectations (2.12.1)
16
+ diff-lcs (~> 1.1.3)
17
+ rspec-mocks (2.12.2)
18
+
19
+ PLATFORMS
20
+ ruby
21
+
22
+ DEPENDENCIES
23
+ cerealizer!
24
+ rspec (>= 2.9.0)
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Brad Gessler
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,87 @@
1
+ # Cerealizer
2
+
3
+ Serialize and deserialize data between models and JSON.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'cerealizer'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install cerealizer
18
+
19
+ ## Usage
20
+
21
+ Want to write a HATOAS API without a bunch of stuff between your model and the serializer? Consider the following code:
22
+
23
+ ```ruby
24
+ class FruitSerializer < Cerealizer::Base
25
+ key :owner_href
26
+ hey :href
27
+ key :color
28
+ key :private_tasting_note
29
+
30
+ def href
31
+ "/fruits/#{object.id}"
32
+ end
33
+
34
+ def href=(href)
35
+ _, object.id = href.split('/')
36
+ end
37
+
38
+ def owner_href
39
+ "/users/#{object.owner_id}"
40
+ end
41
+
42
+ def owner_href=(href)
43
+ _, object.owner_id = href.split('/')
44
+ end
45
+
46
+ # Only the owner of the Fruit can change the owner key or the admin.
47
+ def has_writeable_owner_href?
48
+ object.id == scope.id or scope.is_admin?
49
+ end
50
+
51
+ # Only the owner of the fruit can read the private tasting note.
52
+ def has_readable_private_tasting_note?
53
+ object.id == scope.id
54
+ end
55
+ end
56
+ ```
57
+
58
+ Now lets use it in some app code! Lets generate some hashes that our app can convert into JSON:
59
+
60
+ ```ruby
61
+ user = User.new(:id => 3)
62
+ owner = User.new(:id => 12)
63
+ fruit = Fruit.new(:owner_id => 12, id: => 8, color: => 'Orange')
64
+
65
+ FruitSerializer.new(fruit, user).to_hash
66
+ # => { :owner_href => '/users/12', href: => '/fruits/8', color: => 'Orange' }
67
+
68
+ FruitSerializer.new(fruit, owner).to_hash
69
+ # => { :owner_href => '/users/12', href: => '/fruits/8', color: => 'Orange', :private_tasting_note => nil }
70
+ ```
71
+
72
+ Meh, its OK. Lots of libraries already do this with minimal hacking. That's not why we wrote this lib; what we need is something that can deal with *writing* attributes back into the model.
73
+
74
+ ```ruby
75
+ FruitSerializer.new(fruit, user).write_keys(:owner_href => '/users/9000')
76
+ # => BOOM! Raise a Key::UnauthorizedWrite exception
77
+ ```
78
+
79
+ Now we can implement authorization logic at a key level for our resources. Nifty!
80
+
81
+ ## Contributing
82
+
83
+ 1. Fork it
84
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
85
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
86
+ 4. Push to the branch (`git push origin my-new-feature`)
87
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'cerealizer/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "cerealizer"
8
+ gem.version = Cerealizer::VERSION
9
+ gem.authors = ["Brad Gessler"]
10
+ gem.email = ["brad@polleverywhere.com"]
11
+ gem.description = %q{Serialize and deserialize classes and JSON.}
12
+ gem.summary = %q{Dive into the nitty gritty details of serializing and deserializing between objects and a hash.}
13
+ gem.homepage = "http://github.com/polleverywhere/cerealizer"
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+
20
+ gem.add_development_dependency 'rspec', '>= 2.9.0'
21
+ end
@@ -0,0 +1,3 @@
1
+ module Cerealizer
2
+ VERSION = "0.0.1"
3
+ end
data/lib/cerealizer.rb ADDED
@@ -0,0 +1,78 @@
1
+ require "cerealizer/version"
2
+
3
+ module Cerealizer
4
+ # Encapsulates information about keys.
5
+ class Key
6
+ attr_reader :name
7
+
8
+ def initialize(name)
9
+ @name = name
10
+ end
11
+ end
12
+
13
+ # Configure a serialize keys and deal with marshaling to and from JSON.
14
+ class Base
15
+ attr_reader :object, :scope
16
+
17
+ def initialize(object, scope)
18
+ @object, @scope = object, scope
19
+ self
20
+ end
21
+
22
+ def self.key(key)
23
+ keys.push Key.new(key)
24
+ end
25
+
26
+ def self.keys
27
+ @keys ||= []
28
+ end
29
+
30
+ # Call methods on the object that's being presented and create a flat
31
+ # hash for these mofos.
32
+ def serializable_hash
33
+ self.class.keys.inject Hash.new do |hash, key|
34
+ hash[key.name] = proxy_reader(key.name) if readable?(key.name)
35
+ hash
36
+ end
37
+ end
38
+
39
+ # Update the attrs on zie model.
40
+ def update_attributes(attrs={})
41
+ attrs.each { |key, value| proxy_writer(key, value) if writeable?(key.name) }
42
+ self
43
+ end
44
+
45
+ private
46
+ # TODO - Should the default be writable?
47
+ def writeable?(key)
48
+ meth = "has_writable_#{key}?"
49
+ self.respond_to?(meth) ? self.send(meth) : true
50
+ end
51
+
52
+ # TODO - Should the default be writable?
53
+ def readable?(key)
54
+ meth = "has_readable_#{key}?"
55
+ self.respond_to?(meth) ? self.send(meth) : true
56
+ end
57
+
58
+ # Look for methods locally that we want to use to proxy data between
59
+ # the object and its JSON format.
60
+ def proxy_reader(key)
61
+ if self.respond_to? key
62
+ self.send(key)
63
+ else
64
+ object.send(key)
65
+ end
66
+ end
67
+
68
+ # Proxy the writer to zie object.
69
+ def proxy_writer(key, *args)
70
+ meth = "#{key}="
71
+ if self.respond_to? meth
72
+ self.send(meth, *args)
73
+ else
74
+ object.send(meth, *args)
75
+ end
76
+ end
77
+ end
78
+ end
metadata ADDED
@@ -0,0 +1,72 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cerealizer
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Brad Gessler
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-02-08 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 2.9.0
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 2.9.0
30
+ description: Serialize and deserialize classes and JSON.
31
+ email:
32
+ - brad@polleverywhere.com
33
+ executables: []
34
+ extensions: []
35
+ extra_rdoc_files: []
36
+ files:
37
+ - .gitignore
38
+ - Gemfile
39
+ - Gemfile.lock
40
+ - LICENSE.txt
41
+ - README.md
42
+ - Rakefile
43
+ - cerealizer.gemspec
44
+ - lib/cerealizer.rb
45
+ - lib/cerealizer/version.rb
46
+ homepage: http://github.com/polleverywhere/cerealizer
47
+ licenses: []
48
+ post_install_message:
49
+ rdoc_options: []
50
+ require_paths:
51
+ - lib
52
+ required_ruby_version: !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ! '>='
56
+ - !ruby/object:Gem::Version
57
+ version: '0'
58
+ required_rubygems_version: !ruby/object:Gem::Requirement
59
+ none: false
60
+ requirements:
61
+ - - ! '>='
62
+ - !ruby/object:Gem::Version
63
+ version: '0'
64
+ requirements: []
65
+ rubyforge_project:
66
+ rubygems_version: 1.8.23
67
+ signing_key:
68
+ specification_version: 3
69
+ summary: Dive into the nitty gritty details of serializing and deserializing between
70
+ objects and a hash.
71
+ test_files: []
72
+ has_rdoc: