forked from rails-api/active_model_serializers
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
278 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
#!/usr/bin/env bash | ||
set -e | ||
|
||
case "$1" in | ||
|
||
start) | ||
config="${CONFIG_RU:-test/dummy/config.ru}" | ||
bundle exec ruby -Ilib -S rackup "$config" --daemonize --pid tmp/dummy_app.pid --warn --server webrick | ||
until [ -f 'tmp/dummy_app.pid' ]; do | ||
sleep 0.1 # give it time to start.. I don't know a better way | ||
done | ||
cat tmp/dummy_app.pid | ||
true | ||
;; | ||
|
||
stop) | ||
if [ -f 'tmp/dummy_app.pid' ]; then | ||
kill -TERM $(cat tmp/dummy_app.pid) | ||
else | ||
echo 'No pidfile' | ||
false | ||
fi | ||
;; | ||
|
||
status) | ||
if [ -f 'tmp/dummy_app.pid' ]; then | ||
kill -0 $(cat tmp/dummy_app.pid) | ||
[ "$?" -eq 0 ] | ||
else | ||
echo 'No pidfile' | ||
false | ||
fi | ||
;; | ||
|
||
*) | ||
echo "Usage: $0 [start|stop|status]" | ||
;; | ||
|
||
esac |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
# https://github.com/rails-api/active_model_serializers/pull/872 | ||
# approx ref 792fb8a9053f8db3c562dae4f40907a582dd1720 to test against | ||
require 'bundler/setup' | ||
|
||
require 'rails' | ||
require 'active_model' | ||
require 'active_support' | ||
require 'active_support/json' | ||
require 'action_controller' | ||
require 'action_controller/test_case' | ||
require 'action_controller/railtie' | ||
abort "Rails application already defined: #{Rails.application.class}" if Rails.application | ||
|
||
# ref: https://gist.github.com/bf4/8744473 | ||
class DummyApp < Rails::Application | ||
config.action_controller.perform_caching = ENV['CACHE_ON'] != 'off' | ||
config.action_controller.cache_store = :memory_store | ||
|
||
# Set up production configuration | ||
config.eager_load = true | ||
config.cache_classes = true | ||
|
||
config.active_support.test_order = :random | ||
config.secret_token = '1234' | ||
config.secret_key_base = 'abc123' | ||
config.logger = Logger.new(IO::NULL) | ||
|
||
class DummyLogger < ActiveSupport::Logger | ||
def initialize | ||
@file = StringIO.new | ||
super(@file) | ||
end | ||
|
||
def messages | ||
@file.rewind | ||
@file.read | ||
end | ||
end | ||
end | ||
|
||
require 'active_model_serializers' | ||
|
||
# Initialize app before any serializers are defined, for sanity's sake. | ||
# Otherwise, you have to manually set perform caching. | ||
# | ||
# Details: | ||
# | ||
# 1. Upon load, when AMS.config.perform_caching is true, | ||
# serializers inherit the cache store from ActiveModelSerializers.config.cache_store | ||
# 1. If the serializers are loaded before Rails is initialized (`Rails.application.initialize!`), | ||
# these values are nil, and are not applied to the already loaded serializers | ||
# 1. If Rails is initialized before any serializers are loaded, then the configs are set, | ||
# and are used when serializers are loaded | ||
# 1. In either case, `ActiveModelSerializers.config.cache_store`, and | ||
# `ActiveModelSerializers.config.perform_caching` can be set at any time before the serializers | ||
# are loaded, | ||
# e.g. `ActiveModel::Serializer.config.cache_store ||= | ||
# ActiveSupport::Cache.lookup_store(ActionController::Base.cache_store || | ||
# Rails.cache || :memory_store)` | ||
# and `ActiveModelSerializers.config.perform_caching = true` | ||
# 1. If the serializers are loaded before Rails is initialized, then, | ||
# you can set the `_cache` store directly on the serializers. | ||
# `ActiveModel::Serializer._cache ||= | ||
# ActiveSupport::Cache.lookup_store(ActionController::Base.cache_store || | ||
# Rails.cache || :memory_store` | ||
# is sufficient. | ||
# Setting `_cache` to a truthy value will cause the CachedSerializer | ||
# to consider it cached, which will apply to all serializers (bug? :bug: ) | ||
# | ||
# This happens, in part, because the cache store is set for a serializer | ||
# when `cache` is called, and cache is usually called when the serializer is defined. | ||
# | ||
# So, there's now a 'workaround', something to debug, and a starting point. | ||
Rails.application.initialize! | ||
|
||
require_relative 'fixtures' | ||
require_relative 'controllers' | ||
|
||
# Clear cache | ||
ActionController::Base.cache_store.clear | ||
|
||
# Test caching is on | ||
ActiveSupport::Cache::Store.logger = Logger.new(IO::NULL) # seems to be the best way | ||
# the below is used in some rails tests but isn't available/working in all versions, so far as I can tell | ||
# https://github.com/rails/rails/pull/15943 | ||
# ActiveSupport::Notifications.subscribe(/^cache_(.*)\.active_support$/) do |*args| | ||
# p ActiveSupport::Notifications::Event.new(*args) | ||
# end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
require File.expand_path(['..','app'].join(File::SEPARATOR), __FILE__) | ||
|
||
run Rails.application |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
class PostController < ActionController::Base | ||
POST = | ||
begin | ||
comment = Comment.new(id: 1, body: 'ZOMG A COMMENT') | ||
author = Author.new(id: 1, name: 'Joao Moura.') | ||
Post.new(id: 1, title: 'New Post', blog: nil, body: 'Body', comments: [comment], author: author) | ||
end | ||
|
||
def render_with_caching_serializer | ||
toggle_cache_status | ||
render json: POST, adapter: :json | ||
end | ||
|
||
def render_with_non_caching_serializer | ||
toggle_cache_status | ||
render json: POST, serializer: CachingPostSerializer, adapter: :json | ||
end | ||
|
||
def render_cache_status | ||
toggle_cache_status | ||
# Uncomment to debug | ||
# STDERR.puts cache_store.class | ||
# STDERR.puts cache_dependencies | ||
render json: {caching: perform_caching}.to_json | ||
end | ||
|
||
private | ||
|
||
def toggle_cache_status | ||
case params[:on] | ||
when 'on'.freeze then self.perform_caching = true | ||
when 'off'.freeze then self.perform_caching = false | ||
else # no-op | ||
end | ||
end | ||
end | ||
|
||
Rails.application.routes.draw do | ||
get '/status(/:on)' => 'post#render_cache_status' | ||
get '/caching(/:on)' => 'post#render_with_caching_serializer' | ||
get '/non_caching(/:on)' => 'post#render_with_non_caching_serializer' | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
class AuthorSerializer < ActiveModel::Serializer | ||
attributes :id, :name | ||
|
||
has_many :posts, embed: :ids | ||
has_one :bio | ||
end | ||
|
||
class BlogSerializer < ActiveModel::Serializer | ||
attributes :id, :name | ||
end | ||
|
||
class CommentSerializer < ActiveModel::Serializer | ||
attributes :id, :body | ||
|
||
belongs_to :post | ||
belongs_to :author | ||
end | ||
|
||
class PostSerializer < ActiveModel::Serializer | ||
attributes :id, :title, :body | ||
|
||
has_many :comments, serializer: CommentSerializer | ||
belongs_to :blog, serializer: BlogSerializer | ||
belongs_to :author, serializer: AuthorSerializer | ||
|
||
def blog | ||
Blog.new(id: 999, name: 'Custom blog') | ||
end | ||
end | ||
|
||
class CachingAuthorSerializer < AuthorSerializer | ||
cache key: 'writer', skip_digest: true | ||
end | ||
|
||
class CachingCommentSerializer < CommentSerializer | ||
cache expires_in: 1.day, skip_digest: true | ||
end | ||
|
||
class CachingPostSerializer < PostSerializer | ||
cache key: 'post', expires_in: 0.1, skip_digest: true | ||
belongs_to :blog, serializer: BlogSerializer | ||
belongs_to :author, serializer: CachingAuthorSerializer | ||
has_many :comments, serializer: CachingCommentSerializer | ||
end | ||
|
||
# ActiveModelSerializers::Model is a convenient | ||
# serializable class to inherit from when making | ||
# serializable non-activerecord objects. | ||
class BenchmarkModel | ||
include ActiveModel::Model | ||
include ActiveModel::Serializers::JSON | ||
|
||
attr_reader :attributes | ||
|
||
def initialize(attributes = {}) | ||
@attributes = attributes | ||
super | ||
end | ||
|
||
# Defaults to the downcased model name. | ||
def id | ||
attributes.fetch(:id) { self.class.name.downcase } | ||
end | ||
|
||
# Defaults to the downcased model name and updated_at | ||
def cache_key | ||
attributes.fetch(:cache_key) { "#{self.class.name.downcase}/#{id}-#{updated_at.strftime("%Y%m%d%H%M%S%9N")}" } | ||
end | ||
|
||
# Defaults to the time the serializer file was modified. | ||
def updated_at | ||
attributes.fetch(:updated_at) { File.mtime(__FILE__) } | ||
end | ||
|
||
def read_attribute_for_serialization(key) | ||
if key == :id || key == 'id' | ||
attributes.fetch(key) { id } | ||
else | ||
attributes[key] | ||
end | ||
end | ||
end | ||
|
||
class Comment < BenchmarkModel | ||
attr_accessor :id, :body | ||
|
||
def cache_key | ||
"#{self.class.name.downcase}/#{id}" | ||
end | ||
end | ||
|
||
class Author < BenchmarkModel | ||
attr_accessor :id, :name, :posts | ||
end | ||
|
||
class Post < BenchmarkModel | ||
attr_accessor :id, :title, :body, :comments, :blog, :author | ||
|
||
def cache_key | ||
'benchmarking::post/1-20151215212620000000000' | ||
end | ||
end | ||
|
||
class Blog < BenchmarkModel | ||
attr_accessor :id, :name | ||
end |