diff --git a/Gemfile b/Gemfile index 4d97071..fa75df1 100644 --- a/Gemfile +++ b/Gemfile @@ -1,18 +1,3 @@ source 'https://rubygems.org' gemspec - -group :test do - gem "rspec", "~> 2.12.0" - gem "rack-test" - gem "rake" - gem "activerecord-nulldb-adapter" -end - -group :development, :test do - gem "pry" - gem "pry-debugger" - gem "pry-rescue" - gem "pry-stack_explorer" - gem 'plymouth' -end diff --git a/Gemfile.lock b/Gemfile.lock index 77c2a79..b46a29c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -2,16 +2,12 @@ PATH remote: . specs: grape-active_model_serializers (0.1.0) - active_model_serializers - activerecord grape (~> 0.3) - i18n - tilt GEM remote: https://rubygems.org/ specs: - active_model_serializers (0.7.0) + active_model_serializers (0.8.1) activemodel (>= 3.0) activemodel (3.2.13) activesupport (= 3.2.13) @@ -28,18 +24,7 @@ GEM multi_json (~> 1.0) arel (3.0.2) backports (2.6.7) - binding_of_caller (0.7.1) - debug_inspector (>= 0.0.1) builder (3.0.4) - coderay (1.0.9) - columnize (0.3.6) - debug_inspector (0.0.2) - debugger (1.5.0) - columnize (>= 0.3.1) - debugger-linecache (~> 1.2.0) - debugger-ruby_core_source (~> 1.2.0) - debugger-linecache (1.2.0) - debugger-ruby_core_source (1.2.0) descendants_tracker (0.0.1) diff-lcs (1.1.3) grape (0.4.1) @@ -52,29 +37,10 @@ GEM rack-accept rack-mount virtus - hashie (2.0.3) + hashie (2.0.5) i18n (0.6.1) - interception (0.3) - method_source (0.8.1) - multi_json (1.7.2) + multi_json (1.7.3) multi_xml (0.5.3) - plymouth (0.3.3) - pry-exception_explorer (~> 0.1.7) - pry (0.9.12) - coderay (~> 1.0.5) - method_source (~> 0.8) - slop (~> 3.4) - pry-debugger (0.2.2) - debugger (~> 1.3) - pry (~> 0.9.10) - pry-exception_explorer (0.1.9) - pry-stack_explorer (>= 0.3.9) - pry-rescue (1.1.0) - interception (>= 0.3) - pry - pry-stack_explorer (0.4.9) - binding_of_caller (>= 0.7) - pry (~> 0.9.11) rack (1.5.2) rack-accept (0.4.5) rack (>= 0.4) @@ -91,8 +57,6 @@ GEM rspec-expectations (2.12.1) diff-lcs (~> 1.1.3) rspec-mocks (2.12.2) - slop (3.4.4) - tilt (1.3.6) tzinfo (0.3.37) virtus (0.5.4) backports (~> 2.6.1) @@ -102,13 +66,10 @@ PLATFORMS ruby DEPENDENCIES + active_model_serializers + activerecord activerecord-nulldb-adapter grape-active_model_serializers! - plymouth - pry - pry-debugger - pry-rescue - pry-stack_explorer rack-test rake rspec (~> 2.12.0) diff --git a/README.md b/README.md index fd1bc9a..584b528 100644 --- a/README.md +++ b/README.md @@ -64,7 +64,7 @@ Grape::Formatter::ActiveModelSerializers.infer_serializers = false ``` -### Manually specifying a serializer +### Manually specifying serializer options Serializers can be specified at a route level by with the serializer option. A serializer can be specified by passing the the serializer class or the serializer name. The following are equivalent: @@ -81,6 +81,27 @@ get "/home", :serializer => :home ... ``` +You can also set a serializer at the namespace level. This serializer can/will be overriden if a serilizer is also specified on the route. + +```ruby +namespace 'foo', :serializer => :bar do + get "/" do + # will use "bar" serializer + end + + get "/home", :serializer => :home do + # will use "home" serializer + end +end +``` + +Other standard options for `ActiveModel::Serializers` can be provided at either the namespace or route level with the same overriding behavior. + +```ruby +get "/home", :root => 'world', :each_serializer => :fancy_home +... +``` + ### Example diff --git a/grape-active_model_serializers.gemspec b/grape-active_model_serializers.gemspec index 21021b2..b5ab1bb 100644 --- a/grape-active_model_serializers.gemspec +++ b/grape-active_model_serializers.gemspec @@ -16,8 +16,11 @@ Gem::Specification.new do |gem| gem.version = Grape::ActiveModelSerializers::VERSION gem.add_dependency "grape", "~> 0.3" - gem.add_dependency "activerecord" - gem.add_dependency "active_model_serializers" - gem.add_dependency "tilt" - gem.add_dependency "i18n" + + gem.add_development_dependency "activerecord" + gem.add_development_dependency "active_model_serializers" + gem.add_development_dependency "rspec", "~> 2.12.0" + gem.add_development_dependency "rack-test" + gem.add_development_dependency "rake" + gem.add_development_dependency "activerecord-nulldb-adapter" end diff --git a/lib/grape-active_model_serializers.rb b/lib/grape-active_model_serializers.rb index f26ef11..7847623 100644 --- a/lib/grape-active_model_serializers.rb +++ b/lib/grape-active_model_serializers.rb @@ -1,5 +1,5 @@ require 'active_model_serializers' require 'grape' -require 'hashie/hash' +require 'grape/endpoint_extension' require "grape-active_model_serializers/version" -require "grape-active_model_serializers/formatter" \ No newline at end of file +require "grape-active_model_serializers/formatter" diff --git a/lib/grape-active_model_serializers/formatter.rb b/lib/grape-active_model_serializers/formatter.rb index 6704548..c0d8dae 100644 --- a/lib/grape-active_model_serializers/formatter.rb +++ b/lib/grape-active_model_serializers/formatter.rb @@ -1,21 +1,24 @@ require 'active_record' -require 'pry' module Grape module Formatter module ActiveModelSerializers class << self attr_accessor :infer_serializers - attr_reader :env attr_reader :endpoint ActiveModelSerializers.infer_serializers = true def call(resource, env) - # @object = object - options = env['api.endpoint'].options[:route_options] + @endpoint = env["api.endpoint"] + options = endpoint.namespace_options.merge(endpoint.route_options) - serializer = serializer(endpoint, resource, options) + if resource.is_a?(Array) && !resource.empty? + # ensure we have an root to fallback on + endpoint.controller_name = resource.first.class.name.underscore.pluralize + end + + serializer = ::ActiveModel::Serializer.build_json(endpoint, resource, options) if serializer serializer.to_json @@ -23,41 +26,6 @@ module Grape Grape::Formatter::Json.call resource, env end end - - # options = endpoint.options[:route_options][:serializer_options] || {} - # serializer.new(object, options).to_json - # end - - private - - def serializer(endpoint, resource, options) - # default_options = controller.send(:default_serializer_options) || {} - options = {} #default_options.merge(options || {}) - - 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 - - if options[:root] != false && serializer.root != false - # the serializer for an Array is ActiveModel::ArraySerializer - options[:root] ||= serializer.root || resource.first.class.name.underscore.pluralize - 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 diff --git a/lib/grape/active_model_serializers.rb b/lib/grape/active_model_serializers.rb deleted file mode 100644 index 3d0dcd5..0000000 --- a/lib/grape/active_model_serializers.rb +++ /dev/null @@ -1 +0,0 @@ -require 'grape-active_model_serializers' \ No newline at end of file diff --git a/lib/grape/endpoint_extension.rb b/lib/grape/endpoint_extension.rb new file mode 100644 index 0000000..dac398f --- /dev/null +++ b/lib/grape/endpoint_extension.rb @@ -0,0 +1,26 @@ +# +# Make the Grape::Endpoint quack like a ActionController +# +# This allows us to rely on the ActiveModel::Serializer#build_json method +# to lookup the approriate serializer. +# +module Grape + module EndpointExtension + attr_accessor :controller_name + + def namespace_options + settings[:namespace] ? settings[:namespace].options : {} + end + + def route_options + options[:route_options] + end + + def default_serializer_options; end + def serialization_scope; end + def _serialization_scope; end + def url_options; end + end + + Endpoint.send(:include, EndpointExtension) +end diff --git a/spec/grape_ams_spec.rb b/spec/grape_ams_spec.rb index 7bc2c64..c9f90b5 100644 --- a/spec/grape_ams_spec.rb +++ b/spec/grape_ams_spec.rb @@ -1,5 +1,6 @@ require 'spec_helper' require 'spec_fakes' +require "grape-active_model_serializers" # require 'active_model' describe Grape::ActiveModelSerializers do @@ -74,6 +75,17 @@ describe Grape::ActiveModelSerializers do end end + it "uses namespace options when provided" do + subject.namespace :admin, :serializer => UserSerializer do + get('/jeff') do + User.new(first_name: 'Jeff') + end + end + + get "/admin/jeff" + last_response.body.should == "{\"user\":{\"first_name\":\"Jeff\",\"last_name\":null}}" + end + # [User2Serializer, 'user2', :user2].each do |serializer| # it "should render using serializer (#{serializer})" do # subject.get("/home", serializer: serializer) do diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 32a1f2b..93ff130 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -5,15 +5,15 @@ require 'bundler' Bundler.setup :default, :test require 'active_support/core_ext/hash/conversions' +require 'active_record' require 'active_model' require "active_model_serializers" require "active_support/json" -require 'grape/active_model_serializers' require 'rspec' require 'rack/test' -require "pry" + +ActiveRecord::Base.establish_connection :adapter => :nulldb, :schema => 'db/schema.rb' require 'nulldb_rspec' -# require 'plymouth' include NullDB::RSpec::NullifiedDatabase