cerealizer 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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: