summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarius Peter <marius.peter@tutanota.com>2025-08-29 14:22:37 +0200
committerMarius Peter <marius.peter@tutanota.com>2025-08-29 14:22:37 +0200
commit075665c588989ed0decdfb20d83f32b33eed4639 (patch)
treed9ec78be7338bd51c895b7fb311f081a7c77c45f
parent52b044d6a4278c229992404ad5801769c2d13363 (diff)
Properly implement bed and raft management logic.
-rw-r--r--app/controllers/beds_controller.rb61
-rw-r--r--app/controllers/crops_controller.rb34
-rw-r--r--app/controllers/rafts_controller.rb53
-rw-r--r--app/helpers/beds_helper.rb2
-rw-r--r--app/models/bed.rb1
-rw-r--r--app/models/raft.rb2
-rw-r--r--app/views/application/_navbar.html.erb12
-rw-r--r--app/views/beds/_bed.html.erb2
-rw-r--r--app/views/beds/_form.html.erb28
-rw-r--r--app/views/beds/edit.html.erb11
-rw-r--r--app/views/beds/index.html.erb54
-rw-r--r--app/views/dashboard/_nutrient_measurements.html.erb (renamed from app/views/dashboard/_recent_measurements.html.erb)0
-rw-r--r--app/views/dashboard/_raft_allocation.html.erb4
-rw-r--r--app/views/dashboard/index.html.erb2
-rw-r--r--app/views/rafts/_form.html.erb23
-rw-r--r--app/views/rafts/edit.html.erb5
-rw-r--r--app/views/rafts/editor.html.erb108
-rw-r--r--config/routes.rb17
-rw-r--r--db/seeds/3_crops.rb22
-rw-r--r--db/seeds/4_beds_and_rafts.rb2
-rw-r--r--test/controllers/beds_controller_test.rb48
-rw-r--r--test/fixtures/beds.yml14
-rw-r--r--test/system/beds_test.rb39
23 files changed, 338 insertions, 206 deletions
diff --git a/app/controllers/beds_controller.rb b/app/controllers/beds_controller.rb
new file mode 100644
index 0000000..c213978
--- /dev/null
+++ b/app/controllers/beds_controller.rb
@@ -0,0 +1,61 @@
+class BedsController < ApplicationController
+ before_action :set_bed, only: %i[ edit update ]
+ before_action :get_crops, only: %i[ index edit update ]
+
+ def index
+ @beds = Bed.all
+ end
+
+ def edit
+ end
+
+ def update
+ if @bed.update(bed_params)
+ redirect_to beds_path, notice: "Bed #{@bed.id} successfully updated."
+ else
+ render :edit, status: :unprocessable_entity
+ end
+ end
+
+ def bulk_assign_crops
+ crop = Crop.find(params[:crop_id])
+ Raft.update_all(crop_id: crop.id)
+ redirect_back fallback_location: root_path, notice: "All rafts set to #{crop.name}."
+ end
+
+
+ def reset_seed_crops
+ # mirrors seed logic
+ tomatoes = Crop.find_by!(name: :tomatoes)
+ chives = Crop.find_by!(name: :chives)
+ lettuce = Crop.find_by!(name: :lettuce)
+
+ Bed.includes(:rafts).find_each do |bed|
+ default_crop =
+ case bed.location
+ when 1..3 then tomatoes
+ when 4..7 then chives
+ else lettuce
+ end
+ bed.rafts.update_all(crop_id: default_crop.id)
+ end
+ redirect_back fallback_location: root_path, notice: "Raft crops reset to default seed layout."
+ end
+
+ private
+
+ def set_bed
+ @bed = Bed.find(params[:id])
+ end
+
+ def get_crops
+ @crops = Crop.order(:name)
+ end
+
+ def bed_params
+ params.require(:bed).permit(
+ :location,
+ rafts_attributes: %i[id crop_id]
+ )
+ end
+end
diff --git a/app/controllers/crops_controller.rb b/app/controllers/crops_controller.rb
index 9619852..951d380 100644
--- a/app/controllers/crops_controller.rb
+++ b/app/controllers/crops_controller.rb
@@ -1,40 +1,30 @@
class CropsController < ApplicationController
before_action :set_crop, only: %i[ show edit update destroy ]
- # GET /crops or /crops.json
def index
@crops = Crop.all
end
- # GET /crops/1 or /crops/1.json
def show
end
- # GET /crops/new
def new
@crop = Crop.new
end
- # GET /crops/1/edit
def edit
end
- # POST /crops or /crops.json
def create
@crop = Crop.new(crop_params)
- respond_to do |format|
- if @crop.save
- format.html { redirect_to @crop, notice: "Crop was successfully created." }
- format.json { render :show, status: :created, location: @crop }
- else
- format.html { render :new, status: :unprocessable_entity }
- format.json { render json: @crop.errors, status: :unprocessable_entity }
- end
+ if @crop.save
+ redirect_to @crop, notice: "Crop was successfully created."
+ else
+ render :new, status: :unprocessable_entity
end
end
- # PATCH/PUT /crops/1 or /crops/1.json
def update
respond_to do |format|
if @crop.update(crop_params)
@@ -47,7 +37,6 @@ class CropsController < ApplicationController
end
end
- # DELETE /crops/1 or /crops/1.json
def destroy
@crop.destroy!
@@ -58,13 +47,12 @@ class CropsController < ApplicationController
end
private
- # Use callbacks to share common setup or constraints between actions.
- def set_crop
- @crop = Crop.find(params.expect(:id))
- end
- # Only allow a list of trusted parameters through.
- def crop_params
- params.expect(crop: [ :name, :crop_type, :nno3, :p, :k, :ca, :mg, :s, :na, :cl, :si, :fe, :zn, :b, :mn, :cu, :mo, :nnh4 ])
- end
+ def set_crop
+ @crop = Crop.find(params.expect(:id))
+ end
+
+ def crop_params
+ params.expect(crop: [ :name, :crop_type, :nno3, :p, :k, :ca, :mg, :s, :na, :cl, :si, :fe, :zn, :b, :mn, :cu, :mo, :nnh4 ])
+ end
end
diff --git a/app/controllers/rafts_controller.rb b/app/controllers/rafts_controller.rb
index 96d99fd..c1c8a72 100644
--- a/app/controllers/rafts_controller.rb
+++ b/app/controllers/rafts_controller.rb
@@ -1,54 +1,29 @@
class RaftsController < ApplicationController
- before_action :set_collections, only: [ :editor ]
+ before_action :set_raft, only: %i[ edit update ]
+ before_action :set_crop, only: %i[ edit update ]
- def index
- redirect_to editor_rafts_path
+ def edit
end
- def editor
- # @beds, @crops set in before_action
- end
-
- # 1) Assign ALL rafts
- def assign_all
- crop_id = normalized_crop_id(params[:crop_id])
- Raft.update_all(crop_id: crop_id) # nil ok
- redirect_to editor_rafts_path, notice: "All rafts updated."
- end
-
- # 2) Assign all rafts in ONE bed
- def assign_bed
- bed = Bed.find(params.require(:bed_id))
- crop_id = normalized_crop_id(params[:crop_id])
- bed.rafts.update_all(crop_id: crop_id)
- redirect_to editor_rafts_path, notice: "Bed ##{bed.location} updated."
- end
-
- # 3) Assign ONE raft
- def assign_one
- raft = Raft.find(params[:id])
- val = params[:crop_id].to_s
-
- if val.blank? || val.casecmp("null").zero?
- # Skip validations; write NULL directly
- raft.update_column(:crop_id, nil)
+ def update
+ if @raft.update(raft_params)
+ redirect_to beds_path, notice: "Raft #{@raft.id} successfully updated."
else
- raft.update!(crop_id: val)
+ render :edit, status: :unprocessable_entity
end
-
- redirect_to editor_rafts_path(anchor: "bed-#{raft.bed_id}"), notice: "Raft updated."
end
private
- def set_collections
- @beds = Bed.order(:location)
+ def set_raft
+ @raft = Raft.find(params[:id])
+ end
+
+ def set_crop
@crops = Crop.order(:name)
end
- # Accept "", "null" → nil to allow clearing
- def normalized_crop_id(val)
- return nil if val.blank? || val.to_s.downcase == "null"
- val
+ def raft_params
+ params.require(:raft).permit(:location, :bed_id, :crop_id)
end
end
diff --git a/app/helpers/beds_helper.rb b/app/helpers/beds_helper.rb
new file mode 100644
index 0000000..2f3e2cb
--- /dev/null
+++ b/app/helpers/beds_helper.rb
@@ -0,0 +1,2 @@
+module BedsHelper
+end
diff --git a/app/models/bed.rb b/app/models/bed.rb
index 33eafd2..d41afe6 100644
--- a/app/models/bed.rb
+++ b/app/models/bed.rb
@@ -1,4 +1,5 @@
class Bed < ApplicationRecord
has_many :rafts, -> { order(:location) }, dependent: :destroy
+ accepts_nested_attributes_for :rafts
validates :location, presence: true, uniqueness: true
end
diff --git a/app/models/raft.rb b/app/models/raft.rb
index af52700..3fe5928 100644
--- a/app/models/raft.rb
+++ b/app/models/raft.rb
@@ -1,5 +1,5 @@
class Raft < ApplicationRecord
belongs_to :bed
- belongs_to :crop
+ belongs_to :crop, optional: true
validates :location, presence: true, uniqueness: { scope: :bed_id }
end
diff --git a/app/views/application/_navbar.html.erb b/app/views/application/_navbar.html.erb
index 9fa250a..89dfe3d 100644
--- a/app/views/application/_navbar.html.erb
+++ b/app/views/application/_navbar.html.erb
@@ -3,12 +3,12 @@
<span class="navbar-brand">FAPG</span>
<button class="navbar-toggler"
- type="button"
- data-bs-toggle="collapse"
- data-bs-target="#navbarSupportedContent"
- aria-controls="navbarSupportedContent"
- aria-expanded="false"
- aria-label="Toggle navigation">
+ type="button"
+ data-bs-toggle="collapse"
+ data-bs-target="#navbarSupportedContent"
+ aria-controls="navbarSupportedContent"
+ aria-expanded="false"
+ aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
diff --git a/app/views/beds/_bed.html.erb b/app/views/beds/_bed.html.erb
new file mode 100644
index 0000000..6961f9b
--- /dev/null
+++ b/app/views/beds/_bed.html.erb
@@ -0,0 +1,2 @@
+<div id="<%= dom_id bed %>">
+</div>
diff --git a/app/views/beds/_form.html.erb b/app/views/beds/_form.html.erb
new file mode 100644
index 0000000..e3a5c35
--- /dev/null
+++ b/app/views/beds/_form.html.erb
@@ -0,0 +1,28 @@
+<%= form_with(model: bed) do |form| %>
+ <% if bed.errors.any? %>
+ <div style="color: red">
+ <h2><%= pluralize(bed.errors.count, "error") %> prohibited this bed from being saved:</h2>
+ <ul>
+ <% bed.errors.each do |error| %>
+ <li><%= error.full_message %></li>
+ <% end %>
+ </ul>
+ </div>
+ <% end %>
+
+ <div class="my-3">
+ <%= form.fields_for :rafts do |raft| %>
+ <div class="input-group input-group-sm my-2">
+ <span class="input-group-text">Raft <%= raft.object.location %></span>
+ <%= raft.collection_select :crop_id, @crops, :id, :name,
+ { include_blank: "Unassigned" },
+ { class: "form-select" } %>
+ </div>
+ <%= raft.hidden_field :id %>
+ <% end %>
+ </div>
+
+ <div>
+ <%= form.submit class: "btn btn-primary" %>
+ </div>
+<% end %>
diff --git a/app/views/beds/edit.html.erb b/app/views/beds/edit.html.erb
new file mode 100644
index 0000000..6887586
--- /dev/null
+++ b/app/views/beds/edit.html.erb
@@ -0,0 +1,11 @@
+<% content_for :title, "Editing bed #{@bed.location}" %>
+
+<h1 class="display-1">Editing bed <%= @bed.location %></h1>
+
+<%= render "form", bed: @bed %>
+
+<br>
+
+<div>
+ <%= link_to "Back to beds", beds_path, class: "btn btn-secondary" %>
+</div>
diff --git a/app/views/beds/index.html.erb b/app/views/beds/index.html.erb
new file mode 100644
index 0000000..e645dc5
--- /dev/null
+++ b/app/views/beds/index.html.erb
@@ -0,0 +1,54 @@
+<% content_for :title, "Crop Allocation" %>
+
+<h1 class="display-1">Beds and Rafts</h1>
+
+<%= link_to "Back to dashboard", root_path, class: "btn btn-outline-secondary my-3" %>
+
+
+<p>
+ Click on a bed row or an individual raft to update the corresponding crop.
+</p>
+
+<%= form_with url: bulk_assign_crops_beds_path,
+ method: :patch,
+ local: true do %>
+ <div class="btn-group" role="group" aria-label="Raft crop bulk actions">
+ <select class="form-select" name="crop_id">
+ <% @crops.each do |crop| %>
+ <option value="<%= crop.id %>"><%= crop.name.titleize %></option>
+ <% end %>
+ </select>
+ <button type="submit" class="btn btn-outline-primary">Apply to all</button>
+ </div>
+<% end %>
+
+<div class="table-responsive">
+ <table class="table table-sm small text-center align-middle my-3">
+ <thead>
+ <tr>
+ <th>Bed</th>
+ <% max_cols = @beds.map { |b| b.rafts.count }.max %>
+ <% (1..max_cols).each do |i| %>
+ <th>R<%= i %></th>
+ <% end %>
+ </tr>
+ </thead>
+ <tbody>
+ <% @beds.each do |bed| %>
+ <tr>
+ <th><%= link_to bed.location, edit_bed_path(bed), class: "btn btn-outline-secondary" %></th>
+ <% bed.rafts.each do |raft| %>
+ <td>
+ <%= link_to (raft&.crop&.name || "—"), edit_raft_path(raft), class: "btn btn-sm" %>
+ </td>
+ <% end %>
+ </tr>
+ <% end %>
+ </tbody>
+ </table>
+</div>
+
+<%= button_to "Reset crop allocation", reset_seed_crops_beds_path,
+ method: :post,
+ form: { data: { turbo: false } },
+ class: "btn btn-outline-danger" %>
diff --git a/app/views/dashboard/_recent_measurements.html.erb b/app/views/dashboard/_nutrient_measurements.html.erb
index bc63a60..bc63a60 100644
--- a/app/views/dashboard/_recent_measurements.html.erb
+++ b/app/views/dashboard/_nutrient_measurements.html.erb
diff --git a/app/views/dashboard/_raft_allocation.html.erb b/app/views/dashboard/_raft_allocation.html.erb
index ef95cdd..a2128ea 100644
--- a/app/views/dashboard/_raft_allocation.html.erb
+++ b/app/views/dashboard/_raft_allocation.html.erb
@@ -1,7 +1,7 @@
<div class="card shadow mb-4">
<div class="card-header d-flex justify-content-between align-items-center">
- <h5 class="mb-0">Raft Allocation</h5>
- <%= link_to "Edit raft allocation", editor_rafts_path, class: "btn btn-sm btn-primary" %>
+ <h5 class="mb-0">Crop Allocation</h5>
+ <%= link_to "Edit allocation", beds_path, class: "btn btn-sm btn-primary" %>
</div>
<%= bar_chart @raft_data, stacked: true %>
diff --git a/app/views/dashboard/index.html.erb b/app/views/dashboard/index.html.erb
index 2902ada..b1b2d87 100644
--- a/app/views/dashboard/index.html.erb
+++ b/app/views/dashboard/index.html.erb
@@ -4,4 +4,4 @@
<%= render "target_table" %>
-<%= render "recent_measurements" %>
+<%= render "nutrient_measurements" %>
diff --git a/app/views/rafts/_form.html.erb b/app/views/rafts/_form.html.erb
new file mode 100644
index 0000000..7b5d382
--- /dev/null
+++ b/app/views/rafts/_form.html.erb
@@ -0,0 +1,23 @@
+<%= form_with(model: raft) do |form| %>
+ <% if raft.errors.any? %>
+ <div style="color: red">
+ <h2><%= pluralize(bed.errors.count, "error") %> prohibited this raft from being saved:</h2>
+
+ <ul>
+ <% raft.errors.each do |error| %>
+ <li><%= error.full_message %></li>
+ <% end %>
+ </ul>
+ </div>
+ <% end %>
+
+ <div class="my-3">
+ <label class="form-label">Crop</label>
+ <%= form.collection_select :crop_id, @crops, :id, :name,
+ { include_blank: "Unassigned" }, { class: "form-select" } %>
+ </div>
+
+ <div>
+ <%= form.submit class: "btn btn-primary" %>
+ </div>
+<% end %>
diff --git a/app/views/rafts/edit.html.erb b/app/views/rafts/edit.html.erb
new file mode 100644
index 0000000..bf975dc
--- /dev/null
+++ b/app/views/rafts/edit.html.erb
@@ -0,0 +1,5 @@
+<% content_for :title, "Editing bed #{@raft.bed.location}, raft #{@raft.location}" %>
+
+<h1 class="display-1">Editing bed <%= @raft.bed.location %>, raft <%= @raft.location %></h1>
+
+<%= render "form", raft: @raft %>
diff --git a/app/views/rafts/editor.html.erb b/app/views/rafts/editor.html.erb
deleted file mode 100644
index cde56d8..0000000
--- a/app/views/rafts/editor.html.erb
+++ /dev/null
@@ -1,108 +0,0 @@
-<div class="d-flex justify-content-between align-items-center mb-3">
- <h1 class="display-1">Rafts editor</h1>
- <%= link_to "Back to dashboard", root_path, class: "btn btn-outline-secondary" %>
-</div>
-
-<!-- Bulk assign all rafts -->
-<div class="card">
- <div class="card-header">Assign ALL rafts</div>
- <div class="card-body">
- <%= form_with url: assign_all_rafts_path, method: :patch, class: "row g-2", data: { turbo: false } do %>
- <div class="col-12 col-md-6">
- <select class="form-select" name="crop_id">
- <option value="">— Unassigned (clear) —</option>
- <% @crops.each do |crop| %>
- <option value="<%= crop.id %>"><%= crop.name %></option>
- <% end %>
- </select>
- </div>
- <div class="col-12 col-md-auto">
- <button class="btn btn-primary">Apply to all</button>
- </div>
- <% end %>
- </div>
-</div>
-
-<div class="table-responsive">
- <table class="table table-sm table-striped text-center align-middle my-3">
- <thead>
- <tr>
- <th class="text-start">Bed</th>
- <% max_cols = @beds.map { |b| b.rafts.count }.max %>
- <% (1..max_cols).each do |i| %>
- <th>R<%= i %></th>
- <% end %>
- </tr>
- </thead>
- <tbody>
- <% @beds.each do |bed| %>
- <tr>
- <th><%= bed.location %></th>
- <% bed.rafts.order(:location).each do |raft| %>
- <td>
- <% if raft.crop %>
- <%= raft.crop.name %>
- <% else %>
- —
- <% end %>
- </td>
- <% end %>
- </tr>
- <% end %>
- </tbody>
- </table>
-</div>
-
-<!-- Per-bed tables -->
-<% @beds.each do |bed| %>
- <div class="card mb-3" id="bed-<%= bed.id %>">
- <div class="card-header d-flex flex-wrap gap-2 align-items-center">
- <span class="me-auto">Bed <strong>#<%= bed.location %></strong></span>
- <%= form_with url: assign_bed_rafts_path, method: :patch, class: "d-flex gap-2 align-items-center", data: { turbo: false } do %>
- <input type="hidden" name="bed_id" value="<%= bed.id %>">
- <select class="form-select" name="crop_id">
- <option value="">— Unassigned (clear) —</option>
- <% @crops.each do |crop| %>
- <option value="<%= crop.id %>"><%= crop.name %></option>
- <% end %>
- </select>
- <button class="btn btn-primary">Apply</button>
- <% end %>
- </div>
- <div class="card-body p-0">
- <div class="table-responsive">
- <table class="table table-sm mb-0 align-middle">
- <thead class="table-light">
- <tr>
- <th class="text-nowrap text-center">Raft</th>
- <th>Crop</th>
- <th class="text-end">Actions</th>
- </tr>
- </thead>
- <tbody>
- <% bed.rafts.order(:location).each do |raft| %>
- <tr>
- <td class="text-center"><strong><%= raft.location %></strong></td>
- <td style="max-width: 280px;">
- <%= form_with url: assign_one_raft_path(raft), method: :patch, class: "d-flex gap-2", data: { turbo: false } do %>
- <select class="form-select" name="crop_id">
- <option value="">— Unassigned (clear) —</option>
- <% @crops.each do |crop| %>
- <option value="<%= crop.id %>" <%= "selected" if raft.crop_id == crop.id %>><%= crop.name %></option>
- <% end %>
- </select>
- <button class="btn btn-outline-primary">Save</button>
- <% end %>
- </td>
- <td class="text-end">
- <%= button_to "Clear", assign_one_raft_path(raft, crop_id: ""), method: :patch,
- form: { data: { turbo: false } }, class: "btn btn-outline-secondary btn-sm" %>
- </td>
- </tr>
- <% end %>
- </tbody>
- </table>
- </div>
- </div>
- </div>
-<% end %>
diff --git a/config/routes.rb b/config/routes.rb
index 1b24155..1dd57b5 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -2,18 +2,17 @@ Rails.application.routes.draw do
root "dashboard#index"
get "ferti_recipe", to: "recipes#show"
- resources :fertilizer_products
- resources :raft_crops, only: [ :update ]
- resources :rafts, only: [ :index ] do
+
+ resources :beds, only: [ :index, :edit, :update ] do
collection do
- get :editor # rafts/editor
- patch :assign_all # bulk assign all rafts
- patch :assign_bed # bulk assign per bed
- end
- member do
- patch :assign_one # per raft
+ patch :bulk_assign_crops
+ post :reset_seed_crops
end
+
+ resources :rafts, only: [ :index, :edit, :update ], shallow: true
end
+
+ resources :fertilizer_products
resources :crops
resources :nutrient_measurements
diff --git a/db/seeds/3_crops.rb b/db/seeds/3_crops.rb
index 2957188..6a5c10f 100644
--- a/db/seeds/3_crops.rb
+++ b/db/seeds/3_crops.rb
@@ -104,17 +104,17 @@ RASPBERRY = {
}
[
- [ "lettuce", 0, LEAFY ],
- [ "kale", 0, LEAFY ],
- [ "chinese cabbage", 0, LEAFY ],
- [ "tomatoes", 1, TOMATO ],
- [ "raspberries", 1, RASPBERRY ],
- [ "strawberries", 1, STRAWBERRY ],
- [ "hot peppers", 1, HOT_PEPPER ],
- [ "parsley", 2, HERB ],
- [ "chives", 2, HERB ],
- [ "italian basil", 2, HERB ],
- [ "dill", 2, HERB ]
+ [ "lettuce", 0, LEAFY ],
+ [ "kale", 0, LEAFY ],
+ [ "cabbage, chinese", 0, LEAFY ],
+ [ "tomatoes", 1, TOMATO ],
+ [ "raspberries", 1, RASPBERRY ],
+ [ "strawberries", 1, STRAWBERRY ],
+ [ "hot peppers", 1, HOT_PEPPER ],
+ [ "parsley", 2, HERB ],
+ [ "chives", 2, HERB ],
+ [ "italian basil", 2, HERB ],
+ [ "dill", 2, HERB ]
].each do |name, type, nutrient_requirements|
Crop.find_or_create_by!(name: name) do |c|
c.crop_type = type
diff --git a/db/seeds/4_beds_and_rafts.rb b/db/seeds/4_beds_and_rafts.rb
index 0105260..1cd95dc 100644
--- a/db/seeds/4_beds_and_rafts.rb
+++ b/db/seeds/4_beds_and_rafts.rb
@@ -9,7 +9,7 @@ RAFTS = 10
when 3 then "hot peppers"
when 4 then "chives"
when 5 then "italian basil"
- when 6..7 then "chinese cabbage"
+ when 6..7 then "cabbage, chinese"
else "lettuce"
end
diff --git a/test/controllers/beds_controller_test.rb b/test/controllers/beds_controller_test.rb
new file mode 100644
index 0000000..7afd166
--- /dev/null
+++ b/test/controllers/beds_controller_test.rb
@@ -0,0 +1,48 @@
+require "test_helper"
+
+class BedsControllerTest < ActionDispatch::IntegrationTest
+ setup do
+ @bed = beds(:one)
+ end
+
+ test "should get index" do
+ get beds_url
+ assert_response :success
+ end
+
+ test "should get new" do
+ get new_bed_url
+ assert_response :success
+ end
+
+ test "should create bed" do
+ assert_difference("Bed.count") do
+ post beds_url, params: { bed: {} }
+ end
+
+ assert_redirected_to bed_url(Bed.last)
+ end
+
+ test "should show bed" do
+ get bed_url(@bed)
+ assert_response :success
+ end
+
+ test "should get edit" do
+ get edit_bed_url(@bed)
+ assert_response :success
+ end
+
+ test "should update bed" do
+ patch bed_url(@bed), params: { bed: {} }
+ assert_redirected_to bed_url(@bed)
+ end
+
+ test "should destroy bed" do
+ assert_difference("Bed.count", -1) do
+ delete bed_url(@bed)
+ end
+
+ assert_redirected_to beds_url
+ end
+end
diff --git a/test/fixtures/beds.yml b/test/fixtures/beds.yml
index 330db85..d7a3329 100644
--- a/test/fixtures/beds.yml
+++ b/test/fixtures/beds.yml
@@ -1,7 +1,11 @@
# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
-one:
- number: 1
-
-two:
- number: 1
+# This model initially had no columns defined. If you add columns to the
+# model remove the "{}" from the fixture names and add the columns immediately
+# below each fixture, per the syntax in the comments below
+#
+one: {}
+# column: value
+#
+two: {}
+# column: value
diff --git a/test/system/beds_test.rb b/test/system/beds_test.rb
new file mode 100644
index 0000000..b5e6a86
--- /dev/null
+++ b/test/system/beds_test.rb
@@ -0,0 +1,39 @@
+require "application_system_test_case"
+
+class BedsTest < ApplicationSystemTestCase
+ setup do
+ @bed = beds(:one)
+ end
+
+ test "visiting the index" do
+ visit beds_url
+ assert_selector "h1", text: "Beds"
+ end
+
+ test "should create bed" do
+ visit beds_url
+ click_on "New bed"
+
+ click_on "Create Bed"
+
+ assert_text "Bed was successfully created"
+ click_on "Back"
+ end
+
+ test "should update Bed" do
+ visit bed_url(@bed)
+ click_on "Edit this bed", match: :first
+
+ click_on "Update Bed"
+
+ assert_text "Bed was successfully updated"
+ click_on "Back"
+ end
+
+ test "should destroy Bed" do
+ visit bed_url(@bed)
+ click_on "Destroy this bed", match: :first
+
+ assert_text "Bed was successfully destroyed"
+ end
+end
Copyright 2019--2025 Marius PETER