Coder Social home page Coder Social logo

grape-jsonapi's Introduction

CircleCI

Grape::Jsonapi

Use jsonapi-serializer with Grape.

Installation

Add grape-jsonapi to your Gemfile.

gem 'grape-jsonapi', require: "grape_jsonapi"

Usage

Tell your API to use Grape::Formatter::Jsonapi

class API < Grape::API
  content_type :jsonapi, "application/vnd.api+json"
  formatter :json, Grape::Formatter::Jsonapi
  formatter :jsonapi, Grape::Formatter::Jsonapi
end

Use render to specify JSONAPI options

get "/" do
  user = User.find("123")
  render user, include: [:account]
end

Use a custom serializer

get "/" do
  user = User.find("123")
  render user, serializer: 'CustomUserSerializer'
end

Or

get "/" do
  user = User.find("123")
  render CustomUserSerializer.new(user).serialized_json
end

Override metaand links properties

meta and links properties are usually defined per resource within your serializer (here and here)

However, if you need to override those properties, you can pass them as options when rendering your response:

user = User.find("123")
render user, meta: { pagination: { page: 1, total: 42 } }, links: { self: 'https://my-awesome.app.com/users/1' }

Model parser for response documentation

When using Grape with Swagger via grape-swagger, you can generate response documentation automatically via the provided following model parser:

# FastJsonapi serializer example

# app/serializers/base_serializer.rb
class BaseSerializer; end
# app/serializers/user_serializer.rb
class UserSerializer < BaseSerializer
  include JSONAPI::Serializer

  set_type :user
  has_many :orders

  attributes :name, :email
end

# config/initializers/grape_swagger.rb
GrapeSwagger.model_parsers.register(GrapeSwagger::Jsonapi::Parser, BaseSerializer)

# Your grape API endpoint
desc 'Get current user' do
  success code: 200, model: UserSerializer, message: 'The current user'
# [...]
end

Note that you need the grape-swagger gem for this to work, otherwise it will throw an error.

Credit

Code adapted from grape-jsonapi-resources

grape-jsonapi's People

Contributors

dblommesteijn avatar dependabot[bot] avatar emcousin avatar nathanvda avatar rromanchuk avatar vesan avatar vincentvanbush avatar waclock avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

grape-jsonapi's Issues

Integration with grape-swagger: questions

Thank for this library/gem. It made my integration/setup of a json:api API using swagger very easy.

I have two questions with regards to the integration with grape-swagger.

  • for a single item, the swagger documentation declares each field (attribute) as a string, how can I change that. Somehow I would like to link the original class as well, so it could deduce the types of the attributes? E.g. in PageSerializer declare some link to the Page model?
  • how can we better/easier add swagger documentation for arrays/list of pages, given that I add some links and meta data to the returned result?

Any tips or hints?

[Question] Best way to differentiate serializers that share type?

I'm probably overthinking this, but is there a cleaner way for specifying the serializer when you may have two serializers that share a type?

Here's standard usage when serializing a User instance.

#[...]
user = User.last # AR record
render user, { params: { current_user: current_user } }

Here's usage when I want to render the typical User instance, but using a thinner version of the serializer. Notice how it's a bit anti-pattern, probably because I wasn't sure how to cover this case.

#[...]
user = User.last # AR record
jsonapi_options = {}
render CompactUserSerializer.new(user, jsonapi_options).serialized_json

Respective serializers below

class UserSerializer < BaseSerializer
  include FastJsonapi::ObjectSerializer
  attributes :first_name, :last_name, :name, :bio, :email, :image_url
  
  # More complex/expensive serialization
  attribute :some_other_property do |user|
    user.some_other_property
  end

  attribute :current_user_following do |user, params|
    params[:current_user] ? params[:current_user].follows?(user) : false
  end

  # [...]

end
class CompactUserSerializer < BaseSerializer
  include FastJsonapi::ObjectSerializer
  set_type :user
  attributes :first_name, :last_name, :name, :bio, :image_url
end

This is probably bad practice to begin with because it's definitely not DRY, I wonder if i should just be utilizing fast_jsonapi's conditional attributes and utilize passed params to branch on the same serializer.

