diff --git a/app/controllers/api/v1/exports_controller.rb b/app/controllers/api/v1/exports_controller.rb index 6cd3c00d..91827412 100644 --- a/app/controllers/api/v1/exports_controller.rb +++ b/app/controllers/api/v1/exports_controller.rb @@ -32,6 +32,8 @@ def new Rails.logger.warn "CMDOWS export warning: #{e}" end send_data content, filename: filename, type: "application/xml" + elsif format == "mdajson" + json_response mda, :ok, serializer: AnalysisAttrsSerializer else json_response({ message: "Export format #{format} not knwon" }, :bad_request) end diff --git a/app/lib/whats_opt/mdajson_generator.rb b/app/lib/whats_opt/mdajson_generator.rb new file mode 100644 index 00000000..56c5ca71 --- /dev/null +++ b/app/lib/whats_opt/mdajson_generator.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +require "json" + +module WhatsOpt + class MdajsonGenerator + + def initialize(mda) + @mda = mda + end + + def generate + as_json = AnalysisAttrsSerializer.new(@mda).as_json + + as_json.to_json + end + + end +end diff --git a/app/models/analysis.rb b/app/models/analysis.rb index 2c623aa9..fe18192b 100644 --- a/app/models/analysis.rb +++ b/app/models/analysis.rb @@ -659,9 +659,12 @@ def ensure_ancestry_for_sub_analyses def self.create_nested_analyses(mda_attrs) # Rails.logger.info "################ CREATE NESTED #{mda_attrs["name"]}" subs = [] - # create sub analyses + # manage metamodel and sub analyses if mda_attrs["disciplines_attributes"] mda_attrs["disciplines_attributes"].each.with_index do |disc, i| + # when creating an analysis from params, just disable metamodel + # and set a regular discipline instead + disc["type"] == Discipline::DISCIPLINE if disc["type"] == Discipline::METAMODEL if disc["sub_analysis_attributes"] subs << self.create_nested_analyses(disc["sub_analysis_attributes"]) disc.delete("sub_analysis_attributes") diff --git a/app/serializers/analysis_attrs_serializer.rb b/app/serializers/analysis_attrs_serializer.rb new file mode 100644 index 00000000..e0afc35c --- /dev/null +++ b/app/serializers/analysis_attrs_serializer.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +class AnalysisAttrsSerializer < ActiveModel::Serializer + attributes :name, :disciplines_attributes + + def disciplines_attributes + object.disciplines.map { |disc| + if disc.type == Discipline::ANALYSIS + { + "name" => disc.name, + "type" => disc.type, + "sub_analysis_attributes": AnalysisAttrsSerializer.new(disc.sub_analysis) + } + else + DisciplineAttrsSerializer.new(disc) + end + }.compact + end +end diff --git a/app/serializers/discipline_attrs_serializer.rb b/app/serializers/discipline_attrs_serializer.rb new file mode 100644 index 00000000..ed1440ed --- /dev/null +++ b/app/serializers/discipline_attrs_serializer.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +class DisciplineAttrsSerializer < ActiveModel::Serializer + attributes :name, :type + + has_many :variables, key: :variables_attributes +end diff --git a/db/schema.rb b/db/schema.rb index efea0bd0..37f39be5 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -52,6 +52,13 @@ t.index ["ancestry"], name: "index_analyses_on_ancestry" end + create_table "analyses_design_projects", id: false, force: :cascade do |t| + t.integer "design_project_id", null: false + t.integer "analysis_id", null: false + t.index ["analysis_id", "design_project_id"], name: "index_analysis_id_design_project_id" + t.index ["design_project_id", "analysis_id"], name: "index_design_project_id_analysis_id" + end + create_table "analysis_disciplines", force: :cascade do |t| t.integer "discipline_id" t.integer "analysis_id" @@ -80,6 +87,15 @@ t.text "values" end + create_table "components", force: :cascade do |t| + t.integer "discipline_id" + t.boolean "has_derivatives", default: false + t.boolean "is_implicit", default: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["discipline_id"], name: "index_components_on_discipline_id" + end + create_table "connections", force: :cascade do |t| t.integer "from_id" t.integer "to_id" @@ -208,9 +224,9 @@ end create_table "parameters", force: :cascade do |t| - t.text "init" - t.text "lower" - t.text "upper" + t.string "init", default: "" + t.string "lower", default: "" + t.string "upper", default: "" t.integer "variable_id" end @@ -295,7 +311,6 @@ t.index ["discipline_id"], name: "index_variables_on_discipline_id" end - add_foreign_key "active_storage_attachments", "active_storage_blobs", column: "blob_id" add_foreign_key "analysis_disciplines", "analyses" add_foreign_key "analysis_disciplines", "disciplines" end diff --git a/test/controllers/api/v1/exports_controller_test.rb b/test/controllers/api/v1/exports_controller_test.rb new file mode 100644 index 00000000..a4b08624 --- /dev/null +++ b/test/controllers/api/v1/exports_controller_test.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +require "test_helper" + +class Api::V1::ExportsControllerTest < ActionDispatch::IntegrationTest + setup do + @auth_headers = { "Authorization" => "Token " + TEST_API_KEY } + @mda = analyses(:cicav) + end + + test "should dump analysis as json" do + get api_v1_mda_exports_new_url(@mda, format: :mdajson), as: :json, headers: @auth_headers + assert_response :success + resp = JSON.parse(response.body) + expected = sample_file("cicav_mda.json").read.chomp + assert_equal expected, resp.to_json.to_s + end + + test "should dump nested analysis as json" do + mda = analyses(:outermda) + get api_v1_mda_exports_new_url(mda, format: :mdajson), as: :json, headers: @auth_headers + assert_response :success + resp = JSON.parse(response.body) + expected = sample_file("outer_mda.json").read.chomp + assert_equal expected, resp.to_json.to_s + end + +end diff --git a/test/fixtures/cicav_mda.json b/test/fixtures/cicav_mda.json new file mode 100644 index 00000000..cc1ae5e0 --- /dev/null +++ b/test/fixtures/cicav_mda.json @@ -0,0 +1 @@ +{"name":"CICAV","disciplines_attributes":[{"name":"__DRIVER__","type":"null_driver","variables_attributes":[{"name":"obj","io_mode":"in","shape":"1","type":"Float","active":true,"distributions_attributes":[]},{"name":"x1","io_mode":"out","shape":"1","type":"Float","active":true,"parameter_attributes":{"init":"3.14","lower":"1","upper":"10"},"distributions_attributes":[]},{"name":"y2","io_mode":"in","shape":"1","type":"Float","active":true,"distributions_attributes":[]},{"name":"z","io_mode":"out","shape":"(2,)","type":"Float","active":true,"parameter_attributes":{"init":"3.14","lower":"1","upper":"10"},"distributions_attributes":[]}]},{"name":"Geometry","type":"analysis","variables_attributes":[{"name":"obj","io_mode":"out","shape":"1","type":"Float","active":true,"distributions_attributes":[]},{"name":"x1","io_mode":"in","shape":"1","type":"Float","active":true,"distributions_attributes":[]},{"name":"ya","io_mode":"in","shape":"1","type":"Float","active":true,"distributions_attributes":[]},{"name":"yg","io_mode":"out","shape":"1","type":"Float","active":true,"distributions_attributes":[]},{"name":"z","io_mode":"in","shape":"(2,)","type":"Float","active":true,"distributions_attributes":[]}]},{"name":"Aerodynamics","type":"analysis","variables_attributes":[{"name":"y2","io_mode":"out","shape":"1","type":"Float","active":true,"distributions_attributes":[]},{"name":"ya","io_mode":"out","shape":"1","type":"Float","active":true,"distributions_attributes":[]},{"name":"yg","io_mode":"in","shape":"1","type":"Float","active":true,"distributions_attributes":[]},{"name":"z","io_mode":"in","shape":"(2,)","type":"Float","active":true,"distributions_attributes":[]}]},{"name":"Propulsion","type":"analysis","variables_attributes":[]}]} diff --git a/test/fixtures/outer_mda.json b/test/fixtures/outer_mda.json new file mode 100644 index 00000000..942f2d5e --- /dev/null +++ b/test/fixtures/outer_mda.json @@ -0,0 +1 @@ +{"name":"OUTER","disciplines_attributes":[{"name":"__DRIVER__","type":"null_driver","variables_attributes":[{"name":"x1","io_mode":"out","shape":"1","type":"Float","active":true,"distributions_attributes":[]},{"name":"x2","io_mode":"out","shape":"1","type":"Float","active":true,"distributions_attributes":[]},{"name":"y","io_mode":"in","shape":"1","type":"Float","active":true,"distributions_attributes":[]},{"name":"y1","io_mode":"in","shape":"1","type":"Float","active":true,"distributions_attributes":[]},{"name":"y2","io_mode":"in","shape":"1","type":"Float","active":true,"distributions_attributes":[]},{"name":"z","io_mode":"out","shape":"1","type":"Float","active":true,"distributions_attributes":[]}]},{"name":"Disc","type":"analysis","variables_attributes":[{"name":"x1","io_mode":"in","shape":"1","type":"Float","active":true,"distributions_attributes":[]},{"name":"y1","io_mode":"out","shape":"1","type":"Float","active":true,"distributions_attributes":[]},{"name":"y2","io_mode":"in","shape":"1","type":"Float","active":true,"distributions_attributes":[]},{"name":"z","io_mode":"in","shape":"1","type":"Float","active":true,"distributions_attributes":[]}]},{"name":"InnerMdaDiscipline","type":"mda","sub_analysis_attributes":{"name":"INNER","disciplines_attributes":[{"name":"__DRIVER__","type":"null_driver","variables_attributes":[{"name":"x2","io_mode":"out","shape":"1","type":"Float","active":true,"distributions_attributes":[]},{"name":"y","io_mode":"in","shape":"1","type":"Float","active":true,"distributions_attributes":[]},{"name":"y1","io_mode":"out","shape":"1","type":"Float","active":true,"distributions_attributes":[]},{"name":"y2","io_mode":"in","shape":"1","type":"Float","active":true,"distributions_attributes":[]},{"name":"z","io_mode":"out","shape":"1","type":"Float","active":true,"distributions_attributes":[]}]},{"name":"PlainDiscipline","type":"analysis","variables_attributes":[{"name":"x2","io_mode":"in","shape":"1","type":"Float","active":true,"distributions_attributes":[]},{"name":"y","io_mode":"out","shape":"1","type":"Float","active":true,"distributions_attributes":[]},{"name":"y1","io_mode":"in","shape":"1","type":"Float","active":true,"distributions_attributes":[]},{"name":"y2","io_mode":"out","shape":"1","type":"Float","active":true,"distributions_attributes":[]},{"name":"z","io_mode":"in","shape":"1","type":"Float","active":true,"distributions_attributes":[]}]}]}},{"name":"VacantDiscipline","type":"analysis","variables_attributes":[]}]} diff --git a/test/lib/whats_opt/mdajson_generator_test.rb b/test/lib/whats_opt/mdajson_generator_test.rb new file mode 100644 index 00000000..8ced416c --- /dev/null +++ b/test/lib/whats_opt/mdajson_generator_test.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +require "test_helper" + +class MdajsonGeneratorTest < ActiveSupport::TestCase + def setup + @mda = analyses(:cicav) + @jsongen = WhatsOpt::MdajsonGenerator.new(@mda) + end + + test "should generate mda json" do + content = @jsongen.generate + expected = sample_file("cicav_mda.json").read.chomp + assert_equal expected, content + end +end \ No newline at end of file