Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dpl936 json api - 2 #3990

Closed
wants to merge 45 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
e3d73b2
Added patch quoting
emrojo Nov 14, 2023
28e5d08
Current state
emrojo Nov 16, 2023
784bd2b
Fixes to pass tests
emrojo Dec 6, 2023
dab24c7
Linting
emrojo Dec 6, 2023
1cff17d
Merge branch 'develop' of https://github.com/sanger/sequencescape int…
emrojo Dec 6, 2023
1d53251
Added missing controller for new json api
emrojo Dec 7, 2023
6f12156
Some required files because of json api upgrade. It will need to sepa…
emrojo Dec 7, 2023
f005a01
Move each class to its own file
emrojo Dec 11, 2023
075642b
Merge branch 'develop' of https://github.com/sanger/sequencescape int…
emrojo Dec 14, 2023
ba89ba2
Merge branch 'develop' into dpl936_json_api
yoldas Dec 14, 2023
5e622e0
Merge branch 'develop' into dpl936_json_api
yoldas Dec 21, 2023
4849477
Merge remote-tracking branch 'refs/remotes/origin/dpl936_json_api' in…
yoldas Dec 21, 2023
a38e740
Rubocop
yoldas Dec 21, 2023
81e180b
Removed the old unused resource serializer patch foreign_key_types_an…
yoldas Dec 21, 2023
6cc357b
Prettier
yoldas Dec 21, 2023
d1bd7e8
Merge branch 'develop' into dpl936_json_api
yoldas Jan 18, 2024
fb7073d
Resolve codeclimate Resource has no descriptive comment
yoldas Jan 18, 2024
fab9edb
Override records_for_populate to preload default_includes
yoldas Jan 23, 2024
a1fefff
Include linkage data in relationships
yoldas Jan 23, 2024
1ec913e
Merge branch 'develop' into dpl936_json_api
yoldas Jan 23, 2024
555768c
Specify the relation name to use on the model
yoldas Jan 23, 2024
16d3be0
Remove linkage data from config; Add to specific resources if necessary
yoldas Jan 24, 2024
17ee6fd
Added linkage data option to request on aliquot
yoldas Jan 25, 2024
e956f95
Added linkage data option to submission, order, and request_type on r…
yoldas Jan 25, 2024
7acd4bf
Added linkage data option to purpose on labware resource
yoldas Jan 25, 2024
d43004d
Added linkage data option to has_many relationships on receptacle; th…
yoldas Jan 25, 2024
6027f83
Removed deprecated apply_includes
yoldas Jan 25, 2024
fd4fd58
Removed deprecated resolve_relationship_names_to_relations
yoldas Jan 25, 2024
adf7bf7
Started adding a concern for adding defaults to include param
yoldas Jan 25, 2024
537684c
Adding a concern module for default includes
yoldas Jan 25, 2024
f277249
Added uuid_object resource
yoldas Jan 26, 2024
b18b668
Prepend before action for handling default includes
yoldas Jan 28, 2024
b71c320
Added linkage data for pre_capture pool
yoldas Jan 28, 2024
6a6c70f
Removed resource as there is no need to access uuid_object directly
yoldas Jan 29, 2024
88cdd75
Add patch as mixin to allow calling the original method
yoldas Jan 29, 2024
f77c7e2
Add purpose to defaults to ensure inclusion as before
yoldas Jan 29, 2024
58224d7
Format default includes as include param to inject into parsing.
yoldas Jan 29, 2024
e9e7a49
Experiment default includes formatting
yoldas Jan 29, 2024
1361b4d
Refactor default inclusion parsing and resource checks
yoldas Jan 29, 2024
f1a5548
Rewrite include param to add default includes
yoldas Jan 29, 2024
c38efc1
Rubocop
yoldas Jan 29, 2024
d21cddb
Prettier
yoldas Jan 29, 2024
b2568f4
Merge branch 'develop' into dpl936_json_api
yoldas Jan 29, 2024
af63460
Added a Concern to respect optional linkage data option
yoldas Jan 29, 2024
381c45d
Testing resource object linkage
yoldas Jan 31, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ group :default do
# https://github.com/JamesGlover/sequencescape/tree/depfu/update/jsonapi-resources-0.9.5
# but not only is there a failing test, but performance was tanking in a few places
# due to not correctly eager loading dependencies on nested resources.
gem 'jsonapi-resources', '0.9.0'
gem 'jsonapi-resources' #, '0.9.0'

