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

Feature/105 Add waterbody model #122

Merged
merged 10 commits into from
Apr 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
46 changes: 46 additions & 0 deletions app/controllers/admin/waterbodies_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
module Admin
class WaterbodiesController < Admin::ApplicationController
# Overwrite any of the RESTful controller actions to implement custom behavior
# For example, you may want to send an email after a foo is updated.
#
# def update
# super
# send_foo_updated_email(requested_resource)
# end

# Override this method to specify custom lookup behavior.
# This will be used to set the resource for the `show`, `edit`, and `update`
# actions.
#
# def find_resource(param)
# Foo.find_by!(slug: param)
# end

# The result of this lookup will be available as `requested_resource`

# Override this if you have certain roles that require a subset
# this will be used to set the records shown on the `index` action.
#
# def scoped_resource
# if current_user.super_admin?
# resource_class
# else
# resource_class.with_less_stuff
# end
# end

# Override `resource_params` if you want to transform the submitted
# data before it's persisted. For example, the following would turn all
# empty values into nil values. It uses other APIs such as `resource_class`
# and `dashboard`:
#
# def resource_params
# params.require(resource_class.model_name.param_key).
# permit(dashboard.permitted_attributes).
# transform_values { |value| value == "" ? nil : value }
# end

# See https://administrate-prototype.herokuapp.com/customizing_controller_actions
# for more information
end
end
2 changes: 1 addition & 1 deletion app/controllers/application_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ def authorize!
return if controller_name == 'home' && action_name == 'index'

# TODO: This is cheap, reorganize properly
if %w[measurements sensors sponsors].include?(controller_name) &&
if %w[waterbodies measurements sensors sponsors].include?(controller_name) &&
%w[index show aggregated daily_temperatures hourly_temperatures sponsor].include?(action_name)
return require_public_access!
end
Expand Down
9 changes: 9 additions & 0 deletions app/controllers/waterbodies_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
class WaterbodiesController < ApplicationController
def index
@waterbodies = Waterbody.all.order(created_at: :asc)
end

