-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1479 from sanger/y24-411-batch-library-creation
Y24-411 - PacBio batch library creation
- Loading branch information
Showing
14 changed files
with
324 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
# frozen_string_literal: true | ||
|
||
module V1 | ||
module Pacbio | ||
# LibraryBatchesController | ||
class LibraryBatchesController < ApplicationController | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
# frozen_string_literal: true | ||
|
||
module Pacbio | ||
# Pacbio::LibraryBatch is a audit record created to keep track of libraries created in batches | ||
class LibraryBatch < ApplicationRecord | ||
validates :libraries, presence: true | ||
|
||
has_many :libraries, class_name: 'Pacbio::Library', dependent: :nullify, | ||
foreign_key: :pacbio_library_batch_id, inverse_of: :library_batch | ||
|
||
# This allows the creation of libraries when creating a library batch | ||
accepts_nested_attributes_for :libraries | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
# frozen_string_literal: true | ||
|
||
module V1 | ||
module Pacbio | ||
# This resource is used to create batches of libraries in one go. | ||
# This resource can only be accessed via a `POST` request to the library_batches endpoint. | ||
# | ||
# @example | ||
# { | ||
# "data": { | ||
# "type": "library_batches", | ||
# "attributes": { | ||
# "libraries_attributes": [ | ||
# { | ||
# "volume": 50.2, | ||
# "concentration": 2.222, | ||
# "template_prep_kit_box_barcode": "LK1234567", | ||
# "insert_size": 100, | ||
# "pacbio_request_id": 1, | ||
# "tag_id": 1, | ||
# "primary_aliquot_attributes": { | ||
# "volume": 50.2, | ||
# "concentration": 2.222, | ||
# "template_prep_kit_box_barcode": "LK1234567", | ||
# "insert_size": 100, | ||
# "tag_id": 1 | ||
# }, | ||
# } | ||
# ] | ||
# } | ||
# } | ||
# | ||
# @note | ||
# Access this resource via the `/v1/pacbio/library_batches/` endpoint. | ||
# To return the libraries created, add `libraries` to the include. | ||
# To return the created libraries tubes add `libraries.tube` to the include. | ||
# For example `/v1/pacbio/library_batches?include=libraries.tube` | ||
# | ||
# | ||
# Provides a JSON:API representation of {Pacbio::LibraryBatch}. | ||
# | ||
# For more information about JSON:API see the [JSON:API Specifications](https://jsonapi.org/format/) | ||
# or look at the [JSONAPI::Resources](http://jsonapi-resources.com/) package | ||
# for the service implementation of the JSON:API standard. | ||
class LibraryBatchResource < JSONAPI::Resource | ||
model_name 'Pacbio::LibraryBatch' | ||
|
||
# @!attribute [w] created_at | ||
# @return [String] the creation time of the library | ||
# @!attribute [w] libraries_attributes | ||
# @return [Array] the attributes of the libraries | ||
attributes :created_at, :libraries_attributes | ||
|
||
has_many :libraries, always_include_optional_linkage_data: true | ||
|
||
def libraries_attributes=(libraries_attributes_parameters) | ||
@model.libraries_attributes = libraries_attributes_parameters.map do |library| | ||
library.permit( | ||
:volume, :template_prep_kit_box_barcode, | ||
:concentration, :insert_size, :tag_id, | ||
:pacbio_request_id, | ||
primary_aliquot_attributes: %i[ | ||
volume concentration template_prep_kit_box_barcode insert_size tag_id | ||
] | ||
) | ||
end | ||
end | ||
|
||
def fetchable_fields | ||
super - [:libraries_attributes] | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
class CreatePacbioLibraryBatch < ActiveRecord::Migration[7.2] | ||
def change | ||
create_table :pacbio_library_batches do |t| | ||
t.timestamps | ||
end | ||
|
||
add_reference :pacbio_libraries, :pacbio_library_batch, index: true, foreign_key: true, null: true | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# frozen_string_literal: true | ||
|
||
FactoryBot.define do | ||
factory :pacbio_library_batch, class: 'Pacbio::LibraryBatch' do | ||
libraries { build_list(:pacbio_library, 1) } | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
# frozen_string_literal: true | ||
|
||
require 'rails_helper' | ||
|
||
RSpec.describe Pacbio::LibraryBatch, :pacbio do | ||
it 'is valid with valid attributes' do | ||
library_batch = build(:pacbio_library_batch) | ||
expect(library_batch).to be_valid | ||
end | ||
|
||
it 'is not valid without libraries' do | ||
library_batch = build(:pacbio_library_batch, libraries: []) | ||
expect(library_batch).not_to be_valid | ||
expect(library_batch.errors[:libraries]).to include("can't be blank") | ||
end | ||
|
||
it 'nullifies associated libraries on destroy' do | ||
library_batch = create(:pacbio_library_batch) | ||
library = create(:pacbio_library, library_batch: library_batch) | ||
library_batch.destroy | ||
expect(library.reload.library_batch).to be_nil | ||
end | ||
|
||
describe 'creating nested libraries' do | ||
define_negated_matcher :not_change, :change | ||
|
||
let(:pacbio_requests_enum) { create_list(:pacbio_request, 8).cycle } | ||
let(:pacbio_libraries) { build_list(:pacbio_library, 8, pacbio_request_id: pacbio_requests_enum.next.id) } | ||
# Creates valid attributes for the libraries - including the primary aliquot attributes and a pacbio_request_id | ||
let(:libraries_attributes) do | ||
pacbio_libraries.map do |lib| | ||
{ **lib.attributes, primary_aliquot_attributes: lib.primary_aliquot.attributes, pacbio_request_id: lib.request.id } | ||
end | ||
end | ||
|
||
it 'accepts nested attributes for libraries' do | ||
library_batch = described_class.new(libraries_attributes: libraries_attributes) | ||
expect { library_batch.save! }.to change(Pacbio::Library, :count).by(8) | ||
expect(library_batch.libraries.count).to eq(8) | ||
end | ||
|
||
it 'does not save the library batch if a library is invalid' do | ||
# Make the last library invalid | ||
libraries_attributes.last[:pacbio_request_id] = nil | ||
|
||
library_batch = described_class.new(libraries_attributes: libraries_attributes) | ||
expect { library_batch.save! }.to raise_error(ActiveRecord::RecordInvalid).and not_change(Pacbio::Library, :count) | ||
expect(library_batch.errors['libraries.request']).to include('must exist') | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
# frozen_string_literal: true | ||
|
||
require 'rails_helper' | ||
|
||
RSpec.describe 'LibraryBatchesController', :pacbio do | ||
describe '#create' do | ||
context 'when creating a library batch' do | ||
let!(:pacbio_requests) { create_list(:pacbio_request, 2) } | ||
let!(:tag) { create(:tag) } | ||
|
||
context 'on success' do | ||
let(:body) do | ||
{ | ||
data: { | ||
type: 'library_batches', | ||
attributes: { | ||
libraries_attributes: [ | ||
{ | ||
volume: 1.11, | ||
template_prep_kit_box_barcode: 'LK1234567', | ||
concentration: 2.22, | ||
insert_size: 100, | ||
pacbio_request_id: pacbio_requests.first.id, | ||
tag_id: tag.id, | ||
primary_aliquot_attributes: { | ||
volume: 1.11, | ||
template_prep_kit_box_barcode: 'LK1234567', | ||
concentration: 2.22, | ||
insert_size: 100, | ||
state: 'created', | ||
tag_id: tag.id | ||
} | ||
}, | ||
volume: 1.11, | ||
template_prep_kit_box_barcode: 'LK1234567', | ||
concentration: 2.22, | ||
insert_size: 100, | ||
pacbio_request_id: pacbio_requests.second.id, | ||
tag_id: tag.id, | ||
primary_aliquot_attributes: { | ||
volume: 1.11, | ||
template_prep_kit_box_barcode: 'LK1234567', | ||
concentration: 2.22, | ||
insert_size: 100, | ||
state: 'created', | ||
tag_id: tag.id | ||
} | ||
] | ||
} | ||
} | ||
}.to_json | ||
end | ||
|
||
it 'has a created status' do | ||
post v1_pacbio_library_batches_path, params: body, headers: json_api_headers | ||
expect(response).to have_http_status(:created), response.body | ||
end | ||
|
||
it 'creates a library and aliquots' do | ||
expect { post v1_pacbio_library_batches_path, params: body, headers: json_api_headers } | ||
.to change(Pacbio::Library, :count).by(2) | ||
.and change(Aliquot, :count).by(4) # We create a primary aliquot and a used_by aliquot for each library | ||
end | ||
|
||
it 'returns the id' do | ||
post v1_pacbio_library_batches_path, params: body, headers: json_api_headers | ||
expect(json.dig('data', 'id').to_i).to eq(Pacbio::LibraryBatch.first.id) | ||
end | ||
|
||
it 'includes the libraries and their tubes' do | ||
post "#{v1_pacbio_library_batches_path}?include=libraries.tube", params: body, headers: json_api_headers | ||
expect(json['included'].length).to eq(4) | ||
expect(json['included'].filter { |record| record['type'] == 'tubes' }.length).to eq(2) | ||
expect(json['included'].filter { |record| record['type'] == 'libraries' }.length).to eq(2) | ||
end | ||
end | ||
|
||
context 'on failure - when a library is invalid' do | ||
let(:body) do | ||
{ | ||
data: { | ||
type: 'library_batches', | ||
attributes: { | ||
libraries_attributes: [ | ||
{ | ||
volume: 1.11, | ||
template_prep_kit_box_barcode: 'LK1234567', | ||
concentration: 2.22, | ||
insert_size: 'invalid insert size', | ||
pacbio_request_id: pacbio_requests.first.id, | ||
tag_id: tag.id, | ||
primary_aliquot_attributes: { | ||
volume: 1.11, | ||
template_prep_kit_box_barcode: 'LK1234567', | ||
concentration: 2.22, | ||
insert_size: 100, | ||
state: 'created', | ||
tag_id: tag.id | ||
} | ||
}, | ||
volume: 1.11, | ||
template_prep_kit_box_barcode: 'LK1234567', | ||
concentration: 2.22, | ||
insert_size: 100, | ||
pacbio_request_id: pacbio_requests.second.id, | ||
tag_id: tag.id, | ||
primary_aliquot_attributes: { | ||
volume: 1.11, | ||
template_prep_kit_box_barcode: 'LK1234567', | ||
concentration: 2.22, | ||
insert_size: 100, | ||
state: 'created', | ||
tag_id: tag.id | ||
} | ||
] | ||
} | ||
} | ||
}.to_json | ||
end | ||
|
||
it 'returns unprocessable entity status' do | ||
post v1_pacbio_library_batches_path, params: body, headers: json_api_headers | ||
expect(response).to have_http_status(:unprocessable_entity) | ||
expect(response.body).to include('libraries.insert_size - is not a number') | ||
end | ||
|
||
it 'cannot create a library' do | ||
expect { post v1_pacbio_library_batches_path, params: body, headers: json_api_headers }.not_to( | ||
change(Pacbio::Library, :count) && | ||
change(Aliquot, :count) | ||
) | ||
end | ||
end | ||
end | ||
end | ||
end |