# Wraps bunny with connection pooling ad consumer process handling
gem 'sanger_warren'
Expand Down
12 changes: 6 additions & 6 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ GEM
mini_magick (>= 4.9.5, < 5)
ruby-vips (>= 2.0.17, < 3)
json (2.6.3)
jsonapi-resources (0.9.0)
jsonapi-resources (0.10.7)
activerecord (>= 4.1)
concurrent-ruby
railties (>= 4.1)
Expand All @@ -241,7 +241,7 @@ GEM
listen (3.8.0)
rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10)
loofah (2.21.4)
loofah (2.22.0)
crass (~> 1.0.2)
nokogiri (>= 1.12.0)
mail (2.8.1)
Expand All @@ -257,7 +257,7 @@ GEM
mime-types-data (3.2023.0808)
mini_magick (4.12.0)
mini_mime (1.1.5)
mini_portile2 (2.8.4)
mini_portile2 (2.8.5)
minitest (5.20.0)
minitest-profiler (0.0.2)
activesupport (>= 4.1.0)
Expand Down Expand Up @@ -353,7 +353,7 @@ GEM
rake (>= 0.8.7)
thor (>= 0.20.3, < 2.0)
rainbow (3.1.1)
rake (13.0.6)
rake (13.1.0)
rb-fsevent (0.11.2)
rb-inotify (0.10.1)
ffi (~> 1.0)
Expand Down Expand Up @@ -482,7 +482,7 @@ GEM
sys-uname (1.2.3)
ffi (~> 1.1)
test-prof (1.3.0)
thor (1.2.2)
thor (1.3.0)
thread_safe (0.3.6)
tilt (2.3.0)
timecop (0.9.8)
Expand Down Expand Up @@ -555,7 +555,7 @@ DEPENDENCIES
flipper-ui (~> 0.25.0)
formtastic
json
jsonapi-resources (= 0.9.0)
jsonapi-resources
jsonapi-resources-matchers
knapsack_pro
launchy
Expand Down
12 changes: 12 additions & 0 deletions app/controllers/api/v2/ancestors_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# frozen_string_literal: true

module Api
module V2
yoldas marked this conversation as resolved.
Show resolved Hide resolved
# Provides a JSON API controller for Assets
# See: http://jsonapi-resources.com/ for JSONAPI::Resource documentation
class AncestorsController < JSONAPI::ResourceController
# By default JSONAPI::ResourceController provides most the standard
# behaviour, and in many cases this file may be left empty.
end
end
end
7 changes: 7 additions & 0 deletions app/controllers/api/v2/children_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# frozen_string_literal: true
module Api
module V2
yoldas marked this conversation as resolved.
Show resolved Hide resolved
class ChildrenController < JSONAPI::ResourceController
end
end
end
16 changes: 16 additions & 0 deletions app/controllers/api/v2/concerns/default_includes_parser.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# frozen_string_literal: true
module Api
module V2
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Api::V2 has the name 'V2'

module Concerns
module DefaultIncludesParser
def parse_include_directives(resource_klass, raw_include)
if resource_klass.respond_to?(:format_default_includes)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Api::V2::Concerns::DefaultIncludesParser#parse_include_directives refers to 'resource_klass' more than self (maybe move it to another class?)

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Api::V2::Concerns::DefaultIncludesParser#parse_include_directives manually dispatches method call

default_includes = resource_klass.format_default_includes
raw_include = [raw_include.presence, default_includes.presence].compact.join(',')
end
super(resource_klass, raw_include)
end
end
end
end
end
34 changes: 34 additions & 0 deletions app/controllers/api/v2/concerns/include_optional_linkage.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# frozen_string_literal: true
module Api
module V2
yoldas marked this conversation as resolved.
Show resolved Hide resolved
module Concerns
module IncludeOptionalLinkage
def relationship_object(source, relationship, rid, include_data)
yoldas marked this conversation as resolved.
Show resolved Hide resolved
hash = include_directives.include_directives
include_data ||= relationship_exists?(relationship.name.to_sym, hash)
include_data ||= relationship.always_include_optional_linkage_data
yoldas marked this conversation as resolved.
Show resolved Hide resolved
if relationship.is_a?(JSONAPI::Relationship::ToOne)
relationship_object_to_one(source, relationship, rid, include_data)
elsif relationship.is_a?(JSONAPI::Relationship::ToMany)
relationship_object_to_many(source, relationship, rid, include_data)
end
end

# https://jsonapi.org/format/#document-resource-object-linkage
def relationship_exists?(name, hash)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Method relationship_exists? has a Cognitive Complexity of 11 (exceeds 5 allowed). Consider refactoring.

