Skip to content

Commit 8071c6f

Browse files
committed
feat: chemical associations to support sequence-based macromolecules (SBMM)
- Add SBMM foreign key to chemicals table and update models for polymorphic-like association - Enforce mutual exclusivity and presence validation for sample_id and sequence_based_macromolecule_id - Update API, fetchers, and UI components to handle both sample- and SBMM-linked chemicals - Extend state management and tests for new association logic - Enable inventory tab functionality for sequence-based macromolecule samples
1 parent 6a8e356 commit 8071c6f

20 files changed

Lines changed: 652 additions & 204 deletions

app/api/chemotion/chemical_api.rb

Lines changed: 42 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,28 +8,47 @@ class ChemicalAPI < Grape::API
88
params do
99
requires :chemical_data, type: Array[Hash], desc: 'chemical data'
1010
optional :cas, type: String, desc: 'cas number'
11+
optional :sample_id, type: Integer
12+
optional :sequence_based_macromolecule_sample_id, type: Integer
13+
exactly_one_of :sample_id, :sequence_based_macromolecule_sample_id
1114
end
12-
route_param :sample_id do
13-
put do
14-
Chemotion::ChemicalsService.handle_exceptions do
15-
attributes = declared(params, include_missing: false)
16-
if params[:chemical_data].present? || params[:cas].present?
17-
Chemical.find_by(sample_id: params[:sample_id]).update!(attributes)
18-
else
19-
status 204
20-
end
15+
put do
16+
Chemotion::ChemicalsService.handle_exceptions do
17+
attributes = declared(params, include_missing: false)
18+
if params[:chemical_data].present? || params[:cas].present?
19+
chemical = if params[:sequence_based_macromolecule_sample_id]
20+
attributes[:sample_id] = nil
21+
Chemical.find_by(
22+
sequence_based_macromolecule_sample_id: params[:sequence_based_macromolecule_sample_id],
23+
)
24+
else
25+
attributes[:sequence_based_macromolecule_sample_id] = nil
26+
Chemical.find_by(sample_id: params[:sample_id])
27+
end
28+
error!('chemical not found', 404) unless chemical
29+
chemical.update!(attributes)
30+
else
31+
status 204
2132
end
2233
end
2334
end
2435

25-
desc 'Return chemical by sample_id'
36+
desc 'Return chemical by sample_id or sequence_based_macromolecule_sample_id'
2637
params do
27-
requires :sample_id, type: Integer, desc: 'sample id'
38+
optional :sample_id, type: Integer, desc: 'sample id'
39+
optional :sequence_based_macromolecule_sample_id, type: Integer, desc: 'sequence based macromolecule id'
40+
exactly_one_of :sample_id, :sequence_based_macromolecule_sample_id
2841
end
2942

3043
get do
3144
Chemotion::ChemicalsService.handle_exceptions do
32-
Chemical.find_by(sample_id: params[:sample_id]) || Chemical.new
45+
if params[:sequence_based_macromolecule_sample_id]
46+
Chemical.find_by(
47+
sequence_based_macromolecule_sample_id: params[:sequence_based_macromolecule_sample_id],
48+
) || Chemical.new
49+
else
50+
Chemical.find_by(sample_id: params[:sample_id]) || Chemical.new
51+
end
3352
end
3453
end
3554

@@ -38,12 +57,21 @@ class ChemicalAPI < Grape::API
3857
params do
3958
requires :chemical_data, type: Array[Hash], desc: 'chemical data'
4059
requires :cas, type: String
41-
requires :sample_id, type: Integer
60+
optional :sample_id, type: Integer
61+
optional :sequence_based_macromolecule_sample_id, type: Integer
62+
exactly_one_of :sample_id, :sequence_based_macromolecule_sample_id
4263
end
4364

4465
post do
4566
Chemotion::ChemicalsService.handle_exceptions do
46-
attributes = declared(params, include_missing: false)
67+
attributes = declared(params, include_missing: false) || {}
68+
if params[:sequence_based_macromolecule_sample_id]
69+
attributes[:sample_id] = nil
70+
attributes[:sequence_based_macromolecule_sample_id] = params[:sequence_based_macromolecule_sample_id]
71+
else
72+
attributes[:sequence_based_macromolecule_sample_id] = nil
73+
attributes[:sample_id] = params[:sample_id]
74+
end
4775
Chemical.create!(attributes)
4876
end
4977
end

app/api/entities/sequence_based_macromolecule_sample_entity.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ class SequenceBasedMacromoleculeSampleEntity < ApplicationEntity
3333
expose! :type
3434
expose! :changed
3535
expose! :errors
36+
expose! :inventory_sample
3637

3738
expose! :heterologous_expression, if: ->(_object, _options) { !uniprot_protein? }
3839
expose! :organism, if: ->(_object, _options) { !uniprot_protein? }

app/api/helpers/params_helpers.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ module ParamsHelpers
176176
params :sbmm_sample_params do
177177
optional :name, type: String
178178
optional :collection_id, type: Integer
179+
optional :inventory_sample, type: Boolean, default: false
179180
optional :external_label, type: String
180181
optional :function_or_application, type: String
181182
optional :concentration_value, type: Float

app/javascript/src/apps/mydb/elements/details/ElementDetailSortTab.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,13 @@ export default class ElementDetailSortTab extends Component {
3737
CollectionStore.listen(this.onChangeUI);
3838
}
3939

40+
componentDidUpdate(prevProps) {
41+
if (prevProps.addInventoryTab !== this.props.addInventoryTab
42+
|| !_.isEqual(prevProps.availableTabs, this.props.availableTabs)) {
43+
this.onChangeUI();
44+
}
45+
}
46+
4047
componentWillUnmount() {
4148
UserStore.unlisten(this.onChangeUser);
4249
CollectionStore.unlisten(this.onChangeUI);

app/javascript/src/apps/mydb/elements/details/samples/SampleDetails.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -608,6 +608,7 @@ export default class SampleDetails extends React.Component {
608608
<ListGroupItem>
609609
<ChemicalTab
610610
sample={sample}
611+
type="sample"
611612
handleUpdateSample={(s) => this.setState({ sample: s })}
612613
setSaveInventory={(v) => this.setState({ saveInventoryAction: v })}
613614
saveInventory={saveInventoryAction}

0 commit comments

Comments
 (0)