cached_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.
- checksums.yaml +7 -0
- data/Gemfile +15 -0
- data/LICENSE +21 -0
- data/MIT-LICENSE +20 -0
- data/README.md +121 -0
- data/Rakefile +27 -0
- data/lib/cached_serializer.rb +5 -0
- data/lib/cached_serializer/attr_serializer.rb +32 -0
- data/lib/cached_serializer/attr_serializer_collection.rb +46 -0
- data/lib/cached_serializer/base.rb +160 -0
- data/lib/cached_serializer/railtie.rb +4 -0
- data/lib/cached_serializer/version.rb +3 -0
- data/lib/tasks/cached_serializer_tasks.rake +4 -0
- metadata +83 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 164738a352a3d55ad7ad7efe859c9b4f5840d54f0e21d1ebe5ecbfccbdf16cb8
|
4
|
+
data.tar.gz: b0b6bdbe968c74de5cd8ad85d772190fa465f5b5c971706c0eb00d409e90ef26
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c86836b5aa5f676a4f39564f95565c4c3570fcc8063d7f85d0c22e28f78cf5f4acc3bfcd3f0c0594a38a5de5d78fbc774ce3caccb90130185c04f3b2173e5844
|
7
|
+
data.tar.gz: 275c53b05c3e82d78cdd4aa716b61c6c0465e480c96c22a3e1ca4b99875d2cb7705a6e78951973af07af5ebf463e55132ec7f7a1f53fcb6bc614fb3b503f15ad
|
data/Gemfile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
|
3
|
+
|
4
|
+
# Declare your gem's dependencies in cached_serializer.gemspec.
|
5
|
+
# Bundler will treat runtime dependencies like base dependencies, and
|
6
|
+
# development dependencies will be added by default to the :development group.
|
7
|
+
gemspec
|
8
|
+
|
9
|
+
# Declare any dependencies that are still in development here instead of in
|
10
|
+
# your gemspec. These might include edge Rails or gems from your path or
|
11
|
+
# Git. Remember to move these dependencies to your gemspec before releasing
|
12
|
+
# your gem to rubygems.org.
|
13
|
+
|
14
|
+
# To use a debugger
|
15
|
+
# gem 'byebug', group: [:development, :test]
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2019 Keegan Leitz
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2019 Keegan Leitz
|
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.md
ADDED
@@ -0,0 +1,121 @@
|
|
1
|
+
# CachedSerializer
|
2
|
+
|
3
|
+
A serializer for Rails models that prevents unnecessary lookups.
|
4
|
+
|
5
|
+
## Usage
|
6
|
+
|
7
|
+
The following example serializes a `User` model. By using certain macros, the
|
8
|
+
author can specify what values should be cached or recomputed when serializing
|
9
|
+
a model record. Serialized data is cached via `Rails.cache` (by the User's `id`
|
10
|
+
and specified attribute keys) so the serializer doesn't have to hit the DB for
|
11
|
+
every attribute. This can be desirable when some of the serialized data involves
|
12
|
+
long-running queries, relationship-heavy calculations, etc.
|
13
|
+
|
14
|
+
```rb
|
15
|
+
class UserSerializer < CachedSerializer::Base
|
16
|
+
# Properties specified by `::columns` are called as-is on the model, and
|
17
|
+
# invalidated automatically when the model is saved with new values for these
|
18
|
+
# properties, by checking Rails' built-in `#email_changed?`/`#phone_changed?`
|
19
|
+
# /etc. dynamic methods on save. Allows you to serialize most simple straight-
|
20
|
+
# from-the-DB values without any extra effort.
|
21
|
+
columns :email, :phone
|
22
|
+
|
23
|
+
# Properties specified by `::constant` are are attributes that should never
|
24
|
+
# need to be recomputed. They will be cached ad infinitum (until the cache key
|
25
|
+
# is cleared, manually or otherwise).
|
26
|
+
#
|
27
|
+
# This will call `some_user.id` for the `:id` attribute, and
|
28
|
+
# `some_user.created_at` for the `:created_at` attribute. Consider the values
|
29
|
+
# for each to be cached FOREVER, and never recomputed.
|
30
|
+
constant :id, :created_at
|
31
|
+
|
32
|
+
# Alternatively, you can pass a block to `::constant`. This will use the
|
33
|
+
# result of the block as the value for the `:name` attribute. It will cache
|
34
|
+
# the value FOREVER, and never recompute it.
|
35
|
+
constant :name do |user|
|
36
|
+
"#{user.first_name} #{user.last_name}"
|
37
|
+
end
|
38
|
+
|
39
|
+
# Properties specified by `::volatile` are attributes that should always be
|
40
|
+
# recomputed every time a user is serialized, and will never be cached.
|
41
|
+
#
|
42
|
+
# This will call `some_user.token` for the `:token` attribute, and
|
43
|
+
# `some_user.updated_at` for the `:updated_at` attribute. It will ALWAYS
|
44
|
+
# recompute the values, EVERY time it serializes a user.
|
45
|
+
volatile :token, :updated_at
|
46
|
+
|
47
|
+
# Alternatively, you can pass a block to `::volatile`. This will use the
|
48
|
+
# result of the block as the value for the `:time_on_platform` attribute. It
|
49
|
+
# will ALWAYS recompute the value, EVERY time it serializes a user.
|
50
|
+
volatile :time_on_platform do |user|
|
51
|
+
Time.zone.now.to_i - user.created_at.to_i
|
52
|
+
end
|
53
|
+
|
54
|
+
# Properties specified by `::computed` are attributes that should either be
|
55
|
+
# recomputed by the given block or drawn from the cache based on rules that
|
56
|
+
# you specify.
|
57
|
+
#
|
58
|
+
# You can specify columns that it depends on, such that when any of the
|
59
|
+
# columns change it will invalidate the cache for this serialized property. In
|
60
|
+
# this case, `:address` will only be recomputed when any of the supplied
|
61
|
+
# attributes (`:address_1`, `:address_2`, `:city`, etc.) change on the user
|
62
|
+
# record.
|
63
|
+
computed :address, columns: [:address_1, :address_2, :city, :state, :zip] do |user|
|
64
|
+
"#{user.address_1} #{user.address_2}, #{user.city}, #{user.state} #{user.zip}"
|
65
|
+
end
|
66
|
+
|
67
|
+
# You can also specify a `:recompute_if` proc/lambda. It will run
|
68
|
+
# `:recompute_if` every time a model is being recomputed, and if it returns
|
69
|
+
# `true` then it will recompute. Otherwise, it will use the cached result.
|
70
|
+
computed :active, recompute_if: ->(u) { u.last_logged_in_at > 1.week.ago } do |user|
|
71
|
+
user.purchases.where(created_at: 1.week.ago..Time.zone.now).present?
|
72
|
+
end
|
73
|
+
|
74
|
+
# Additionally, you can specify an `:expires_in` expiration duration. This
|
75
|
+
# will cache the result for one day after the last time the
|
76
|
+
# `:revenue_generated` attribute was recomputed.
|
77
|
+
computed :revenue_generated, expires_in: 1.week do |user|
|
78
|
+
user.offers.accepted.reduce(0) { |total, offer| total + offer.total_price }
|
79
|
+
end
|
80
|
+
|
81
|
+
# You can use any number of these cache conditions with `:compute`. For
|
82
|
+
# example, this will cache the result until `:foo` changes on the user, `:bar`
|
83
|
+
# changes on the user, `u.silly?` is `true` at the time of serialization, or
|
84
|
+
# it has been more than 10 seconds since the last time the `:silly` attribute
|
85
|
+
# was recomputed.
|
86
|
+
computed :silly, columns: [:foo, :bar], recompute_if: ->(u) { u.silly? }, expires_in: 10.seconds do |user|
|
87
|
+
rand(100)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
```
|
91
|
+
|
92
|
+
## Installation
|
93
|
+
|
94
|
+
Add this line to your application's `Gemfile`:
|
95
|
+
|
96
|
+
```ruby
|
97
|
+
gem 'cached_serializer'
|
98
|
+
```
|
99
|
+
|
100
|
+
Then `cd` into your project's directory and run:
|
101
|
+
|
102
|
+
```bash
|
103
|
+
bundle install
|
104
|
+
```
|
105
|
+
|
106
|
+
## Bug reports
|
107
|
+
|
108
|
+
If you encounter a bug, you can report it [here](https://github.com/kjleitz/cached_serializer/issues). Please include the following information, if possible:
|
109
|
+
|
110
|
+
- your Ruby version (`ruby --version`; if using multiple Rubies via `rvm` or similar, make sure you're in your project's directory when you run `ruby --version`)
|
111
|
+
- your Rails version (`cd` into your project's directory, then `bundle exec rails --version`)
|
112
|
+
- example code (which demonstrates the issue)
|
113
|
+
- your soul (for eating)
|
114
|
+
|
115
|
+
## Contributing
|
116
|
+
|
117
|
+
Bug reports and pull requests are welcome on GitHub at [https://github.com/kjleitz/cached_serializer](https://github.com/kjleitz/cached_serializer).
|
118
|
+
|
119
|
+
## License
|
120
|
+
|
121
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
@@ -0,0 +1,27 @@
|
|
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 = 'CachedSerializer'
|
12
|
+
rdoc.options << '--line-numbers'
|
13
|
+
rdoc.rdoc_files.include('README.md')
|
14
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
15
|
+
end
|
16
|
+
|
17
|
+
require 'bundler/gem_tasks'
|
18
|
+
|
19
|
+
require 'rake/testtask'
|
20
|
+
|
21
|
+
Rake::TestTask.new(:test) do |t|
|
22
|
+
t.libs << 'test'
|
23
|
+
t.pattern = 'test/**/*_test.rb'
|
24
|
+
t.verbose = false
|
25
|
+
end
|
26
|
+
|
27
|
+
task default: :test
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module CachedSerializer
|
2
|
+
class AttrSerializer
|
3
|
+
attr_accessor :attr_name, :recompute_ifs, :expires_in, :recompute
|
4
|
+
|
5
|
+
class << self
|
6
|
+
def cache_key(subject, attr_name)
|
7
|
+
"cached_serializer:#{subject.class.model_name.name.underscore}:#{subject.id}:#{attr_name}"
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize(attr_name, recompute_ifs = nil, :expires_in = nil, &recompute)
|
12
|
+
self.attr_name = attr_name
|
13
|
+
self.recompute_ifs = [recompute_ifs].flatten.compact
|
14
|
+
self.expires_in = expires_in
|
15
|
+
self.recompute = recompute || proc { |subj| subj.send(attr_name.to_sym) }
|
16
|
+
end
|
17
|
+
|
18
|
+
def serialize_for(subject)
|
19
|
+
{ attr_name.to_sym => serialized_value_for(subject) }
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def serialized_value_for(subject)
|
25
|
+
should_recompute = recompute_ifs.any? { |recompute_if| recompute_if.call(subject) }
|
26
|
+
cache_key = self.class.cache_key(subject, attr_name)
|
27
|
+
Rails.cache.fetch(cache_key, expires_in: expires_in, force: should_recompute) do
|
28
|
+
attr_serializer.recompute.call(subject)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module CachedSerializer
|
2
|
+
class AttrSerializerCollection
|
3
|
+
attr_accessor :collection
|
4
|
+
|
5
|
+
def initialize(collection = [])
|
6
|
+
self.collection = collection
|
7
|
+
end
|
8
|
+
|
9
|
+
def add(*attr_serializers)
|
10
|
+
attr_serializers.each do |attr_serializer|
|
11
|
+
existing = collection.find { |serializer| serializer.attr_name == attr_serializer.attr_name }
|
12
|
+
if existing
|
13
|
+
existing.recompute_ifs.concat(attr_serializer.recompute_ifs)
|
14
|
+
existing.recompute = attr_serializer.recompute # shadowed attrs override the blocks of previously-declared ones
|
15
|
+
existing.expires_in = attr_serializer.expires_in # shadowed attrs override the expires_in of previously-declared ones
|
16
|
+
else
|
17
|
+
existing << attr_serializer
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
alias_method :push, :add
|
23
|
+
|
24
|
+
def <<(item)
|
25
|
+
add(item)
|
26
|
+
end
|
27
|
+
|
28
|
+
def concat(items)
|
29
|
+
add(*items)
|
30
|
+
end
|
31
|
+
|
32
|
+
def method_missing(method, *args, &block)
|
33
|
+
collection.send(method, *args, &block)
|
34
|
+
end
|
35
|
+
|
36
|
+
def respond_to?(method, *args)
|
37
|
+
collection.respond_to?(method, *args)
|
38
|
+
end
|
39
|
+
|
40
|
+
def serialize_for(subject)
|
41
|
+
collection.reduce({}) do |memo, attr_serializer|
|
42
|
+
memo.merge(attr_serializer.serialize_for(subject))
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,160 @@
|
|
1
|
+
require "json"
|
2
|
+
require_relative "./attr_serializer"
|
3
|
+
require_relative "./attr_serializer_collection"
|
4
|
+
|
5
|
+
module CachedSerializer
|
6
|
+
class Base
|
7
|
+
attr_accessor :subject
|
8
|
+
|
9
|
+
@serializers = AttrSerializerCollection.new
|
10
|
+
|
11
|
+
class << self
|
12
|
+
def serializers
|
13
|
+
@serializers
|
14
|
+
end
|
15
|
+
|
16
|
+
# Example (in a UserSerializer):
|
17
|
+
#
|
18
|
+
# columns :email, :phone
|
19
|
+
#
|
20
|
+
# This will call `some_user.email` for the `:email` attribute, and
|
21
|
+
# `some_user.phone` for the `:phone` attribute. It will cache the value
|
22
|
+
# for each, until the attribute changes on the record.
|
23
|
+
#
|
24
|
+
def columns(*column_names)
|
25
|
+
column_names.each do |column_name|
|
26
|
+
serializers << AttrSerializer.new(column_name)
|
27
|
+
add_column_changed_cache_invalidator_callback(column_name, column_name)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Example (in a UserSerializer):
|
32
|
+
#
|
33
|
+
# constant :email, :phone
|
34
|
+
#
|
35
|
+
# This will call `some_user.email` for the `:email` attribute, and
|
36
|
+
# `some_user.phone` for the `:phone` attribute. It will cache the value
|
37
|
+
# for each FOREVER, and never recompute it.
|
38
|
+
#
|
39
|
+
# constant :name do |user|
|
40
|
+
# "#{user.first_name} #{user.last_name}"
|
41
|
+
# end
|
42
|
+
#
|
43
|
+
# This will use the result of the block as the value for the `:name`
|
44
|
+
# attribute. It will cache the value FOREVER, and never recompute it.
|
45
|
+
#
|
46
|
+
def constant(*attr_names, &recompute)
|
47
|
+
attr_names.each do |attr_name|
|
48
|
+
serializers << AttrSerializer.new(attr_name, &recompute)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# Example (in a UserSerializer):
|
53
|
+
#
|
54
|
+
# volatile :email, :phone
|
55
|
+
#
|
56
|
+
# This will call `some_user.email` for the `:email` attribute, and
|
57
|
+
# `some_user.phone` for the `:phone` attribute. It will ALWAYS recompute
|
58
|
+
# the values, EVERY time it serializes a user.
|
59
|
+
#
|
60
|
+
# volatile :name do |user|
|
61
|
+
# "#{user.first_name} #{user.last_name}"
|
62
|
+
# end
|
63
|
+
#
|
64
|
+
# This will use the result of the block as the value for the `:name`
|
65
|
+
# attribute. It will ALWAYS recompute the value, EVERY time it serializes
|
66
|
+
# a user.
|
67
|
+
#
|
68
|
+
def volatile(*attr_names, &recompute)
|
69
|
+
attr_names.each do |attr_name|
|
70
|
+
always_recompute = proc { |_subj| true }
|
71
|
+
serializers << AttrSerializer.new(attr_name, always_recompute, &recompute)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# Example (in a UserSerializer):
|
76
|
+
#
|
77
|
+
# computed :name, columns: [:first_name, :last_name] do |user|
|
78
|
+
# "#{user.first_name} #{user.last_name}"
|
79
|
+
# end
|
80
|
+
#
|
81
|
+
# This will use the result of the block as the value for the `:name`
|
82
|
+
# attribute. It will cache the result until either `:first_name` or
|
83
|
+
# `:last_name` changes on the user record.
|
84
|
+
#
|
85
|
+
# computed :active, recompute_if: ->(u) { u.last_logged_in_at > 1.week.ago } do |user|
|
86
|
+
# user.purchases.where(created_at: 1.week.ago..Time.zone.now).present?
|
87
|
+
# end
|
88
|
+
#
|
89
|
+
# This will use the result of the block as the value for the `:active`
|
90
|
+
# attribute. It will cache the result until the `recompute_if` proc/lambda
|
91
|
+
# returns `true`.
|
92
|
+
#
|
93
|
+
# computed :purchase_count, expires_in: 1.day do |user|
|
94
|
+
# user.purchases.count
|
95
|
+
# end
|
96
|
+
#
|
97
|
+
# This will use the result of the block as the value for the
|
98
|
+
# `:purchase_count` attribute. It will cache the result for one day after
|
99
|
+
# the last time the `:purchase_count` attribute was recomputed.
|
100
|
+
#
|
101
|
+
# computed :silly, columns: [:foo, :bar], recompute_if: ->(u) { u.silly? }, expires_in: 10.seconds do |user|
|
102
|
+
# rand(100)
|
103
|
+
# end
|
104
|
+
#
|
105
|
+
# This will use the result of the block as the value for the `:silly`
|
106
|
+
# attribute. It will cache the result until `:foo` changes on the user,
|
107
|
+
# `:bar` changes on the user, `u.silly?` at the time of serialization,
|
108
|
+
# or it has been more than 10 seconds since the last time the `:silly`
|
109
|
+
# attribute was recomputed.
|
110
|
+
#
|
111
|
+
def computed(attr_name, columns: [], recompute_if: nil, expires_in: nil, &recompute)
|
112
|
+
if (columns.empty? && !recompute_if && !expires_in)
|
113
|
+
raise ArgumentError, "Must provide :columns, :recompute_if, or :expires_in to a computed attribute setter"
|
114
|
+
end
|
115
|
+
serializers << AttrSerializer.new(attr_name, recompute_if, expires_in, &recompute)
|
116
|
+
columns.each do |column_name|
|
117
|
+
add_column_changed_cache_invalidator_callback(attr_name, column_name)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
private
|
122
|
+
|
123
|
+
def subject_class
|
124
|
+
@subject_class ||= self.class.to_s.gsub(/[Ss]erializer\z/, '').constantize
|
125
|
+
end
|
126
|
+
|
127
|
+
def add_column_changed_cache_invalidator_callback(attr_name, dependent_attr_name)
|
128
|
+
@already_added_callback ||= {}
|
129
|
+
@already_added_callback[attr_name.to_sym] ||= {}
|
130
|
+
return if @already_added_callback[attr_name.to_sym][dependent_attr_name.to_sym]
|
131
|
+
|
132
|
+
subject_class.class_eval do
|
133
|
+
after_commit(on: :save) do
|
134
|
+
if changes[dependent_attr_name.to_s]
|
135
|
+
Rails.cache.delete(CachedSerializer::AttrSerializer.cache_key(subject, attr_name))
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
@already_added_callback[attr_name.to_sym][dependent_attr_name.to_sym] = true
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def initialize(subject)
|
145
|
+
self.subject = subject
|
146
|
+
end
|
147
|
+
|
148
|
+
def to_h
|
149
|
+
self.class.serializers.serialize_for(subject)
|
150
|
+
end
|
151
|
+
|
152
|
+
def as_json
|
153
|
+
to_h
|
154
|
+
end
|
155
|
+
|
156
|
+
def to_json
|
157
|
+
JSON.generate(as_json)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
metadata
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: cached_serializer
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Keegan Leitz
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-10-18 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 4.2.6
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 4.2.6
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: sqlite3
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
description: A serializer for Rails models that prevents unnecessary lookups
|
42
|
+
email:
|
43
|
+
- keegan@openbay.com
|
44
|
+
executables: []
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- Gemfile
|
49
|
+
- LICENSE
|
50
|
+
- MIT-LICENSE
|
51
|
+
- README.md
|
52
|
+
- Rakefile
|
53
|
+
- lib/cached_serializer.rb
|
54
|
+
- lib/cached_serializer/attr_serializer.rb
|
55
|
+
- lib/cached_serializer/attr_serializer_collection.rb
|
56
|
+
- lib/cached_serializer/base.rb
|
57
|
+
- lib/cached_serializer/railtie.rb
|
58
|
+
- lib/cached_serializer/version.rb
|
59
|
+
- lib/tasks/cached_serializer_tasks.rake
|
60
|
+
homepage: https://github.com/kjleitz/cached_serializer
|
61
|
+
licenses:
|
62
|
+
- MIT
|
63
|
+
metadata: {}
|
64
|
+
post_install_message:
|
65
|
+
rdoc_options: []
|
66
|
+
require_paths:
|
67
|
+
- lib
|
68
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
69
|
+
requirements:
|
70
|
+
- - ">="
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: '0'
|
73
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
74
|
+
requirements:
|
75
|
+
- - ">="
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
requirements: []
|
79
|
+
rubygems_version: 3.0.6
|
80
|
+
signing_key:
|
81
|
+
specification_version: 4
|
82
|
+
summary: A serializer for Rails models that prevents unnecessary lookups
|
83
|
+
test_files: []
|