cerializable 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +48 -0
- data/Rakefile +34 -0
- data/lib/cerializable.rb +23 -0
- data/lib/cerializable/acts_as_cerializable.rb +86 -0
- data/lib/cerializable/cerializer.rb +9 -0
- data/lib/cerializable/version.rb +3 -0
- data/lib/tasks/cerializable_tasks.rake +4 -0
- data/test/acts_as_cerializable_test.rb +52 -0
- data/test/cerializable_test.rb +21 -0
- data/test/dummy/README.rdoc +28 -0
- data/test/dummy/Rakefile +6 -0
- data/test/dummy/app/assets/javascripts/application.js +13 -0
- data/test/dummy/app/assets/stylesheets/application.css +15 -0
- data/test/dummy/app/controllers/application_controller.rb +5 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/models/another_model.rb +9 -0
- data/test/dummy/app/models/model.rb +9 -0
- data/test/dummy/app/serializers/another_serializer.rb +6 -0
- data/test/dummy/app/serializers/model_serializer.rb +6 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/bin/bundle +3 -0
- data/test/dummy/bin/rails +4 -0
- data/test/dummy/bin/rake +4 -0
- data/test/dummy/bin/setup +29 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/config/application.rb +26 -0
- data/test/dummy/config/boot.rb +5 -0
- data/test/dummy/config/database.yml +25 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +41 -0
- data/test/dummy/config/environments/production.rb +79 -0
- data/test/dummy/config/environments/test.rb +42 -0
- data/test/dummy/config/initializers/assets.rb +11 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/test/dummy/config/initializers/inflections.rb +16 -0
- data/test/dummy/config/initializers/mime_types.rb +4 -0
- data/test/dummy/config/initializers/session_store.rb +3 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +23 -0
- data/test/dummy/config/routes.rb +56 -0
- data/test/dummy/config/secrets.yml +22 -0
- data/test/dummy/db/development.sqlite3 +0 -0
- data/test/dummy/db/migrate/20160629071239_create_models.rb +8 -0
- data/test/dummy/db/migrate/20160629190700_create_another_models.rb +8 -0
- data/test/dummy/db/schema.rb +26 -0
- data/test/dummy/db/test.sqlite3 +0 -0
- data/test/dummy/log/development.log +17 -0
- data/test/dummy/log/test.log +8614 -0
- data/test/dummy/public/404.html +67 -0
- data/test/dummy/public/422.html +67 -0
- data/test/dummy/public/500.html +66 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/dummy/test/fixtures/another_models.yml +11 -0
- data/test/dummy/test/fixtures/models.yml +11 -0
- data/test/dummy/test/models/another_model_test.rb +7 -0
- data/test/dummy/test/models/model_test.rb +7 -0
- data/test/test_helper.rb +20 -0
- metadata +184 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: ad9653d367e90c3a5193cc66829ee77c94522dcc
|
4
|
+
data.tar.gz: 15ce70990ee56482735914313d184b6f9ddec8c6
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 0bf553c69da8102511de80890a057d0e0d33cae3cf8a4b824ee5362877f20d9e1d598fb5e128572ff3f441d2ec6caa073850500da048a043f4294ff94bbdc608
|
7
|
+
data.tar.gz: 5ab2836756669bdbd69b110f8c93c5244ec18d92232d948ed9990ba252df78a6a83cb02a3e10cde6cfd46e0fc5978e4665b1377a108d688a38e96899b94195c2
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2016 Eric Arnold
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
= Cerializable
|
2
|
+
|
3
|
+
Cerializable provides flexible custom serialization for Rails models.
|
4
|
+
|
5
|
+
HOW TO USE
|
6
|
+
|
7
|
+
Add Cerializable to your Gemfile
|
8
|
+
|
9
|
+
gem 'cerializable', git: 'git://github.com/nativestranger/cerializable.git', branch: 'master'
|
10
|
+
|
11
|
+
Call 'acts_as_cerializable' in the models you wish to use Cerializable with.
|
12
|
+
|
13
|
+
class Comment < ApplicationRecord
|
14
|
+
acts_as_cerializable
|
15
|
+
end
|
16
|
+
|
17
|
+
Define corresponding serializer modules.
|
18
|
+
|
19
|
+
module CommentSerializer
|
20
|
+
|
21
|
+
include ActionView::Helpers::DateHelper
|
22
|
+
|
23
|
+
def run(comment, options)
|
24
|
+
{ id: comment.id,
|
25
|
+
user: { id: comment.user.id,
|
26
|
+
name: comment.user.name },
|
27
|
+
body: comment.body,
|
28
|
+
ancestorCount: comment.ancestor_count,
|
29
|
+
childComments: options[:children] || comment.child_comments.order(id: :desc).map { |c| c.serializable_hash },
|
30
|
+
createdAtInWords: "#{ time_ago_in_words(comment.created_at) } ago" }
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
The only requirement is that the 'run' method accepts two arguments and returns a hash which details how any given instance of your model is to be represented in JSON.
|
36
|
+
|
37
|
+
Pass custom options to #as_json, #to_json, or #serializable_hash and your models will use the #run method of their serializers to produce the result.
|
38
|
+
|
39
|
+
If you wish, you can specify the serializer module to use:
|
40
|
+
|
41
|
+
class Comment < ApplicationRecord
|
42
|
+
acts_as_cerializable serialize_with: SomeSerializerModule
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
TODO:
|
47
|
+
|
48
|
+
* Support #to_xml
|
data/Rakefile
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
begin
|
2
|
+
require 'bundler/setup'
|
3
|
+
rescue LoadError
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'rdoc/task'
|
8
|
+
|
9
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
10
|
+
rdoc.rdoc_dir = 'rdoc'
|
11
|
+
rdoc.title = 'Cerializable'
|
12
|
+
rdoc.options << '--line-numbers'
|
13
|
+
rdoc.rdoc_files.include('README.rdoc')
|
14
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
|
20
|
+
|
21
|
+
|
22
|
+
Bundler::GemHelper.install_tasks
|
23
|
+
|
24
|
+
require 'rake/testtask'
|
25
|
+
|
26
|
+
Rake::TestTask.new(:test) do |t|
|
27
|
+
t.libs << 'lib'
|
28
|
+
t.libs << 'test'
|
29
|
+
t.pattern = 'test/**/*_test.rb'
|
30
|
+
t.verbose = false
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
task default: :test
|
data/lib/cerializable.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'cerializable/cerializer'
|
2
|
+
require 'cerializable/acts_as_cerializable'
|
3
|
+
|
4
|
+
module Cerializable
|
5
|
+
|
6
|
+
def self.setup(options) # :nodoc:
|
7
|
+
# evaluate code in the context of the base class
|
8
|
+
options[:base].class_eval do
|
9
|
+
|
10
|
+
# define a 'cerializer' class method on the base class.
|
11
|
+
# it returns a cerializer object which does the serialization for instances of the class.
|
12
|
+
define_singleton_method :cerializer, proc {
|
13
|
+
@cerializer ||= Cerializer.new.tap do |cerializer|
|
14
|
+
serializer_module = options[:serialize_with] || "#{ options[:base].name }Serializer".constantize
|
15
|
+
# use class_eval to include the serializer module in the cerializer's eigenclass
|
16
|
+
cerializer.class_eval { include serializer_module }
|
17
|
+
end
|
18
|
+
}
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
module Cerializable
|
2
|
+
module ActsAsCerializable
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
# #serializable_hash delegates to the #run method of the model's 'cerializer' object.
|
7
|
+
#
|
8
|
+
# It accepts `:only`, `:except`, and `:methods` options which can be passed as a
|
9
|
+
# symbol or as an array of symbols.
|
10
|
+
#
|
11
|
+
# Using the `:only` option will return a hash that only has the specified keys.
|
12
|
+
#
|
13
|
+
# > comment.serializable_hash(only: :id)
|
14
|
+
# => { id: 1 }
|
15
|
+
#
|
16
|
+
# Using the `:except` option will return a hash that has all default keys except those specified.
|
17
|
+
#
|
18
|
+
# > comment.serializable_hash(except: [:id, :user_id])
|
19
|
+
# => { body: '...sushi? ;)', deleted_at: nil }
|
20
|
+
#
|
21
|
+
# Using the `:methods` option add will add a key and value for each method specified.
|
22
|
+
#
|
23
|
+
# The key is the method name as a symbol.
|
24
|
+
# The value is the return value given when calling the method on the model instance.
|
25
|
+
#
|
26
|
+
# The :methods option is processed after the :only and :except options.
|
27
|
+
#
|
28
|
+
# > comment.serializable_hash(only: id, methods: :hash])
|
29
|
+
# => { id: 1, hash: -2535926706119161824 }
|
30
|
+
#
|
31
|
+
def serializable_hash(options = {})
|
32
|
+
[:only, :except, :methods].each do |option_name|
|
33
|
+
break if options[:option_name].nil?
|
34
|
+
|
35
|
+
unless options[:option_name].is_a?(Symbol) || options[:option_name].is_a?(Array)
|
36
|
+
raise Exception, "'#{ option_name }' option must be of an Array or Symbol class."
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# serialize the instance using the class's cerializer object.
|
41
|
+
hash = self.class.cerializer.run(self, options)
|
42
|
+
|
43
|
+
# alter the hash according to the :only, :except, and :methods serialization options.
|
44
|
+
ensure_is_array = proc { |arg| arg.class.ancestors.include?(Array) ? arg : Array.new(1, arg) }
|
45
|
+
|
46
|
+
if except_options = options[:except] && ensure_is_array.call(options[:except])
|
47
|
+
except_options.each { |key| hash.delete(key) }
|
48
|
+
end
|
49
|
+
|
50
|
+
if only_options = options[:only] && ensure_is_array.call(options[:only])
|
51
|
+
hash.keys.each { |key| hash.delete(key) unless only_options.include?(key) }
|
52
|
+
end
|
53
|
+
|
54
|
+
if methods_options = options[:methods] && ensure_is_array.call(options[:methods])
|
55
|
+
methods_options.each { |method_name| hash[method_name] = self.send(method_name) }
|
56
|
+
end
|
57
|
+
|
58
|
+
hash
|
59
|
+
end
|
60
|
+
|
61
|
+
alias :as_json :serializable_hash
|
62
|
+
alias :to_json :serializable_hash
|
63
|
+
end
|
64
|
+
|
65
|
+
module ClassMethods
|
66
|
+
# `acts_as_cerializable` is used to declare that a
|
67
|
+
# model uses Cerializable for serialization.
|
68
|
+
#
|
69
|
+
# Unless a module is specified via the
|
70
|
+
# +serialize_with+ option, the base model's cerializer will attempt
|
71
|
+
# to include a module based on the model's name.
|
72
|
+
#
|
73
|
+
# For example, calling +Comment.acts_as_cerializable+ without a +serialize_with+
|
74
|
+
# option will cause Cerializable to look for a +CommentSerializer+.
|
75
|
+
#
|
76
|
+
# Calling +Comment.acts_as_cerializable+ +serialize_with:+ +MySerializer+
|
77
|
+
# will cause Cerializable to look for a +MySerializer+ instead.
|
78
|
+
def acts_as_cerializable(options = {})
|
79
|
+
Cerializable.setup(options.merge(base: self))
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
ActiveRecord::Base.send :include, Cerializable::ActsAsCerializable
|
@@ -0,0 +1,9 @@
|
|
1
|
+
module Cerializable
|
2
|
+
# Cerializable::Cerializer instances are used to do the serialization
|
3
|
+
# for models that use +acts_as_cerializable+.
|
4
|
+
#
|
5
|
+
# Each Cerializable::Cerializer instance includes the serializer
|
6
|
+
# module for its model.
|
7
|
+
class Cerializer
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class ActsAsCerializableTest < ActiveSupport::TestCase
|
4
|
+
|
5
|
+
test "ActiveRecord::Base#acts_as_cerializable" do
|
6
|
+
assert true, ActiveRecord::Base.respond_to?(:acts_as_cerializable)
|
7
|
+
end
|
8
|
+
|
9
|
+
# Ensure both models are serializing their instances as expected
|
10
|
+
[Model, AnotherModel].each { |model_class|
|
11
|
+
|
12
|
+
test "#{ model_class.name }#cerializer is defined" do
|
13
|
+
assert_equal model_class.send(:cerializer).class, Cerializable::Cerializer
|
14
|
+
assert true, model_class.send(:cerializer).respond_to?(:run)
|
15
|
+
end
|
16
|
+
|
17
|
+
expected_result = model_class.send(:default_json_representation)
|
18
|
+
[:serializable_hash, :as_json, :to_json].each do |method_name|
|
19
|
+
|
20
|
+
test "#{ model_class.name.downcase }##{ method_name } works as expected" do
|
21
|
+
instance = model_class.send(:new)
|
22
|
+
|
23
|
+
assert_equal instance.send(method_name), expected_result
|
24
|
+
|
25
|
+
# except option
|
26
|
+
assert_equal instance.send(method_name, except: :arbitraryKey1), expected_result.except(:arbitraryKey1)
|
27
|
+
|
28
|
+
assert_equal instance.send(method_name, except: [:arbitraryKey1, :arbitraryKey2]),
|
29
|
+
expected_result.except(:arbitraryKey1, :arbitraryKey2)
|
30
|
+
|
31
|
+
# only option
|
32
|
+
assert_equal instance.send(method_name, only: :arbitraryKey1), expected_result.slice(:arbitraryKey1)
|
33
|
+
|
34
|
+
assert_equal instance.send(method_name, only: [:arbitraryKey1, :arbitraryKey2]),
|
35
|
+
expected_result.slice(:arbitraryKey1, :arbitraryKey2)
|
36
|
+
|
37
|
+
# method option
|
38
|
+
assert_equal instance.send(method_name, methods: :object_id),
|
39
|
+
expected_result.merge(object_id: instance.object_id)
|
40
|
+
|
41
|
+
assert_equal instance.send(method_name, methods: [:object_id, :hash]),
|
42
|
+
expected_result.merge(object_id: instance.object_id, hash: instance.hash)
|
43
|
+
|
44
|
+
# custom option
|
45
|
+
assert_equal instance.send(method_name, custom_option: true),
|
46
|
+
expected_result.merge(customOption: '( ͡° ͜ʖ ͡°)')
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
}
|
51
|
+
|
52
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class CerializableTest < ActiveSupport::TestCase
|
4
|
+
|
5
|
+
test "Cerializable is defined" do
|
6
|
+
assert_kind_of Module, Cerializable
|
7
|
+
end
|
8
|
+
|
9
|
+
test "Cerializable#setup is defined" do
|
10
|
+
assert true, Cerializable.respond_to?(:setup)
|
11
|
+
end
|
12
|
+
|
13
|
+
test "Cerializable::Cerializer is defined" do
|
14
|
+
assert_kind_of Class, Cerializable::Cerializer
|
15
|
+
end
|
16
|
+
|
17
|
+
test "Cerializable::ActsAsCerializable is defined" do
|
18
|
+
assert_kind_of Module, Cerializable::ActsAsCerializable
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
== README
|
2
|
+
|
3
|
+
This README would normally document whatever steps are necessary to get the
|
4
|
+
application up and running.
|
5
|
+
|
6
|
+
Things you may want to cover:
|
7
|
+
|
8
|
+
* Ruby version
|
9
|
+
|
10
|
+
* System dependencies
|
11
|
+
|
12
|
+
* Configuration
|
13
|
+
|
14
|
+
* Database creation
|
15
|
+
|
16
|
+
* Database initialization
|
17
|
+
|
18
|
+
* How to run the test suite
|
19
|
+
|
20
|
+
* Services (job queues, cache servers, search engines, etc.)
|
21
|
+
|
22
|
+
* Deployment instructions
|
23
|
+
|
24
|
+
* ...
|
25
|
+
|
26
|
+
|
27
|
+
Please feel free to use a different markup language if you do not plan to run
|
28
|
+
<tt>rake doc:app</tt>.
|
data/test/dummy/Rakefile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
// This is a manifest file that'll be compiled into application.js, which will include all the files
|
2
|
+
// listed below.
|
3
|
+
//
|
4
|
+
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
|
5
|
+
// or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
|
6
|
+
//
|
7
|
+
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
|
8
|
+
// compiled file.
|
9
|
+
//
|
10
|
+
// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
|
11
|
+
// about supported directives.
|
12
|
+
//
|
13
|
+
//= require_tree .
|
@@ -0,0 +1,15 @@
|
|
1
|
+
/*
|
2
|
+
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
3
|
+
* listed below.
|
4
|
+
*
|
5
|
+
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
6
|
+
* or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
|
7
|
+
*
|
8
|
+
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
|
9
|
+
* compiled file so the styles you add here take precedence over styles defined in any styles
|
10
|
+
* defined in the other CSS/SCSS files in this directory. It is generally better to create a new
|
11
|
+
* file per style scope.
|
12
|
+
*
|
13
|
+
*= require_tree .
|
14
|
+
*= require_self
|
15
|
+
*/
|
@@ -0,0 +1,9 @@
|
|
1
|
+
class AnotherModel < ActiveRecord::Base
|
2
|
+
# the :serialize_with option allows you to specify a serialization module
|
3
|
+
acts_as_cerializable serialize_with: AnotherSerializer
|
4
|
+
|
5
|
+
# this is here just to make testing easier
|
6
|
+
def self.default_json_representation
|
7
|
+
{ arbitraryKey3: 'arbitrary value', arbitraryKey4: 'another arbitrary value' }
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
class Model < ActiveRecord::Base
|
2
|
+
# by default, Cerializable#setup will look for a module named "#{ model_name }Serializer"
|
3
|
+
acts_as_cerializable
|
4
|
+
|
5
|
+
# this is here just to make testing easier
|
6
|
+
def self.default_json_representation
|
7
|
+
{ arbitraryKey1: 'value', arbitraryKey2: 'another value' }
|
8
|
+
end
|
9
|
+
end
|