cerebris / jsonapi-resources-site Goto Github PK
View Code? Open in Web Editor NEWSource for the JSONAPI::Resources site
Home Page: jsonapi-resources.com
License: MIT License
Source for the JSONAPI::Resources site
Home Page: jsonapi-resources.com
License: MIT License
I followed the docs on flattening a Rails relationship. For completeness, let me copy-paste the code from the docs:
# Given Models
class Person < ActiveRecord::Base
has_many :spoken_languages
validates :name, :email, :spoken_languages, presence: true
end
class SpokenLanguage < ActiveRecord::Base
belongs_to :person, inverse_of: :spoken_languages
validates :person, :language_code, presence: true
end
# Resource with getters and setter
class PersonResource < JSONAPI::Resource
attributes :name, :email, :spoken_languages
# Getter
def spoken_languages
@model.spoken_languages.pluck(:language_code)
end
# Setter (because spoken_languages needed for creation)
def spoken_languages=(new_spoken_language_codes)
@model.spoken_languages.destroy_all
new_spoken_language_codes.each do |new_lang_code|
@model.spoken_languages.build(language_code: new_lang_code)
end
end
end
When GET /persons
is processed, the spoken languages are individually queried from the database for every person in the collection. I was able to optimize the queries by adding this code to PersonResource
:
def self.records_for_populate(options = {})
records_base(options).includes(:spoken_languages)
end
Is that the right thing to do here? If yes then you can consider to improve the documentation by including that snippet.
guide/serializer.html
suggests that we can do:
post = Post.find(1)
JSONAPI::ResourceSerializer.new(PostResource).serialize_to_hash(PostResource.new(post, nil))
But when I do the equivalent in 0.10.2, I get the error:
undefined method `serialize_to_hash'
for #<JSONAPI::ResourceSerializer:0x00007fae9ec1cbf0>
Looking through the source of JSONAPI::ResourceSerializer
, #object_hash
seems to be the currently-available method that meets that need. The code succeeds for me with the following change:
post = Post.find(1)
JSONAPI::ResourceSerializer.new(PostResource).object_hash(PostResource.new(post, nil), nil)
(Note that #object_hash
takes two arguments, so we pass nil
for the second.)
I would PR this change to the page, but I'm unsure of the correct changes for the rest of the page.
We're upgrading from 0.9.10 to 0.10.1
in one of our acceptance specs we saw a failure
{"exception"=>"undefined method `where' for []:Array",
"backtrace"=>
["/root/server/vendor/bundle/ruby/2.6.0/gems/jsonapi-resources-0.10.1/lib/jsonapi/active_relation_resource.rb:843:in `apply_filter'",
it turns out, it's added a filter[:id] = "57630ec8-3332-4be3-8421-6de45545f294"
where that uuid is coming from the resource identifier.
the reason there's an []
is that this is a plain old resource where we, naturally, cannot return an active record relation, but instead are returning an empty collection.
I've tried fiddling with class methods self.records
, self.records_base
, self.apply_filter
, self.apply_join
and instance methodsrecords_for
, records
, records_base
and stepped through quite a bunch of code, but haven't been able to figure out what exactly changed or how to handle it
e.g.
90: # @return [Hash{ResourceIdentity => {identity: => ResourceIdentity, cache: cache_field, attributes: => {name => value}}}]
91: # the ResourceInstances matching the filters, sorting, and pagination rules along with any request
92: # additional_field values
93: def find_fragments(filters, options = {})
filters
=> {:id=>"e57ed230-84e5-429c-806f-5e4e13af81ea"}
options
=> {:context=>
{:current_user=>
#<User:0x00007fba8499eb20
id: 1,
:fields=>{},
:filters=>{:id=>"e57ed230-84e5-429c-806f-5e4e13af81ea"},
:include_directives=>
#<JSONAPI::IncludeDirectives:0x00007fba849dd348
@include_directives_hash={:include_related=>{}},
@resource_klass=V1::SomeResource>,
:cache=>false}
probably this is related to cerebris/jsonapi-resources#1221 ?
The 0.9.x resource in question is defined something like below (we only interact with it by POST)
module PlainOldResource
module Extensions
# @override
def records(*)
[]
end
end
extend ActiveSupport::Concern
class_methods do
# @override
def updatable_fields(_context)
[]
end
end
included do |base|
base.extend ::PlainOldResource::Extensions
end
# @override
def id
if _model.respond_to?(:id)
_model.id
else
@id ||= SecureRandom.uuid
end
end
# @override
def created_at
@created_at ||= Time.now
end
# @override
alias_method :updated_at, :created_at
# @override
def records_for(association_name, _options = {})
_model.public_send(association_name)
end
# @override
# @see https://github.com/cerebris/jsonapi-resources/blob/v0.9.10/lib/jsonapi/resource.rb#L395-L425
def replace_attributes(data)
attributes = attributes_from(data)
assign_attributes attributes
end
def assign_attributes(attributes)
attributes.each do |key, value|
attribute_setter = "#{key}="
_model.public_send(attribute_setter, value)
end
end
# Finds attributes in the POST/PUT request to assign to the model.
#
# Override to add relationships or remove attributes
# @example
# def attributes_from(data)
# super.merge!(
# some_thing_ids: data[:to_many][:some_things],
# )
# end
def attributes_from(data)
attributes = data[:attributes].dup
data[:to_many].each do |key, value|
attributes["#{key}_ids"] = value
end
data[:to_one].each do |key, value|
attributes["#{key}_id"] = value
end
attributes
end
end
class ThingActionResource < BaseResource
include PlainOldResource
abstract
has_one :thing
attribute :comment
def fetchable_fields
[:id, :thing, :comment]
end
def replace_fields(data)
attributes = replace_attributes(data)
ensure_model_exists!(attributes)
authorize_action!(:create?)
perform
end
private
def assign_attributes(attributes)
super
_model.changed_by = current_user
end
def ensure_model_exists!(attributes)
return unless _model.thing.nil?
fail JSONAPI::Exceptions::RecordNotFound.new(attributes[:thing_id])
end
def perform
if _model.perform
:completed
else
fail JSONAPI::Exceptions::ValidationErrors.new(self)
end
end
def current_user
context[:current_user]
end
end
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.