return false unless hash
hash.each do |key, value|
if key == :include_related && value.is_a?(Hash) && value.key?(name)
return true
end
if value.is_a?(Hash)
result = relationship_exists?(name, value)
return true if result
end
end
false
end
end
end
end
end
20 changes: 20 additions & 0 deletions app/controllers/api/v2/concerns/nested_include_expander.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# frozen_string_literal: true
module Api
module V2
module Concerns
module NestedIncludeExpander
def parse_include_directives(resource_klass, raw_include)
raw_include ||= ''
raw_include = expand_include_parameters(raw_include)
super(resource_klass, raw_include)
end

def expand_include_parameters(raw_include)
raw_include.split(',').flat_map do |path|
path.split('.').each_with_index.map { |_, index| path.split('.')[0..index].join('.') }
end.uniq.join(',')
end
end
end
end
end
7 changes: 7 additions & 0 deletions app/controllers/api/v2/downstream_assets_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# frozen_string_literal: true
module Api
module V2
yoldas marked this conversation as resolved.
Show resolved Hide resolved
class DownstreamAssetsController < JSONAPI::ResourceController
end
end
end
7 changes: 7 additions & 0 deletions app/controllers/api/v2/parents_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# frozen_string_literal: true
module Api
module V2
yoldas marked this conversation as resolved.
Show resolved Hide resolved
class ParentsController < JSONAPI::ResourceController
end
end
end
7 changes: 2 additions & 5 deletions app/controllers/api/v2/qc_assays_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,8 @@ def create
@qc_result_factory = QcResultFactory.new(qc_assay_params)
if @qc_result_factory.valid?
@qc_result_factory.save
render json:
JSONAPI::ResourceSerializer
.new(QcAssayResource)
.serialize_to_hash(QcAssayResource.new(@qc_result_factory.qc_assay, nil)),
status: :created

render json: serialize_resource(QcAssayResource.new(@qc_result_factory.qc_assay, nil)), status: :created
else
render json: { errors: @qc_result_factory.errors }, status: :unprocessable_entity
end
Expand Down
4 changes: 2 additions & 2 deletions app/controllers/api/v2/qc_results_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ def create
if @qc_result_factory.valid?
@qc_result_factory.save
@qc_result_resources = @qc_result_factory.qc_results.map { |qc_result| QcResultResource.new(qc_result, nil) }
render json: JSONAPI::ResourceSerializer.new(QcResultResource).serialize_to_hash(@qc_result_resources),
status: :created

render json: serialize_array(@qc_result_resources), status: :created
else
render json: @qc_result_factory.errors, status: :unprocessable_entity
end
Expand Down
7 changes: 7 additions & 0 deletions app/controllers/api/v2/source_receptacles_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# frozen_string_literal: true
module Api
module V2
yoldas marked this conversation as resolved.
Show resolved Hide resolved
class SourceReceptaclesController < JSONAPI::ResourceController
end
end
end
7 changes: 7 additions & 0 deletions app/controllers/api/v2/upstream_assets_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# frozen_string_literal: true
module Api
module V2
yoldas marked this conversation as resolved.
Show resolved Hide resolved
class UpstreamAssetsController < JSONAPI::ResourceController
end
end
end
4 changes: 2 additions & 2 deletions app/resources/api/v2/aliquot_resource.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ class AliquotResource < BaseResource
has_one :study
has_one :project
has_one :sample
has_one :request
has_one :request, always_include_optional_linkage_data: true
has_one :receptacle
has_one :tag
has_one :tag2
has_one :tag2, class_name: 'Tag'

# Attributes
attribute :tag_oligo, readonly: true
Expand Down
10 changes: 10 additions & 0 deletions app/resources/api/v2/ancestor_resource.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# frozen_string_literal: true
module Api
module V2
yoldas marked this conversation as resolved.
Show resolved Hide resolved
# Provides a JSON API representation of Ancestor
# See: http://jsonapi-resources.com/ for JSONAPI::Resource documentation
class AncestorResource < LabwareResource
yoldas marked this conversation as resolved.
Show resolved Hide resolved
filter :purpose_name
end
end
end
74 changes: 42 additions & 32 deletions app/resources/api/v2/base_resource.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,49 +39,59 @@ def self.inclusions
@default_includes || [].freeze
end

# Extends the default behaviour to add our default inclusions if provided
def self.apply_includes(records, options = {})
# TODO: Explain preloading and why we used it here.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO found


def self.records_for_populate(options = {})
if @default_includes.present?
super(records.preload(*inclusions), options)
super(options).preload(*inclusions)
else
super
end
end

# The majority of this is lifted from JSONAPI::Resource
# We've had to modify the when Symbol chunk to handle nested includes
# We disable the cops for the shared section to avoid accidental drift
# due to auto-correct.
# rubocop:disable all
def self.resolve_relationship_names_to_relations(resource_klass, model_includes, options = {})
case model_includes
when Array
return model_includes.map { |value| resolve_relationship_names_to_relations(resource_klass, value, options) }
def self.format_default_includes
@format_default_includes ||= format_inclusions
end