#[...]
user = User.last # AR record
render user, { params: { current_user: current_user, compact_version: true } }

Could probably also use a combination of mixins to make the serializer more readable

module AuthenticatedProperties
  attribute :foo, if: Proc.new { |record, params|
    params[:compact_version] == false
  }

  # [...]
end

class UserSerializer < BaseSerializer
  include FastJsonapi::ObjectSerializer
  include AuthenticatedProperties
  
  attributes :first_name, :last_name, :name, :bio, :image_url
  # [...]
end 

content-type not supported

Hello,

Thanks for the great gem. I'm currently using Grape + this gem, and I'm having some issues regarding the content-type. I can GET without problems, however patching/posting/putting is giving me problems:

error: "The provided content-type 'application/vnd.api+json' is not supported."

The CURL I'm doing is the following:

curl 'http://localhost:5000/api/v1/users/1' -H 'Origin: http://localhost:3000' -H 'access-token: JB3pVL_Zg5u3zO6V2PsLQg' -H 'client: D8QkWH9542kk9BtnUzZpgQ' -H 'Content-Type: application/vnd.api+json' -H 'Accept: application/vnd.api+json' -H 'expiry: 1554285246' -H 'uid: [email protected]' -H 'Referer: http://localhost:3000/profile' -H 'token-type: Bearer' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.75 Safari/537.36' --data-binary '{"data":{"id":1,"type":"user","attributes":{"test":true}}}' --compressed

Uninitialized Constant Grape::Formatter::Jsonapi

Hello and thank you for this great gem.

I'm just implementing this formatter, but it's not initializing.

Uninitialized Constant Grape::Formatter::Jsonapi

Bundler: 2.2.24
Rubygems: 3.2.25
Both are latest

The gem is quite simple, yet I can't parse the problem myself. My setup is identical to the readme, only my first class using Grape::API is one module deeper for versioning purposes. I.e.,

API
-Base.rb *<---Here're the three lines from the readme inside of module API and class Base < Grape::API
--V1
---Lots of API controllers

I suspect this is a problem with my implementation and/or bundler and rubygems, so no problem if you close it out right. I appreciate your help.

Is Rails dependency really necessary?

First of all, thank you for this gem. :)

But is it really necessary to pull Rails as a dependency? I see that it's specified as "development" dependency in gemspec file, but there's an explicit require 'rails' statement in lib/grape_fast_jsonapi.rb:3, which prevents it from being used with, for example, Sinatra-based apps.

[Question] Any hints on best way to support swagger response/model parsers?

Basically i want to be able to support https://github.com/ruby-grape/grape-swagger#response-documentation-

It looks like you can provide custom parsers, but I haven't really dug much more into this
https://github.com/ruby-grape/grape-swagger#model_parsers

Just wondering if you have tried adding response support for swagger + grape + fast_jsonapi, or if there is an approach that isn't going to end up being a major headache?

Question: using render method for empty data

Good afternoon !

I have a question regarding an edge case that I am experiencing using the gem.

Context:
I am sometimes sending to the render method an empty array - if there are no objects to return - , and in addition some metadata passed as options:

Example:

response = []
metadata = {pagination: { page: 1, page_size: 2}}
render response, meta: metadata

I get in reply only

[]

This surprises me, because I was expecting the below reply, which seems for me consistent with the jsonapi specification for empty data:

{
  "data": [],
  "meta": {
    "pagination": {
      "page": 1,
      "page_size": 2
    }
  }
}

The [] answer is due to the fact that, by the implementation, serializable_class method will render nil on an empty array, thus the method serialize_resource will then perform a resource.map(&:serializable_hash), which ultimately leads to an empty array.

To override this, and get my expected answer payload, I have to do this little trick:

render data: response, meta: metadata

Questions:
To be sure that we both understand the same thing about the jsonapi specification for empty data, could you confirm that for empty array of data, the expected return of the render method should be:

{
  "data": []
}

If not, how should I use the render method for an empty array of data and my additional options ?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.