스케쥴 추가 기능 구현

This commit is contained in:
RubyOn 2025-04-19 00:07:28 +09:00
parent eb3bc33509
commit 32d0ac69c9
13 changed files with 141 additions and 63 deletions

View File

@ -1,5 +1,6 @@
class ModalsController < ApplicationController
def open
@schedule = Schedule.new
render partial: "partials/modals_open", locals: { type: params[:type], close_button: params[:close_button] }
end
end

View File

@ -1,53 +1,11 @@
class ModbusController < ApplicationController
def index
@schedule = Schedule.all
@modbus_running = Modbus::PollingService.running?
end
def destroy
schedule = Schedule.find_by(id: params[:id])
if schedule.destroy
redirect_to schedule_edit_modbus_index_path, notice: "스케줄이 삭제되었습니다."
else
redirect_to schedule_edit_modbus_index_path, alert: "스케줄 삭제에 실패했습니다."
end
end
def start
Modbus::PollingService.start
redirect_to modbus_index_path
redirect_to schedules_path
end
def stop
Modbus::PollingService.stop
redirect_to modbus_index_path
end
def schedule_edit
@schedule = Schedule.all
end
def schedule_edit_update
error_time = []
params[:schedule].each do |id, attributes|
schedule = Schedule.find_by(id: id)
unless schedule.update(
hour: attributes[:hour],
minute: attributes[:minute],
is_active: attributes[:is_active],
temperature: attributes[:temperature]
)
error_time << "#{schedule.hour}#{schedule.minute}"
end
end
if error_time.any?
redirect_to modbus_index_path, alert: "#{error_time.join(', ')}의 온도 업데이트에 실패하였습니다."
else
redirect_to modbus_index_path, notice: "스케줄이 성공적으로 업데이트되었습니다."
end
redirect_to schedules_path
end
end

View File

@ -0,0 +1,68 @@
class SchedulesController < ApplicationController
def index
@schedule = Schedule.order(:hour, :minute)
@modbus_running = Modbus::PollingService.running?
end
def new
@schedule = Schedule.new
end
def create
@schedule = Schedule.new(schedule_params)
if @schedule.save
redirect_to schedule_edit_schedules_path, notice: "스케쥴이 추가 되었습니다."
else
error_messages = @schedule.errors.full_messages.join(", ")
redirect_to schedule_edit_schedules_path, alert: "스케쥴 추가 실패: #{error_messages}"
end
end
def destroy
@schedule = Schedule.find_by(id: params[:id])
if @schedule.destroy
redirect_to schedule_edit_schedules_path, notice: "스케줄이 삭제되었습니다."
else
error_messages = @schedule.errors.full_messages.join(", ")
redirect_to schedule_edit_schedules_path, alert: "스케쥴 삭제 실패: #{error_messages}"
end
end
def schedule_edit
@schedule = Schedule.order(:hour, :minute)
end
def schedule_edit_update
error_messages = []
params[:schedule].each do |id, attributes|
schedule = Schedule.find_by(id: id)
next unless schedule
unless schedule.update(
hour: attributes[:hour],
minute: attributes[:minute],
is_active: attributes[:is_active],
temperature: attributes[:temperature]
)
error_detail = schedule.errors.full_messages.join(", ")
time_label = "#{attributes[:hour]}#{attributes[:minute]}"
error_messages << "#{time_label} - #{error_detail}"
end
end
if error_messages.any?
redirect_to schedules_path, alert: error_messages.join("<br>")
else
redirect_to schedules_path, notice: "스케줄이 성공적으로 업데이트되었습니다."
end
end
private
def schedule_params
params.require(:schedule).permit(:hour, :minute, :is_active, :temperature)
end
end

View File

@ -0,0 +1,2 @@
module SchedulesHelper
end

View File

@ -45,10 +45,7 @@ export default class extends Controller {
setTimeout(() => {
const modalsFrame = document.querySelector("turbo-frame#modals")
if (modalsFrame) {
modalsFrame.innerHTML = ""
window.location.reload()
}
}, 300) // 닫힘 애니메이션 시간과 동일하게 300ms 지연 후 모달 제거
}
}

View File

