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 'active_record'
require 'pry'
module Grape module Grape
module Formatter module Formatter
@ -10,40 +11,52 @@ module Grape
ActiveModelSerializers.infer_serializers = true ActiveModelSerializers.infer_serializers = true
def call(object, env) def call(resource, env)
@object = object # @object = object
@env = env options = env['api.endpoint'].options[:route_options]
@endpoint = env['api.endpoint']
if object.is_a? ActiveRecord::Base and active_model_serializer? serializer = serializer(endpoint, resource, options)
options = endpoint.options[:route_options][:serializer_options] || {}
active_model_serializer.new(object).as_json options if serializer
serializer.to_json
else else
Grape::Formatter::Json.call object, env Grape::Formatter::Json.call resource, env
end end
end end
# options = endpoint.options[:route_options][:serializer_options] || {}
# serializer.new(object, options).to_json
# end
private private
def active_model_serializer? def serializer(endpoint, resource, options)
!!active_model_serializer # default_options = controller.send(:default_serializer_options) || {}
end options = {} #default_options.merge(options || {})
def active_model_serializer serializer = options.delete(:serializer) ||
route_options = endpoint.options[:route_options] (resource.respond_to?(:active_model_serializer) &&
# Infer serializer name if its not set resource.active_model_serializer)
if self.infer_serializers
route_options[:serializer] = @object.class.name unless route_options.has_key? :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 end
serializer = route_options[:serializer] if options[:root] != false && serializer.root != false
# the serializer for an Array is ActiveModel::ArraySerializer
if serializer.instance_of? String or serializer.instance_of? Symbol options[:root] ||= serializer.root || resource.first.class.name.downcase.pluralize
name = "#{serializer.to_s.camelize}Serializer"
serializer = Kernel.const_get(name)
end end
serializer
end 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 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 end
it "should respond with proper content-type" do 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"}} {user: {first_name: "JR", last_name: "HE"}}
end end
get("/home") get("/home/users")
last_response.headers["Content-Type"].should == "application/json" last_response.headers["Content-Type"].should == "application/json"
end end
@ -40,33 +40,30 @@ describe Grape::ActiveModelSerializers do
end end
get "/home" 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 end
context "serializer inference is disabled" do it "should serializer arrays of objects" do
before do subject.get("/home") do
Grape::Formatter::ActiveModelSerializers.infer_serializers = false user = User.new({first_name: 'JR', last_name: 'HE', email: 'contact@jrhe.co.uk'})
[user, user]
end end
it "should NOT infer serializer when there is no serializer set" do get "/home"
subject.get("/home") do last_response.body.should == "{\"users\":[{\"first_name\":\"JR\",\"last_name\":\"HE\"},{\"first_name\":\"JR\",\"last_name\":\"HE\"}]}"
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
end end
[UserSerializer, 'user', :user].each do |serializer| # [User2Serializer, 'user2', :user2].each do |serializer|
it "should render using serializer (#{serializer})" do # it "should render using serializer (#{serializer})" do
subject.get("/home", serializer: serializer) do # subject.get("/home", serializer: serializer) do
User.new({first_name: 'JR', last_name: 'HE', email: 'contact@jrhe.co.uk'}) # User.new({first_name: 'JR', last_name: 'HE', email: 'contact@jrhe.co.uk'})
end # 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 end

View file

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