Recoded to use active_model_serializer parameter of models/arrays and added array support

This commit is contained in:
jrhe 2013-04-10 19:17:26 +01:00
parent a3416e51d4
commit 3b67bd5393
4 changed files with 130 additions and 45 deletions

View file

@ -1,4 +1,5 @@
require 'active_record'
require 'pry'
module Grape
module Formatter
@ -10,40 +11,52 @@ module Grape
ActiveModelSerializers.infer_serializers = true
def call(object, env)
@object = object
@env = env
@endpoint = env['api.endpoint']
def call(resource, env)
# @object = object
options = env['api.endpoint'].options[:route_options]
if object.is_a? ActiveRecord::Base and active_model_serializer?
options = endpoint.options[:route_options][:serializer_options] || {}
active_model_serializer.new(object).as_json options
serializer = serializer(endpoint, resource, options)
if serializer
serializer.to_json
else
Grape::Formatter::Json.call object, env
Grape::Formatter::Json.call resource, env
end
end
# options = endpoint.options[:route_options][:serializer_options] || {}
# serializer.new(object, options).to_json
# end
private
def active_model_serializer?
!!active_model_serializer
end
def serializer(endpoint, resource, options)
# default_options = controller.send(:default_serializer_options) || {}
options = {} #default_options.merge(options || {})
def active_model_serializer
route_options = endpoint.options[:route_options]
# Infer serializer name if its not set
if self.infer_serializers
route_options[:serializer] = @object.class.name unless route_options.has_key? :serializer
serializer = options.delete(:serializer) ||
(resource.respond_to?(:active_model_serializer) &&
resource.active_model_serializer)
return serializer unless serializer
if resource.respond_to?(:to_ary)
unless serializer <= ActiveModel::ArraySerializer
raise ArgumentError.new("#{serializer.name} is not an ArraySerializer. " +
"You may want to use the :each_serializer option instead.")
end
serializer = route_options[:serializer]
if serializer.instance_of? String or serializer.instance_of? Symbol
name = "#{serializer.to_s.camelize}Serializer"
serializer = Kernel.const_get(name)
if options[:root] != false && serializer.root != false
# the serializer for an Array is ActiveModel::ArraySerializer
options[:root] ||= serializer.root || resource.first.class.name.downcase.pluralize
end
serializer
end
# options[:scope] = controller.serialization_scope unless options.has_key?(:scope)
# options[:scope_name] = controller._serialization_scope
# options[:url_options] = controller.url_options
serializer.new(resource, options)
end
end
end

View file

@ -0,0 +1,74 @@
module Twitter
class API < Grape::API
version 'v1', :using => :header, :vendor => 'twitter'
format :json
helpers do
def current_user
@current_user ||= User.authorize!(env)
end
def authenticate!
error!('401 Unauthorized', 401) unless current_user
end
end
resource :statuses do
desc "Return a public timeline."
get :public_timeline do
Status.limit(20)
end
desc "Return a personal timeline."
get :home_timeline do
authenticate!
current_user.statuses.limit(20)
end
desc "Return a status."
params do
requires :id, :type => Integer, :desc => "Status id."
end
get ':id' do
Status.find(params[:id])
end
desc "Create a status."
params do
requires :status, :type => String, :desc => "Your status."
end
post do
authenticate!
Status.create!({
:user => current_user,
:text => params[:status]
})
end
desc "Update a status."
params do
requires :id, :type => String, :desc => "Status ID."
requires :status, :type => String, :desc => "Your status."
end
put ':id' do
authenticate!
current_user.statuses.find(params[:id]).update({
:user => current_user,
:text => params[:status]
})
end
desc "Delete a status."
params do
requires :id, :type => String, :desc => "Status ID."
end
delete ':id' do
authenticate!
current_user.statuses.find(params[:id]).destroy
end
end
end
end

View file

@ -27,10 +27,10 @@ describe Grape::ActiveModelSerializers do
end
it "should respond with proper content-type" do
subject.get("/home", :serializer => "user") do
subject.get("/home/users", :serializer => "user") do
{user: {first_name: "JR", last_name: "HE"}}
end
get("/home")
get("/home/users")
last_response.headers["Content-Type"].should == "application/json"
end
@ -40,33 +40,30 @@ describe Grape::ActiveModelSerializers do
end
get "/home"
last_response.body.should == '{:user=>{:first_name=>"JR", :last_name=>"HE"}}'
last_response.body.should == "{\"user\":{\"first_name\":\"JR\",\"last_name\":\"HE\"}}"
end
context "serializer inference is disabled" do
before do
Grape::Formatter::ActiveModelSerializers.infer_serializers = false
it "should serializer arrays of objects" do
subject.get("/home") do
user = User.new({first_name: 'JR', last_name: 'HE', email: 'contact@jrhe.co.uk'})
[user, user]
end
it "should NOT infer serializer when there is no serializer set" do
subject.get("/home") do
User.new({first_name: 'JR', last_name: 'HE', email: 'contact@jrhe.co.uk'})
end
get "/home"
last_response.body.should == "{\"user\":{\"created_at\":null,\"first_name\":\"JR\",\"id\":null,\"last_name\":\"HE\",\"updated_at\":null,\"username\":null}}"
end
get "/home"
last_response.body.should == "{\"users\":[{\"first_name\":\"JR\",\"last_name\":\"HE\"},{\"first_name\":\"JR\",\"last_name\":\"HE\"}]}"
end
[UserSerializer, 'user', :user].each do |serializer|
it "should render using serializer (#{serializer})" do
subject.get("/home", serializer: serializer) do
User.new({first_name: 'JR', last_name: 'HE', email: 'contact@jrhe.co.uk'})
end
# [User2Serializer, 'user2', :user2].each do |serializer|
# it "should render using serializer (#{serializer})" do
# subject.get("/home", serializer: serializer) do
# User.new({first_name: 'JR', last_name: 'HE', email: 'contact@jrhe.co.uk'})
# end
# get "/home"
# last_response.body.should == "{\"user\":{\"first_name\":\"JR\",\"last_name\":\"HE\"}}"
# end
# end
get "/home"
last_response.body.should == '{:user=>{:first_name=>"JR", :last_name=>"HE"}}'
end
end
end

View file

@ -13,6 +13,7 @@ require 'rspec'
require 'rack/test'
require "pry"
require 'nulldb_rspec'
# require 'plymouth'
include NullDB::RSpec::NullifiedDatabase