@ -1,9 +1,9 @@
class Schedule < ApplicationRecord
validates :hour, presence: true
validates :minute, presence: true
validates :hour, presence: { message: "시간을 입력하세요" }
validates :minute, presence: { message: "분을 입력하세요" }
validates :temperature,
presence: true,
numericality: true,
format: { with: /\A\d+(\.\d)?\z/ }
validates :minute, uniqueness: { scope: :hour }
presence: { message: "온도를 입력하세요" },
numericality: { message: "온도는 숫자여야 합니다" },
format: { with: /\A\d+(\.\d)?\z/, message: "온도는 소수점 한 자리까지 입력 가능합니다" }
validates :minute, uniqueness: { scope: :hour, message: "같은 시:분의 스케쥴이 이미 존재합니다" }
end

View File

@ -29,9 +29,8 @@ module Modbus
begin
now = Time.now
current = [ now.hour, now.min ]
if current != last_logged
puts "시간 변경 감지됨: #{current.join(':')}"
puts "시간 변경 감지됨: #{format('%02d:%02d', current[0], current[1])}"
schedule = Schedule.find_by(hour: current[0], minute: current[1])
apply_schedule(schedule) if schedule
last_logged = current

View File

@ -31,11 +31,11 @@
<div class="w-full h-full">
<% if flash[:notice] %>
<div class="m-4 rounded px-4 py-2 bg-accept text-white">
<%= flash[:notice] %>
<%= raw flash[:notice] %>
</div>
<% elsif flash[:alert] %>
<div class="m-4 rounded px-4 py-2 bg-danger text-white">
<%= flash[:alert] %>
<%= raw flash[:alert] %>
</div>
<% end %>
<%= yield %>

View File

@ -1 +1,39 @@
스케쥴 추가
<%= form_with model: @schedule, method: :post, data: { turbo: false }, class: 'flex flex-col h-full divide-y divide-border-table-border' do |form| %>
<div class="flex-1 p-4">
<table class="base-table">
<thead>
<tr>
<th>시간</th>
<th>분</th>
<th>사용여부</th>
<th>온도</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<%= form.select :hour,
options_for_select((0..23).map { |h| [h.to_s.rjust(2, '0'), h] }, @schedule.hour),
{},
class: "input-style" %>
</td>
<td>
<%= form.number_field :minute,
min: 0, max: 59, step: 1, inputmode: "decimal", class: "input-style" %>
</td>
<td>
<%= check_box_tag "schedule[is_active]", "1", true %>
</td>
<td>
<%= form.number_field :temperature,
step: "0.1", inputmode: "decimal", class: "input-style" %>
</td>
</tr>
</tbody>
</table>
</div>
<div class="flex p-4">
<%= submit_tag "추가", class: "btn bg-primary" %>
</div>
<% end %>

View File

@ -37,6 +37,6 @@
</div>
</div>
<div class="flex p-4">
<%= link_to "수정", "/modbus/schedule_edit", class: "btn bg-default-slate" %>
<%= link_to "수정", schedule_edit_schedules_path, class: "btn bg-default-slate" %>
</div>
</div>

View File

@ -1,4 +1,4 @@
<%= form_with url: schedule_edit_update_modbus_index_path, method: :post, class: 'flex flex-col h-full divide-y divide-border-table-border' do %>
<%= form_with url: schedule_edit_update_schedules_path, method: :post, class: 'flex flex-col h-full divide-y divide-border-table-border' do %>
<div class="flex-1 p-4">
<table class="base-table">
<thead>
@ -22,7 +22,7 @@
<td><%= check_box_tag "schedule[#{s.id}][is_active]", "1", s.is_active == true || s.is_active == 1 %></td>
<td><%= number_field_tag "schedule[#{s.id}][temperature]", s.temperature, step: "0.1", inputmode: "decimal", class: "input-style" %></td>
<td>
<%= link_to "삭제", modbus_path(s),
<%= link_to "삭제", schedule_path(s),
data: {
turbo_method: :delete,
turbo_confirm: "정말 삭제하시겠습니까?"

View File

@ -10,7 +10,15 @@ Rails.application.routes.draw do
# get "service-worker" => "rails/pwa#service_worker", as: :pwa_service_worker
# Defines the root path route ("/")
root "modbus#index"
root "schedules#index"
resources :schedules do
collection do
get "schedule_edit"
post "schedule_edit_update"
end
end
resources :modbus do
collection do

View File

@ -0,0 +1,7 @@
require "test_helper"
class SchedulesControllerTest < ActionDispatch::IntegrationTest
# test "the truth" do
# assert true
# end
end