def self.format_inclusions
formatted = Array(inclusions).filter_map { |inclusion| format_single_inclusion(inclusion) }
formatted.join(',')
end

def self.format_single_inclusion(inclusion, parent = nil)
case inclusion
when Symbol
format_symbol_inclusion(inclusion, parent)
when Hash
model_includes.keys.each do |key|
relationship = resource_klass._relationships[key]
value = model_includes[key]
model_includes.delete(key)
format_hash_inclusion(inclusion, parent)
when Array
format_array_inclusion(inclusion, parent)
end
end

def self.format_symbol_inclusion(inclusion, parent)
resource_klass_for(inclusion.to_s) # Test that the resource exists
[parent, inclusion].compact.join('.') unless _relationship(inclusion).nil?
rescue StandardError
nil
end

# MODIFICATION BEGINS
included_relationships =
resolve_relationship_names_to_relations(relationship.resource_klass, value, options)
model_includes[relationship.relation_name(options)] =
relationship.resource_klass.inclusions + included_relationships
# MODIFICATION ENDS
def self.format_hash_inclusion(inclusion, parent)
result =
inclusion.filter_map do |key, value|
new_parent = format_single_inclusion(key, parent)
next if new_parent.nil?
format_single_inclusion(value, new_parent)
end
return model_includes
when Symbol
relationship = resource_klass._relationships[model_includes]
result.join(',') unless result.empty?
end

# MODIFICATION BEGINS
# return relationship.relation_name(options)
inclusions = relationship.resource_klass.inclusions
{ relationship.relation_name(options) => inclusions }
# MODIFICATION ENDS
end
def self.format_array_inclusion(inclusion, parent)
result = inclusion.filter_map { |value| format_single_inclusion(value, parent) }
result.join(',') unless result.empty?
end
# rubocop:enable all
end
end
end

# {k1: {k2: { k3: 'v3' }}} # => "k1.k2.k3.v3"
9 changes: 9 additions & 0 deletions app/resources/api/v2/child_resource.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# frozen_string_literal: true
module Api
module V2
yoldas marked this conversation as resolved.
Show resolved Hide resolved
# Provides a JSON API representation of Child
# See: http://jsonapi-resources.com/ for JSONAPI::Resource documentation
class ChildResource < JSONAPI::Resource
yoldas marked this conversation as resolved.
Show resolved Hide resolved
end
end
end
4 changes: 2 additions & 2 deletions app/resources/api/v2/comment_resource.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ class CommentResource < BaseResource
has_one :commentable, polymorphic: true

# Attributes
attribute :title, readonly: true
attribute :description, readonly: true
attribute :title
attribute :description
attribute :created_at, readonly: true
attribute :updated_at, readonly: true

Expand Down
9 changes: 9 additions & 0 deletions app/resources/api/v2/descendant_resource.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# frozen_string_literal: true
module Api
module V2
yoldas marked this conversation as resolved.
Show resolved Hide resolved
# Provides a JSON API representation of Descendant
# See: http://jsonapi-resources.com/ for JSONAPI::Resource documentation
class DescendantResource < JSONAPI::Resource
yoldas marked this conversation as resolved.
Show resolved Hide resolved
end
end
end
9 changes: 9 additions & 0 deletions app/resources/api/v2/downstream_asset_resource.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# frozen_string_literal: true
module Api
module V2
yoldas marked this conversation as resolved.
Show resolved Hide resolved
# Provides a JSON API representation of DownstreamAsset
# See: http://jsonapi-resources.com/ for JSONAPI::Resource documentation
class DownstreamAssetResource < JSONAPI::Resource
yoldas marked this conversation as resolved.
Show resolved Hide resolved
end
end
end
2 changes: 1 addition & 1 deletion app/resources/api/v2/labware_resource.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class LabwareResource < BaseResource
# is automatically available on plate and tube.
include Api::V2::SharedBehaviour::Labware

default_includes :uuid_object, :barcodes
default_includes :uuid_object, :barcodes, :purpose

# Custom methods
# These shouldn't be used for business logic, and a more about
Expand Down
7 changes: 7 additions & 0 deletions app/resources/api/v2/parent_resource.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# frozen_string_literal: true
class ParentResource < JSONAPI::Resource
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ParentResource has no descriptive comment

def self.records(options = {})
class_name = options[:_relation_helper_options][:join_manager].resource_klass
class_name.to_s.demodulize.sub(/Resource$/, '').constantize.all
end
end
Loading
Loading