Research
Security News
Malicious npm Package Targets Solana Developers and Hijacks Funds
A malicious npm package targets Solana developers, rerouting funds in 2% of transactions to a hardcoded address.
So you say you need JSON:API support in your API...
- hey how did your hackathon go?
- not too bad, we got Babel set up
- yep…
- yep.
Here are some codes to help you build your next JSON:API compliable application easier and faster.
It's quite a hassle to setup a Ruby (Rails) web application to use and follow the JSON:API specifications.
The idea is simple, JSONAPI.rb offers a bunch of modules/mixins/glue, add them to your controllers, call some methods, profit!
Main goals:
The available features include:
fast_jsonapi
)Mainly by leveraging JSON:API Serializer and Ransack.
Thanks to everyone who worked on these amazing projects!
I'm grateful for the following companies for supporting this project!
Add this line to your application's Gemfile:
gem 'jsonapi.rb'
And then execute:
$ bundle
Or install it yourself as:
$ gem install jsonapi.rb
To enable the support for Rails, add this to an initializer:
# config/initializers/jsonapi.rb
require 'jsonapi'
JSONAPI::Rails.install!
This will register the mime type and the jsonapi
and jsonapi_errors
renderers.
The jsonapi
renderer will try to guess and resolve the serializer class based
on the object class, and if it is a collection, based on the first item in the
collection.
The naming scheme follows the ModuleName::ClassNameSerializer
for an instance
of the ModuleName::ClassName
.
Please follow the JSON:API Serializer guide on how to define a serializer.
To provide a different naming scheme implement the jsonapi_serializer_class
method in your resource or application controller.
Here's an example:
class CustomNamingController < ActionController::Base
# ...
private
def jsonapi_serializer_class(resource, is_collection)
JSONAPI::Rails.serializer_class(resource, is_collection)
rescue NameError
# your serializer class naming implementation
end
end
To provide extra parameters to the serializer,
implement the jsonapi_serializer_params
method.
Here's an example:
class CustomSerializerParamsController < ActionController::Base
# ...
private
def jsonapi_serializer_params
{
first_name_upcase: params[:upcase].present?
}
end
end
To provide meta information for a collection, provide the jsonapi_meta
controller method.
Here's an example:
class MyController < ActionController::Base
def index
render jsonapi: Model.all
end
private
def jsonapi_meta(resources)
{ total: resources.count } if resources.respond_to?(:count)
end
end
JSONAPI::Errors
provides a basic error handling. It will generate a valid
error response on exceptions from strong parameters, on generic errors or
when a record is not found.
To render the validation errors, just pass it to the error renderer.
To use an exception notifier, overwrite the
render_jsonapi_internal_server_error
method in your controller.
Here's an example:
class MyController < ActionController::Base
include JSONAPI::Errors
def update
record = Model.find(params[:id])
if record.update(params.require(:data).require(:attributes).permit!)
render jsonapi: record
else
render jsonapi_errors: record.errors, status: :unprocessable_entity
end
end
private
def render_jsonapi_internal_server_error(exception)
# Call your exception notifier here. Example:
# Raven.capture_exception(exception)
super(exception)
end
end
JSONAPI::Fetching
provides support on inclusion of related resources and
serialization of only specific fields.
Here's an example:
class MyController < ActionController::Base
include JSONAPI::Fetching
def index
render jsonapi: Model.all
end
private
# Overwrite/whitelist the includes
def jsonapi_include
super & ['wanted_attribute']
end
end
This allows you to run queries like:
$ curl -X GET /api/resources?fields[model]=model_attr,relationship
JSONAPI::Filtering
uses the power of
Ransack
to filter and sort over a collection of records.
The support is pretty extended and covers also relationships and composite
matchers.
Please add ransack
to your Gemfile
in order to benefit from this functionality!
Here's an example:
class MyController < ActionController::Base
include JSONAPI::Filtering
def index
allowed = [:model_attr, :relationship_attr]
jsonapi_filter(Model.all, allowed) do |filtered|
render jsonapi: filtered.result
end
end
end
This allows you to run queries like:
$ curl -X GET \
/api/resources?filter[model_attr_or_relationship_attr_cont_any]=value,name\
&sort=-model_attr,relationship_attr
You can use basic aggregations like min
, max
, avg
, sum
and count
when sorting. This is an optional feature since SQL aggregations require
grouping. To enable expressions along with filters, use the option flags:
options = { sort_with_expressions: true }
jsonapi_filter(User.all, allowed_fields, options) do |filtered|
render jsonapi: filtered.result.group('id').to_a
end
This allows you to run queries like:
$ curl -X GET /api/resources?sort=-model_attr_sum
JSONAPI::Pagination
provides support for paginating model record sets as long
as enumerables.
Here's an example:
class MyController < ActionController::Base
include JSONAPI::Pagination
def index
jsonapi_paginate(Model.all) do |paginated|
render jsonapi: paginated
end
end
end
This will generate the relevant pagination links.
If you want to add the pagination information to your meta,
use the jsonapi_pagination_meta
method:
def jsonapi_meta(resources)
pagination = jsonapi_pagination_meta(resources)
{ pagination: pagination } if pagination.present?
end
If you want to change the default number of items per page or define a custom logic to handle page size, use the
jsonapi_page_size
method:
def jsonapi_page_size(pagination_params)
per_page = pagination_params[:size].to_f.to_i
per_page = 30 if per_page > 30 || per_page < 1
per_page
end
JSONAPI::Deserialization
provides a helper to transform a JSONAPI
document
into a flat dictionary that can be used to update an ActiveRecord::Base
model.
Here's an example using the jsonapi_deserialize
helper:
class MyController < ActionController::Base
include JSONAPI::Deserialization
def update
model = MyModel.find(params[:id])
if model.update(jsonapi_deserialize(params, only: [:attr1, :rel_one]))
render jsonapi: model
else
render jsonapi_errors: model.errors, status: :unprocessable_entity
end
end
end
The jsonapi_deserialize
helper accepts the following options:
only
: returns exclusively attributes/relationship data in the provided listexcept
: returns exclusively attributes/relationship which are not in the listpolymorphic
: will add and detect the _type
attribute and class to the
defined list of polymorphic relationshipsThis functionality requires support for inflections. If your project uses
active_support
or rails
you don't need to do anything. Alternatively, we will
try to load a lightweight alternative to active_support/inflector
provided
by the dry/inflector
gem, please make sure it's added if you want to benefit
from this feature.
After checking out the repo, run bundle
to install dependencies.
Then, run rake spec
to run the tests.
To install this gem onto your local machine, run bundle exec rake install
.
To release a new version, update the version number in version.rb
, and then
run bundle exec rake release
, which will create a git tag for the version,
push git commits and tags, and push the .gem
file to
rubygems.org.
Bug reports and pull requests are welcome on GitHub at https://github.com/stas/jsonapi.rb
This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.
The gem is available as open source under the terms of the MIT License.
FAQs
Unknown package
We found that jsonapi.rb demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
A malicious npm package targets Solana developers, rerouting funds in 2% of transactions to a hardcoded address.
Security News
Research
Socket researchers have discovered malicious npm packages targeting crypto developers, stealing credentials and wallet data using spyware delivered through typosquats of popular cryptographic libraries.
Security News
Socket's package search now displays weekly downloads for npm packages, helping developers quickly assess popularity and make more informed decisions.