Skip to content

Commit

Permalink
Download inputs as a csv with min, max, default, unit and user value
Browse files Browse the repository at this point in the history
  • Loading branch information
louispt1 committed Oct 15, 2024
1 parent 4d43973 commit 56aea09
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 18 deletions.
65 changes: 57 additions & 8 deletions app/controllers/api/v3/inputs_controller.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# frozen_string_literal: true
require 'csv'

module Api
module V3
Expand All @@ -10,18 +11,19 @@ class InputsController < ::Api::V3::BaseController

# GET /api/v3/inputs
# GET /api/v3/scenarios/:scenario_id/inputs
# GET /api/v3/scenarios/:scenario_id/inputs.csv
#
# Returns the details for all available inputs. If the scenario_id isn't
# passed then the action will use the latest scenario.
#
# Returns input details in JSON or CSV format. Uses the latest scenario if
# scenario_id is not provided.

def index
extras = ActiveModel::Type::Boolean.new.cast(params[:include_extras])
inputs = serialized_inputs(extras)

render json: InputSerializer.collection(
Input.all,
@scenario,
**serializer_args(extra_attributes: extras)
)
respond_to do |format|
format.json { render json: inputs }
format.csv { send_csv_data(inputs) }
end
end

# GET /api/v3/inputs/:id
Expand Down Expand Up @@ -77,6 +79,53 @@ def serializer_args(extra_attributes:)
extra_attributes:
}
end

def serialized_inputs(extras)
InputSerializer.collection(
Input.all,
@scenario,
**serializer_args(extra_attributes: extras)
)
end

def send_csv_data(inputs)
csv_data = generate_csv(inputs)
send_data csv_data, filename: "inputs_#{@scenario.id}.csv"
end

def generate_csv(inputs)
CSV.generate(headers: true) do |csv|
csv << csv_headers
cached_values = Input.cache(@scenario.parent)
user_values = @scenario.user_values

inputs.each do |key, input|
add_csv_row(csv, key, input, cached_values, user_values)
end
end
end

def csv_headers
["Key", "Min", "Max", "Default", "User Value", "Unit", "Share Group"]
end

def add_csv_row(csv, key, input, cached_values, user_values)
input_data = input.instance_variable_get(:@input)
return if input_data.nil?

values = cached_values.read(@scenario.parent, input_data)
default_value = input.instance_variable_get(:@default_values_from).call(values)

csv << [
key,
input_data.min_value,
input_data.max_value,
default_value,
user_values[input_data.key] || "",
input_data.unit,
input_data.share_group
]
end
end
end
end
2 changes: 1 addition & 1 deletion config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@
get 'converters', to: redirect('/api/v3/scenarios/%{scenario_id}/nodes')
get 'converters/:id', to: redirect('/api/v3/scenarios/%{scenario_id}/nodes/%{id}')

resources :inputs, :only => [:index, :show]
resources :inputs, :only => [:index, :show], defaults: { format: :json}

resource :version, :only => [:create, :show, :update], controller: 'scenario_version_tags'

Expand Down
20 changes: 11 additions & 9 deletions spec/controllers/api/v3/inputs_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,29 @@
FactoryBot.build(:input, {
min_value: 5,
max_value: 15,
start_value: 10
start_value: 10,
unit: 'kWh'
})
end

let(:gql_input) do
FactoryBot.build(:input, {
start_value_gql: 'present:2 * 4',
min_value_gql: 'present:2 * 2',
max_value_gql: 'present:2 * 8'
max_value_gql: 'present:2 * 8',
unit: 'MW'
})
end

before do
NastyCache.instance.expire!
allow(Input).to receive(:all).and_return([ static_input, gql_input ])
allow(Input).to receive(:all).and_return([static_input, gql_input])
end

# --------------------------------------------------------------------------

describe 'GET /api/v3/scenarios/:scenario_id/inputs' do
let(:json) { JSON.parse(get(:index, params: { scenario_id: scenario.id }).body) }
describe 'GET /api/v3/scenarios/:scenario_id/inputs (JSON format)' do
let(:json) { JSON.parse(get(:index, params: { scenario_id: scenario.id, format: :json }).body) }

it 'is successful' do
json
Expand Down Expand Up @@ -174,7 +176,8 @@
end

let(:json) do
JSON.parse(get(:index, params: { scenario_id: scenario.id, defaults: 'parent' }).body)
response = get(:index, params: { scenario_id: scenario.id, defaults: 'parent', format: :json })
JSON.parse(response.body)
end

it 'has a "default" attribute for each input based on the parent' do
Expand All @@ -192,7 +195,7 @@
end

let(:json) do
JSON.parse(get(:index, params: { scenario_id: scenario.id, defaults: 'original' }).body)
JSON.parse(get(:index, params: { scenario_id: scenario.id, defaults: 'original', format: :json }).body)
end

it 'has a "default" attribute for each input based on the dataset' do
Expand All @@ -211,7 +214,7 @@
gql_input.key => gql_input
})

get(:show, params: { scenario_id: scenario.id, id: static_input.key })
get(:show, params: { scenario_id: scenario.id, id: static_input.key, format: :json })
JSON.parse(response.body)
end

Expand Down Expand Up @@ -303,5 +306,4 @@
expect(json.any? { |v| v['code'] == gql_input.key }).to be_falsey
end
end # GET /api/v3/scenarios/:scenario_id/inputs

end

0 comments on commit 56aea09

Please sign in to comment.