├── .gitignore ├── Gemfile ├── LICENSE ├── OSSMETADATA ├── README.md ├── Rakefile ├── lib └── restful │ ├── jsonapi.rb │ └── jsonapi │ ├── active_model_serializer.rb │ ├── railtie.rb │ ├── restify_param.rb │ ├── serializable_errors.rb │ └── version.rb └── restful-jsonapi.gemspec /.gitignore: -------------------------------------------------------------------------------- 1 | /.bundle/ 2 | /.yardoc 3 | /Gemfile.lock 4 | /_yardoc/ 5 | /coverage/ 6 | /doc/ 7 | /pkg/ 8 | /spec/reports/ 9 | /tmp/ 10 | *.bundle 11 | *.so 12 | *.o 13 | *.a 14 | mkmf.log 15 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # Specify your gem's dependencies in restful-jsonapi.gemspec 4 | gemspec 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Netflix, Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /OSSMETADATA: -------------------------------------------------------------------------------- 1 | osslifecycle=active 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Restful::Jsonapi 2 | 3 | A temporary monkeypatch for JSONAPI support, both in request payload, and serializing the type without a namespace. 4 | 5 | [![Gem Version](https://badge.fury.io/rb/restful-jsonapi.svg)](http://badge.fury.io/rb/restful-jsonapi) 6 | 7 | 8 | ## Installation 9 | 10 | Add this line to your application's Gemfile: 11 | 12 | ```ruby 13 | gem 'restful-jsonapi' 14 | ``` 15 | 16 | And then execute: 17 | 18 | $ bundle 19 | 20 | Or install it yourself as: 21 | 22 | $ gem install restful-jsonapi 23 | 24 | ## Usage 25 | 26 | ``` 27 | class MovieTypesController < ApplicationController 28 | 29 | ... 30 | 31 | private 32 | 33 | def movie_type_params 34 | restify_param(:movie_type).require(:movie_type).permit( 35 | :id, 36 | :name, 37 | created_user: [ 38 | :id, 39 | :email 40 | ] 41 | end 42 | end 43 | ``` 44 | 45 | ## Contributing 46 | 47 | 1. Fork it ( https://github.com/[my-github-username]/restful-jsonapi/fork ) 48 | 2. Create your feature branch (`git checkout -b my-new-feature`) 49 | 3. Commit your changes (`git commit -am 'Add some feature'`) 50 | 4. Push to the branch (`git push origin my-new-feature`) 51 | 5. Create a new Pull Request 52 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require "bundler/gem_tasks" 2 | 3 | -------------------------------------------------------------------------------- /lib/restful/jsonapi.rb: -------------------------------------------------------------------------------- 1 | require "restful/jsonapi/version" 2 | require 'restful/jsonapi/railtie' if defined?(Rails) 3 | require 'restful/jsonapi/restify_param' 4 | require 'restful/jsonapi/serializable_errors' 5 | require 'restful/jsonapi/active_model_serializer' 6 | 7 | module Restful 8 | module Jsonapi 9 | # Good job! 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /lib/restful/jsonapi/active_model_serializer.rb: -------------------------------------------------------------------------------- 1 | module Restful 2 | module Jsonapi 3 | module ActiveModelSerializer 4 | extend ActiveSupport::Concern 5 | 6 | included do 7 | def type 8 | object.class.model_name.name.demodulize.pluralize.underscore 9 | end 10 | end 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /lib/restful/jsonapi/railtie.rb: -------------------------------------------------------------------------------- 1 | module Restful 2 | module Jsonapi 3 | class Railtie < Rails::Railtie 4 | initializer "restful-jsonapi.action_controller" do 5 | ActiveSupport.on_load(:action_controller) do 6 | include Restful::Jsonapi::RestifyParam 7 | include Restful::Jsonapi::SerializableErrors 8 | end 9 | end 10 | 11 | initializer "restful-jsonapi.active_model_serializer" do 12 | ActiveModel::Serializer.class_eval do 13 | include Restful::Jsonapi::ActiveModelSerializer 14 | end 15 | end if defined? ActiveModel::Serializer 16 | end 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /lib/restful/jsonapi/restify_param.rb: -------------------------------------------------------------------------------- 1 | module Restful 2 | module Jsonapi 3 | module RestifyParam 4 | extend ActiveSupport::Concern 5 | 6 | def restify_param(param_key) 7 | ActionController::Parameters.new(param_key => restify_data(param_key)) 8 | end 9 | 10 | private 11 | 12 | def restify_data(param_key, value = params) 13 | if value == params 14 | value = params.clone[:data] # leave params alone 15 | end 16 | new_params = ActionController::Parameters.new 17 | return new_params if value.nil? 18 | value.delete(:type) 19 | # relationships 20 | if value.has_key? :relationships 21 | value.delete(:relationships).each do |relationship_name, relationship_data| 22 | new_data = restify_relationship(relationship_name, relationship_data) 23 | new_params = new_params.merge(new_data.to_h) if new_data.present? 24 | end 25 | end 26 | # attributes 27 | attributes = value.has_key?(:attributes) ? value[:attributes] : value 28 | attributes = attributes.merge(id: value[:id]) if value[:id] 29 | attributes.transform_keys!(&:underscore) 30 | new_params = new_params.merge(attributes.to_unsafe_h) 31 | new_params 32 | end 33 | 34 | def restify_relationship(relationship_name, relationship_data) 35 | if data_is_present?(relationship_data[:data]) && relationship_data[:data].is_a?(Array) 36 | restify_has_many(relationship_name, relationship_data) 37 | elsif relationship_data.present? && relationship_data.has_key?(:data) 38 | restify_belongs_to(relationship_name, relationship_data) 39 | end 40 | end 41 | 42 | def restify_belongs_to(relationship_name, relationship_data) 43 | if relationship_data[:data].present? and relationship_data[:data].values_at(:attributes,:relationships).compact.length > 0 44 | relationship_key = relationship_name.to_s.underscore+"_attributes" 45 | {relationship_key => restify_data(relationship_name,relationship_data[:data])} 46 | else 47 | if relationship_data[:data].nil? || relationship_data[:data].empty? 48 | {"#{relationship_name.underscore}_id" => nil} 49 | else 50 | {"#{relationship_name.underscore}_id" => relationship_data[:data][:id]} 51 | end 52 | end 53 | end 54 | 55 | def restify_has_many(relationship_name, relationship_data) 56 | if data_is_present?(relationship_data[:data]) 57 | if relationship_data[:data].select{|d|d[:attributes]||d[:relationships]}.blank? 58 | relationship_key = relationship_name.to_s.singularize.underscore+"_ids" 59 | relationship = [] 60 | relationship_data[:data].each do |vv| 61 | relationship.push vv[:id] 62 | end 63 | {relationship_key => relationship} 64 | else 65 | relationship_key = relationship_name.to_s.underscore+"_attributes" 66 | relationship = [] 67 | relationship_data[:data].each do |vv| 68 | relationship.push restify_data(relationship_name,vv) 69 | end 70 | {relationship_key => relationship} 71 | end 72 | end 73 | end 74 | 75 | def data_is_present?(data) 76 | data.is_a? Array or data.present? 77 | end 78 | 79 | end 80 | end 81 | end 82 | -------------------------------------------------------------------------------- /lib/restful/jsonapi/serializable_errors.rb: -------------------------------------------------------------------------------- 1 | module Restful 2 | module Jsonapi 3 | module SerializableErrors 4 | extend ActiveSupport::Concern 5 | 6 | def serializable_errors(object) 7 | prefix = object.class.to_s.demodulize.underscore 8 | 9 | errors = object.errors.to_hash.each_with_object([]) do |(k, v), array| 10 | v.each do |msg| 11 | array.push(id: "#{prefix}.#{k}", title: msg) 12 | end 13 | end 14 | 15 | { errors: errors } 16 | end 17 | end 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /lib/restful/jsonapi/version.rb: -------------------------------------------------------------------------------- 1 | module Restful 2 | module Jsonapi 3 | VERSION = "1.0.7" 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /restful-jsonapi.gemspec: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | lib = File.expand_path('../lib', __FILE__) 3 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 4 | require 'restful/jsonapi/version' 5 | 6 | Gem::Specification.new do |spec| 7 | spec.name = "restful-jsonapi" 8 | spec.version = Restful::Jsonapi::VERSION 9 | spec.authors = ["Zach Wentz", "Ryan Johnston", "David Lee", "Adam Gross"] 10 | spec.email = ["zwentz@netflix.com", "ryanj@netflix.com", "dalee@netflix.com", "agross@netflix.com"] 11 | spec.summary = %q{Nice type and params for temporary JSONAPI support.} 12 | spec.description = %q{Nice type and params for temporary JSONAPI support.} 13 | spec.homepage = "https://github.com/Netflix/restful-jsonapi" 14 | spec.license = "MIT" 15 | 16 | spec.files = `git ls-files -z`.split("\x0") 17 | spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } 18 | spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) 19 | spec.require_paths = ["lib"] 20 | 21 | spec.add_dependency "rails", [">=4", "< 6"] 22 | 23 | spec.add_development_dependency "bundler", "~> 1.7" 24 | spec.add_development_dependency "rake", "~> 10.0" 25 | end 26 | --------------------------------------------------------------------------------