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