def show
@waterbody = Waterbody.find(params[:id])
end
end
4 changes: 4 additions & 0 deletions app/dashboards/sensor_dashboard.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class SensorDashboard < Administrate::BaseDashboard
ATTRIBUTE_TYPES = {
measurements: Field::HasMany,
sponsor: Field::BelongsTo,
waterbody: Field::BelongsTo,
id: Field::Number,
device_name: Field::String,
caption: Field::String,
Expand All @@ -27,6 +28,7 @@ class SensorDashboard < Administrate::BaseDashboard
COLLECTION_ATTRIBUTES = %i[
measurements
sponsor
waterbody
id
device_name
].freeze
Expand All @@ -36,6 +38,7 @@ class SensorDashboard < Administrate::BaseDashboard
SHOW_PAGE_ATTRIBUTES = %i[
measurements
sponsor
waterbody
id
device_name
caption
Expand All @@ -50,6 +53,7 @@ class SensorDashboard < Administrate::BaseDashboard
# on the model's form (`new` and `edit`) pages.
FORM_ATTRIBUTES = %i[
sponsor
waterbody
device_name
caption
latitude
Expand Down
76 changes: 76 additions & 0 deletions app/dashboards/waterbody_dashboard.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
require 'administrate/base_dashboard'

class WaterbodyDashboard < Administrate::BaseDashboard
# ATTRIBUTE_TYPES
# a hash that describes the type of each of the model's fields.
#
# Each different type represents an Administrate::Field object,
# which determines how the attribute is displayed
# on pages throughout the dashboard.
ATTRIBUTE_TYPES = {
id: Field::Number,
description: Field::String,
latitude: Field::Number.with_options(decimals: 2),
longitude: Field::Number.with_options(decimals: 2),
name: Field::String,
sensors: Field::HasMany,
created_at: Field::DateTime,
updated_at: Field::DateTime
}.freeze

# COLLECTION_ATTRIBUTES
# an array of attributes that will be displayed on the model's index page.
#
# By default, it's limited to four items to reduce clutter on index pages.
# Feel free to add, remove, or rearrange items.
COLLECTION_ATTRIBUTES = %i[
id
name
description
sensors
latitude
longitude
].freeze

# SHOW_PAGE_ATTRIBUTES
# an array of attributes that will be displayed on the model's show page.
SHOW_PAGE_ATTRIBUTES = %i[
id
name
description
sensors
latitude
longitude
created_at
updated_at
].freeze

# FORM_ATTRIBUTES
# an array of attributes that will be displayed
# on the model's form (`new` and `edit`) pages.
FORM_ATTRIBUTES = %i[
name
description
latitude
longitude
].freeze

# COLLECTION_FILTERS
# a hash that defines filters that can be used while searching via the search
# field of the dashboard.
#
# For example to add an option to search for open resources by typing "open:"
# in the search field:
#
# COLLECTION_FILTERS = {
# open: ->(resources) { resources.where(open: true) }
# }.freeze
COLLECTION_FILTERS = {}.freeze

# Overwrite this method to customize how waterbodies are displayed
# across all pages of the admin dashboard.
#
# def display_resource(waterbody)
# "Waterbody ##{waterbody.id}"
# end
end
1 change: 1 addition & 0 deletions app/models/sensor.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
class Sensor < ApplicationRecord
has_many :measurements, dependent: :destroy
belongs_to :sponsor, optional: true
belongs_to :waterbody, optional: true
rnestler marked this conversation as resolved.
Show resolved Hide resolved

validates :device_name, presence: true
validates :caption, presence: true
Expand Down
5 changes: 5 additions & 0 deletions app/models/waterbody.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class Waterbody < ApplicationRecord
has_many :sensors, dependent: :nullify

validates :name, :latitude, :longitude, presence: true
end
4 changes: 4 additions & 0 deletions app/views/waterbodies/index.json.jbuilder
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
json.array!(@waterbodies) do |waterbody|
json.extract! waterbody, :id, :name, :description, :latitude, :longitude, :sensor_ids
json.url waterbody_url(waterbody, format: :json)
end
2 changes: 2 additions & 0 deletions app/views/waterbodies/show.json.jbuilder
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
json.extract! @waterbody, :id, :name, :description, :latitude, :longitude,
:sensor_ids, :created_at, :updated_at
2 changes: 2 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
resources :measurements
resources :sensors
resources :sponsors
resources :waterbodies

root to: "sensors#index"
end
Expand All @@ -16,6 +17,7 @@
end
resources :sensors
resources :sponsors
resources :waterbodies, only: [:index, :show]

namespace :mobile_app do
resources :sensors, only: [:index, :show] do
Expand Down
12 changes: 12 additions & 0 deletions db/migrate/20230205145109_create_waterbodies.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
class CreateWaterbodies < ActiveRecord::Migration[6.1]
def change
create_table :waterbodies do |t|
t.string :name, null: false
t.string :description, null: false
rnestler marked this conversation as resolved.
Show resolved Hide resolved
t.float :latitude, null: false
t.float :longitude, null: false

t.timestamps
end
end
end
5 changes: 5 additions & 0 deletions db/migrate/20230205152214_add_waterbody_ref_to_sensors.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class AddWaterbodyRefToSensors < ActiveRecord::Migration[6.1]
def change
add_reference :sensors, :waterbody, foreign_key: true
end
end
14 changes: 13 additions & 1 deletion db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema.define(version: 2023_01_20_212413) do
ActiveRecord::Schema.define(version: 2023_02_05_152214) do

# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
Expand Down Expand Up @@ -42,7 +42,9 @@
t.datetime "updated_at", null: false
t.float "latitude", null: false
t.float "longitude", null: false
t.bigint "waterbody_id"
t.index ["sponsor_id"], name: "index_sensors_on_sponsor_id"
t.index ["waterbody_id"], name: "index_sensors_on_waterbody_id"
end

create_table "sponsors", id: :serial, force: :cascade do |t|
Expand All @@ -54,5 +56,15 @@
t.string "logo_source", comment: "filename (in ./public/images/), relative path or URL"
end

create_table "waterbodies", force: :cascade do |t|
t.string "name", null: false
t.string "description", null: false
t.float "latitude", null: false
t.float "longitude", null: false
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
end

add_foreign_key "measurements", "sensors"
add_foreign_key "sensors", "waterbodies"
end
17 changes: 17 additions & 0 deletions test/controllers/admin/waterbodies_controller_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
require 'test_helper'

class WaterbodiesControllerTest < ActionDispatch::IntegrationTest
setup do
@headers = admin_auth_header
end

test 'should get unauthorized without authentication' do
get admin_waterbodies_url
assert_response :unauthorized
end

test 'should get success with authentication' do
get admin_waterbodies_url, headers: @headers
assert_response :success
end
end
27 changes: 27 additions & 0 deletions test/controllers/waterbodies_controller_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
require 'test_helper'

class WaterbodiesControllerTest < ActionDispatch::IntegrationTest
setup do
@waterbody = create(:waterbody)
end

test 'should get unauthorized without auth header' do
get waterbodies_url
assert_response :unauthorized
end

test 'should get index' do
get waterbodies_url, env: public_auth_header
assert_response :success
response_object = JSON.parse(response.body)
assert response_object.length == 1
assert response_object[0]['name'] == @waterbody.name
end

test 'get an individual waterbody' do
get waterbody_url(@waterbody), env: public_auth_header
assert_response :success
response_object = JSON.parse(response.body)
assert response_object['name'] == @waterbody.name
end
end
8 changes: 8 additions & 0 deletions test/factories/waterbodies.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
FactoryBot.define do
factory :waterbody do
name { 'Zürichsee' }
description { 'Our favorite lake' }
latitude { 47.222578 }
longitude { 8.814744 }
end
end
11 changes: 11 additions & 0 deletions test/models/waterbody_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
require 'test_helper'

class WaterbodyTest < ActiveSupport::TestCase
test 'should nullify sensor waterbody references on destroy' do
sensor = create(:sensor)
waterbody = create(:waterbody, sensors: [sensor])
assert_equal sensor.waterbody, waterbody
waterbody.destroy
assert_nil sensor.reload.waterbody
end
end
rnestler marked this conversation as resolved.
Show resolved Hide resolved