kodamarisa / osinotameni_yasetai

0 stars 0 forks source link

編集ボタンでのモーダルの切り替え #49

Open kodamarisa opened 1 week ago

kodamarisa commented 1 week ago
app/views/schedules/_schedule_details.html.erb
<%= date %>

<% if schedules.any? %> <% schedules.each do |schedule| %>

<%= schedule.exercise.name %> <%= schedule.repetitions %> 回 × <%= schedule.sets %> セット

<% end %> <% else %>

この日にスケジュールはありません。

<% end %>

<% if schedules.count < 3 %>

<% else %>

これ以上スケジュールを追加できません。

<% end %>

app/views/schedules/_edit_modal.html.erb
app/javascript/packs/schedule.js

document.addEventListener("DOMContentLoaded", () => { const scheduleModalEl = document.getElementById("scheduleModal");

if (scheduleModalEl) { const scheduleModal = new bootstrap.Modal(scheduleModalEl); } else { console.error("Schedule modal element not found."); }

const scheduleModal = new bootstrap.Modal(scheduleModalEl); const scheduleForm = document.getElementById("schedule-form");

// 編集ボタンがクリックされたときの処理 const editButtons = document.querySelectorAll('.btn-outline-primary[data-bs-toggle="modal"]');

editButtons.forEach(button => { button.addEventListener('click', function () { const scheduleId = this.getAttribute('data-schedule-id'); const exerciseName = this.getAttribute('data-exercise-name'); const reps = this.getAttribute('data-reps'); const sets = this.getAttribute('data-sets'); const date = this.getAttribute('data-date');

  // モーダルのタイトルにエクササイズ名を表示
  document.getElementById('exercise_name_display').textContent = exerciseName;

  // フォームに値を設定
  document.getElementById('exercise_id').value = scheduleId;
  document.getElementById('schedule_date').value = date; // 日付
  document.getElementById('reps').value = reps; // 回数
  document.getElementById('sets').value = sets; // セット数
});

});

// 初期化関数 function initializeModal() { scheduleModalEl.addEventListener("hidden.bs.modal", cleanupModal); }

// モーダルを開いてスケジュールを表示する関数 function openScheduleModal(date, calendarId) { fetch(/calendars/${calendarId}/schedules?date=${date}) .then((response) => { if (!response.ok) throw new Error("Failed to load schedule details."); return response.text(); }) .then((html) => { document.getElementById("schedule-details").innerHTML = html; scheduleModal.show(); registerAddButtonListener(); }) .catch((error) => console.error("Error loading schedule details:", error)); }

// 追加ボタンのイベントを登録 function registerAddButtonListener() { const addScheduleBtn = document.getElementById("add-schedule-btn"); if (addScheduleBtn) { addScheduleBtn.addEventListener("click", () => { scheduleModal.hide(); window.location.href = "/exercises"; }); } }

// カレンダーの日付クリック処理 function registerCalendarClickListeners() { document.querySelectorAll(".calendar-date").forEach((element) => { element.addEventListener("click", (event) => { event.preventDefault(); const date = event.currentTarget.dataset.date; const calendarId = event.currentTarget.dataset.calendarId; openScheduleModal(date, calendarId); }); }); }

// フォームの送信処理 function handleFormSubmit(event) { event.preventDefault(); const formData = new FormData(scheduleForm);

fetch(scheduleForm.action, {
  method: scheduleForm.method,
  body: formData,
  headers: { 'X-Requested-With': 'XMLHttpRequest' }
})
.then((response) => {
  if (!response.ok) throw new Error("Failed to save schedule.");
  return response.json();
})
.then((data) => {
  console.log("Schedule saved successfully:", data);
  scheduleModal.hide();
  // カレンダー更新処理をここに追加
})
.catch((error) => console.error("Error saving schedule:", error));

}

// モーダル閉じるときの後処理 function cleanupModal() { if (scheduleForm) { scheduleForm.reset(); // フォームのリセット } else { console.warn("Schedule form not found."); }

document.getElementById("exercise_name_display").textContent = "";
const exerciseIdField = document.querySelector("#schedule-form input[name='schedule[exercise_id]']");
if (exerciseIdField) exerciseIdField.value = "";

// モーダルの背景削除
document.body.classList.remove("modal-open");
const backdrop = document.querySelector(".modal-backdrop");
if (backdrop) backdrop.remove();

}

// イベント登録 function registerEventListeners() { registerCalendarClickListeners(); if (scheduleForm) { scheduleForm.addEventListener("submit", handleFormSubmit); } }

// 初期化とイベント登録の実行 initializeModal(); registerEventListeners(); });


- 試したこと
モーダルを初期化してみようと

const scheduleModalEl = document.getElementById("scheduleModal"); console.log("scheduleModalEl:", scheduleModalEl); // デバッグ: モーダル取得確認 const editModalEl = document.getElementById("editModal");

if (scheduleModalEl) { const scheduleModal = new bootstrap.Modal(scheduleModalEl); console.log("Schedule modal initialized:", scheduleModal); // モーダルの初期化確認 } else { console.error("Schedule modal element not found."); }

const scheduleModal = new bootstrap.Modal(scheduleModalEl); const editModal = new bootstrap.Modal(editModalEl); const scheduleForm = document.getElementById("schedule-form"); console.log("scheduleForm:", scheduleForm); // フォーム取得確認


このようにコードを追加したら、app/views/schedules/_schedule_details.html.erbが表示されず、動作確認ができなくなってしまった。
kodamarisa commented 1 week ago

app/javascript/packs/schedule.js

document.addEventListener("DOMContentLoaded", () => {
  const scheduleModalEl = document.getElementById("scheduleModal");
  const editModalEl = document.getElementById("editModal");
  const scheduleForm = document.getElementById("schedule-form");

  // モーダルのインスタンスを作成
  const scheduleModal = scheduleModalEl ? new bootstrap.Modal(scheduleModalEl) : null;
  const editModal = editModalEl ? new bootstrap.Modal(editModalEl) : null;

  // モーダルを開いてスケジュールを表示する関数
  function openScheduleModal(date, calendarId) {
    fetch(`/calendars/${calendarId}/schedules?date=${date}`, {
      headers: { "X-Requested-With": "XMLHttpRequest" },
    })
      .then((response) => {
        if (!response.ok) throw new Error("スケジュールの取得に失敗しました。");
        return response.text();
      })
      .then((html) => {
        document.getElementById("schedule-details").innerHTML = html;
        scheduleModal.show();  // スケジュールモーダルを表示
        registerEditButtonListeners();  // 編集ボタンのリスナーを登録
      })
      .catch((error) => {
        console.error(error);
        alert("スケジュールの読み込みに失敗しました。");
      });
  }

  // 編集ボタンのリスナーを登録する関数
  function registerEditButtonListeners() {
    document.querySelectorAll(".edit-schedule-btn").forEach((button) => {
      button.addEventListener("click", () => {
        const scheduleId = button.dataset.scheduleId;
        const exerciseName = button.dataset.exerciseName;
        const reps = button.dataset.reps;
        const sets = button.dataset.sets;
        const date = button.dataset.date;

        // モーダルのタイトルにエクササイズ名を表示
        document.getElementById("exercise_name_display").textContent = exerciseName;

        // フォームに値を設定
        document.getElementById("exercise_id").value = scheduleId;
        document.getElementById("schedule_date").value = date;
        document.getElementById("reps").value = reps;
        document.getElementById("sets").value = sets;

        scheduleModal.hide();  // スケジュールモーダルを隠す
        editModal.show();  // 編集モーダルを表示
      });
    });
  }

  // カレンダーの日付クリック処理
  document.querySelectorAll(".calendar-date").forEach((element) => {
    element.addEventListener("click", (event) => {
      event.preventDefault();
      const date = element.dataset.date;
      const calendarId = element.dataset.calendarId;
      openScheduleModal(date, calendarId);  // モーダルを開く
    });
  });

  // フォームの送信処理
  if (scheduleForm) {
    scheduleForm.addEventListener("submit", (event) => {
      event.preventDefault();
      const formData = new FormData(scheduleForm);

      fetch(scheduleForm.action, {
        method: scheduleForm.method,
        body: formData,
        headers: { 'X-Requested-With': 'XMLHttpRequest' }
      })
        .then((response) => {
          if (!response.ok) throw new Error("保存に失敗しました。");
          return response.json();
        })
        .then(() => {
          editModal.hide();  // 編集モーダルを隠す
          alert("スケジュールが保存されました。");
          // カレンダー更新処理をここに追加
        })
        .catch((error) => console.error(error));
    });
  }
});

こうしたところ、編集ボタンでの切り替えができるようになりましたが、追加ボタンでの筋トレ一覧へのリダレクトができなくなってしまいました。 もう少し、前のコードと見比べながら、修正できそうか試してみます。

kodamarisa commented 1 week ago

app/javascript/packs/schedule.js

document.addEventListener("DOMContentLoaded", () => {
  const scheduleModalEl = document.getElementById("scheduleModal");
  const editModalEl = document.getElementById("editModal");
  const scheduleForm = document.getElementById("schedule-form");

  // モーダルのインスタンスを作成
  const scheduleModal = scheduleModalEl ? new bootstrap.Modal(scheduleModalEl) : null;
  const editModal = editModalEl ? new bootstrap.Modal(editModalEl) : null;

  // モーダルを開いてスケジュールを表示する関数
  function openScheduleModal(date, calendarId) {
    fetch(`/calendars/${calendarId}/schedules?date=${date}`, {
      headers: { "X-Requested-With": "XMLHttpRequest" },
    })
      .then((response) => {
        if (!response.ok) throw new Error("スケジュールの取得に失敗しました。");
        return response.text();
      })
      .then((html) => {
        document.getElementById("schedule-details").innerHTML = html;
        scheduleModal.show();  // スケジュールモーダルを表示
        registerEditButtonListeners();  // 編集ボタンのリスナーを登録
        registerAddButtonListener();  // 追加ボタンのリスナーを登録
      })
      .catch((error) => {
        console.error(error);
        alert("スケジュールの読み込みに失敗しました。");
      });
  }

  // 編集ボタンのリスナーを登録する関数
  function registerEditButtonListeners() {
    document.querySelectorAll(".edit-schedule-btn").forEach((button) => {
      button.addEventListener("click", () => {
        const scheduleId = button.dataset.scheduleId;
        const exerciseName = button.dataset.exerciseName;
        const reps = button.dataset.reps;
        const sets = button.dataset.sets;
        const date = button.dataset.date;

        // モーダルのタイトルにエクササイズ名を表示
        document.getElementById("exercise_name_display").textContent = exerciseName;

        // フォームに値を設定
        document.getElementById("exercise_id").value = scheduleId;
        document.getElementById("schedule_date").value = date;
        document.getElementById("reps").value = reps;
        document.getElementById("sets").value = sets;

        scheduleModal.hide();  // スケジュールモーダルを隠す
        editModal.show();  // 編集モーダルを表示
      });
    });
  }

  // 追加ボタンのリスナーを登録する関数
  function registerAddButtonListener() {
    const addScheduleBtn = document.getElementById("add-schedule-btn");
    if (addScheduleBtn) {
      addScheduleBtn.addEventListener("click", () => {
        scheduleModal.hide(); // モーダルを閉じる
        window.location.href = "/exercises"; // 筋トレ一覧にリダイレクト
      });
    }
  }

  // モーダル閉じるときの後処理
  function cleanupModal() {
    document.getElementById("exercise_name_display").textContent = "";
    const exerciseIdField = document.querySelector("#schedule-form input[name='schedule[exercise_id]']");
    if (exerciseIdField) exerciseIdField.value = "";

    // モーダルの背景削除
    document.body.classList.remove("modal-open");
    const backdrop = document.querySelector(".modal-backdrop");
    if (backdrop) backdrop.remove();
  }

  // カレンダーの日付クリック処理
  document.querySelectorAll(".calendar-date").forEach((element) => {
    element.addEventListener("click", (event) => {
      event.preventDefault();
      const date = element.dataset.date;
      const calendarId = element.dataset.calendarId;
      openScheduleModal(date, calendarId);  // モーダルを開く
    });
  });

  // フォームの送信処理
  if (scheduleForm) {
    scheduleForm.addEventListener("submit", (event) => {
      event.preventDefault();
      const formData = new FormData(scheduleForm);

      fetch(scheduleForm.action, {
        method: scheduleForm.method,
        body: formData,
        headers: { 'X-Requested-With': 'XMLHttpRequest' }
      })
        .then((response) => {
          if (!response.ok) throw new Error("保存に失敗しました。");
          return response.json();
        })
        .then(() => {
          editModal.hide();  // 編集モーダルを隠す
          alert("スケジュールが保存されました。");
          // カレンダー更新処理をここに追加
        })
        .catch((error) => console.error(error));
    });
  }

  // モーダルが閉じられたときにクリーンアップ処理を呼び出す
  scheduleModalEl.addEventListener('hidden.bs.modal', cleanupModal);
});

こうしたら、問題なく、筋トレ一覧へのリダレクトも行えるようになりました。 しかし、動作を確認したところ、編集した内容がうまく保存できず、 https://gyazo.com/3d35ade34e95d9a21b9af8734c385ca9 このようなエラーが出現しています。 現在、原因の絞り込みをしています。

kodamarisa commented 4 days ago

現在、 編集で日付を変更し、保存しようとしたら"exercise_id"が空白であるため、エラーが発生し、保存ができない。 "exercise_id"に編集ボタンを押された筋トレのidを入れれるようにし、日付や回数を変更してもカレンダーに反映されるようにしたい。

Started PUT "/calendars/56/schedules/20" for ::1 at 2024-10-28 12:42:52 +0900
Processing by SchedulesController#update as */*
  Parameters: {"authenticity_token"=>"[FILTERED]", "schedule"=>{"exercise_id"=>"", "date"=>"2024-10-28", "repetitions"=>"4", "sets"=>"2"}, "calendar_id"=>"56", "id"=>"20"}
  Calendar Load (1.0ms)  SELECT "calendars".* FROM "calendars" WHERE "calendars"."id" = $1 LIMIT $2  [["id", 56], ["LIMIT", 1]]
  ↳ app/controllers/application_controller.rb:39:in `set_current_calendar'
  CACHE Calendar Load (0.0ms)  SELECT "calendars".* FROM "calendars" WHERE "calendars"."id" = $1 LIMIT $2  [["id", 56], ["LIMIT", 1]]
  ↳ app/controllers/schedules_controller.rb:92:in `set_calendar'
Set Calendar: #<Calendar id: 56, title: "あ", image: nil, calendar_color: nil, calendar_type: nil, user_type: "User", user_id: 4, created_at: "2024-09-30 08:55:52.401595000 +0000", updated_at: "2024-09-30 09:32:30.371458000 +0000">
  Schedule Load (1.5ms)  SELECT "schedules".* FROM "schedules" WHERE "schedules"."calendar_id" = $1 AND "schedules"."id" = $2 LIMIT $3  [["calendar_id", 56], ["id", 20], ["LIMIT", 1]]
  ↳ app/controllers/schedules_controller.rb:97:in `set_schedule'
Set Schedule: #<Schedule id: 20, calendar_id: 56, exercise_id: 1, date: "2024-10-28", repetitions: 1, duration: nil, created_at: "2024-10-18 07:16:08.417868000 +0000", updated_at: "2024-10-18 07:16:08.417868000 +0000", distance: nil, sets: 1>
UPDATE: Schedule ID: 20, Params: #<ActionController::Parameters {"_method"=>"put", "authenticity_token"=>"yBVLEyh0jwspLdg7Fq7DdD09fym_zcoivPNQ5tcxERHkRA2kbJSw9N6RjxRS_5lDs3rHDgIrymI_n3idkh1YcQ", "schedule"=>{"exercise_id"=>"", "date"=>"2024-10-28", "repetitions"=>"4", "sets"=>"2"}, "controller"=>"schedules", "action"=>"update", "calendar_id"=>"56", "id"=>"20"} permitted: false>
Exercise ID is missing.
  Rendering layout layouts/application.html.erb
  Rendering schedules/edit.html.erb within layouts/application
  Rendered schedules/edit.html.erb within layouts/application (Duration: 14.7ms | Allocations: 5480)
  Rendered layout layouts/application.html.erb (Duration: 15.0ms | Allocations: 5556)
Completed 500 Internal Server Error in 31ms (ActiveRecord: 2.5ms | Allocations: 8466)

ActionView::Template::Error (undefined method `schedule_path' for #<ActionView::Base:0x0000000000e240>

              recipient.public_send(method, *args, options)
                       ^^^^^^^^^^^^):
    1: <%= form_with(model: @schedule, local: true) do |form| %>
    2:   <div class="field">
    3:     <%= form.label :date %>
    4:     <%= form.date_field :date, value: @schedule.date %>

app/views/schedules/edit.html.erb:1
app/controllers/schedules_controller.rb:56:in `block (2 levels) in update'
app/controllers/schedules_controller.rb:55:in `update'

"exercise_id"が空白であるため、編集ボタンを押された筋トレのidを入れれるようにしたい。

<% if schedules.any? %> <% schedules.each do |schedule| %>

<%= schedule.exercise.name %> <%= schedule.repetitions %> 回 × <%= schedule.sets %> セット

<% end %> <% else %>

この日にスケジュールはありません。

<% end %>

<% if schedules.count < 3 %>

<% else %>

これ以上スケジュールを追加できません。

<% end %>

app/views/schedules/_edit_modal.html.erb
app/controllers/schedules_controller.rb

class SchedulesController < ApplicationController before_action :set_calendar before_action :set_schedule, only: [:show, :edit, :update, :destroy]

def new logger.debug "NEW: Calendar ID: #{params[:calendar_id]}, Exercise ID: #{params[:exercise_id]}, Date: #{params[:date]}"

@calendar = Calendar.find(params[:calendar_id])
@exercise = Exercise.find(params[:exercise_id])
@schedule = @calendar.schedules.build(exercise: @exercise)

@exercises = Exercise.all
@selected_exercise = @exercise
@selected_date = params[:date] ? Date.parse(params[:date]) : Date.today

end

def create logger.debug "CREATE: Params: #{params.inspect}"

@schedule = @calendar.schedules.build(schedule_params)
if @schedule.save
  logger.info "Schedule successfully created: #{@schedule.inspect}"
  render json: { status: 'success', schedule: @schedule }, status: :created
else
  logger.error "Failed to create schedule: #{@schedule.errors.full_messages}"
  render json: { status: 'error', errors: @schedule.errors.full_messages }, status: :unprocessable_entity
end

end

def index logger.debug "INDEX: Calendar ID: #{params[:calendar_id]}, Date: #{params[:date]}"

@calendar = Calendar.find(params[:calendar_id])
@schedules = @calendar.schedules.where(date: params[:date])
@exercises = Exercise.all

if params[:exercise_id]
  @exercise = Exercise.find(params[:exercise_id])
  logger.debug "Selected Exercise: #{@exercise.name}"
end

respond_to do |format|
  format.html { render partial: 'schedules/schedule_details', locals: { schedules: @schedules, date: params[:date] } }
  format.js
end

end

def update logger.debug "UPDATE: Schedule ID: #{@schedule.id}, Params: #{params.inspect}"

# exercise_idが空でないことを確認
if params[:schedule][:exercise_id].blank?
  logger.error "Exercise ID is missing."
  @exercises = Exercise.all  # エクササイズのリストを再取得
  respond_to do |format|
    format.html { render :edit, alert: 'エクササイズを選択してください。' }
    format.js { render json: { status: 'error', errors: ['エクササイズを選択してください。'] }, status: :unprocessable_entity }
  end
  return  # ここで処理を終了
end

# スケジュールを更新
if @schedule.update(schedule_params)
  logger.info "Schedule updated: #{@schedule.inspect}"
  respond_to do |format|
    format.html { redirect_to calendar_path(@calendar), notice: 'スケジュールが正常に更新されました。' }
    format.js
  end
else
  logger.error "Failed to update schedule: #{@schedule.errors.full_messages}"
  @exercises = Exercise.all
  respond_to do |format|
    format.html { render :edit }
    format.js { render json: { status: 'error', errors: @schedule.errors.full_messages }, status: :unprocessable_entity }
  end
end

end

def destroy logger.info "DESTROY: Schedule ID: #{@schedule.id}"

@schedule.destroy
respond_to do |format|
  format.html { redirect_to calendar_path(@calendar), notice: 'スケジュールが正常に削除されました。' }
  format.js
end

end

private

def set_calendar @calendar = Calendar.find(params[:calendar_id]) logger.debug "Set Calendar: #{@calendar.inspect}" end

def set_schedule @schedule = @calendar.schedules.find(params[:id]) logger.debug "Set Schedule: #{@schedule.inspect}" end

def schedule_params params.require(:schedule).permit(:exercise_id, :repetitions, :sets, :date) end end

app/models/schedule.rb

class Schedule < ApplicationRecord belongs_to :calendar belongs_to :exercise validates :date, presence: true

def start_time self.date end end

app/models/exercise.rb

class Exercise < ApplicationRecord has_many :schedules, dependent: :destroy

def self.ransackable_attributes(auth_object = nil) ["created_at", "description", "difficulty", "duration", "id", "name", "updated_at", "target_muscles"] end

def self.ransackable_associations(auth_object = nil) [] # 今回はアソシエーションでの検索は許可しない end end

config/routes.rb

Rails.application.routes.draw do get 'static_pages/privacy_policy' get 'static_pages/terms_of_service' root 'calendars#new'

Devise routes

devise_for :users, controllers: { sessions: 'users/sessions', registrations: 'users/registrations', passwords: 'users/passwords', confirmations: 'users/confirmations', unlocks: 'users/unlocks', }

Custom session routes

devise_scope :user do get '/login', to: 'users/sessions#new', as: :new_line_user_session post '/login', to: 'users/sessions#create' get '/logout', to: 'users/sessions#destroy', as: :destroy_line_user_session get '/line_login', to: 'sessions#line_login', as: :login_with_line end

get '/auth/:provider/callback', to: 'sessions#create' get '/auth/failure', to: redirect('/')

User profile route

authenticated :user do get '/choose_registration', to: 'users/registrations#choose', as: :choose_registration get '/profile', to: 'users#profile', as: :user_profile end

Calendar routes

resources :calendars, except: [:destroy, :update] do resources :schedules, only: [:index, :show, :new, :create, :edit, :update, :destroy] end

Exercise routes

resources :exercises, only: [:index, :show] do collection do get :autocomplete end resources :bookmarks, only: [:create, :destroy], shallow: false end

Registration routes

resources :registrations, only: [:new] get '/line_registration', to: 'line_users#line_registration', as: :line_registration get '/email_registration', to: 'registrations#email_registration', as: :email_registration

LineUsers routes

resources :line_users, only: [:show, :new, :create]

Customize routes

resources :customizes, only: [:new, :edit, :create, :update]

Bookmarks route

resources :bookmarks, only: [:index]

Static pages routes

scope controller: :static_pages do get :privacy_policy get :terms_of_service end

For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html

end


- 試したこと
デバックログで"exercise_id"が渡せていないことまではわかりましたが、どうやったら、編集ボタンでモーダルを開かれた筋トレのidが渡せるのかがわかりません。
何かアイディアや助言等あればお願いいたします。
kenchasonakai commented 3 days ago

hidden_fieldに何もvalueを設定していなのでnilになるとかですかね? <%= form.hidden_field :exercise_id, id: 'schedule_exercise_id' %>

<div class="modal fade" id="editModal" tabindex="-1" aria-labelledby="editModalLabel" aria-hidden="true">
  <div class="modal-dialog modal-dialog-centered">
    <div class="modal-content">
      <div class="modal-header">
        <h1 class="modal-title fs-5" id="editModalLabel">
          Edit Schedule: <span id="exercise_name_display"></span>
        </h1>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
      </div>

      <div class="modal-body">
        <%= form_with model: [@calendar, @schedule], local: true, method: :put, id: "schedule-form" do |form| %>
            <%= form.hidden_field :exercise_id, id: 'schedule_exercise_id' %>
          <div class="mb-3">
            <label for="schedule_date" class="form-label">Schedule Date</label>
            <%= form.date_field :date, class: "form-control", id: "schedule_date", required: true %>
          </div>

          <div class="mb-3">
            <label for="reps" class="form-label">Reps/Distance</label>
            <%= form.number_field :repetitions, class: "form-control", id: "reps", min: 1, required: true %>
          </div>

          <div class="mb-3">
            <label for="sets" class="form-label">Sets</label>
            <%= form.number_field :sets, class: "form-control", id: "sets", min: 1, required: true %>
          </div>

          <div class="modal-footer">
            <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
            <%= form.submit "Save changes", class: "btn btn-primary" %>
          </div>
        <% end %>
      </div>
    </div>
  </div>
</div>
kodamarisa commented 3 days ago

valueの設定を確認するため、app/javascript/packs/schedule.jsに

console.log("Opening edit modal with data:", {
          scheduleId,
          calendarId,
          exerciseId,
          exerciseName,
          reps,
          sets,
          date
        });

このログを追加しました。この状態で、 https://gyazo.com/a868035e0db2d7b3a33a3b1f1eb5206d この一番上のスクワットの編集ボタンを押すと https://gyazo.com/97a6a922f3490a2e0e8c88d3441fdd21 このログが出たため、セット数を2から5に変更し、Saveボタンを押したところ、 https://gyazo.com/11935e1047e5b4969a14978326e42bfd こうなっています。 この、編集ボタンを押し、編集モーダルに切り替わる際一瞬だけ、Edit Schedule:の横にスクワットの文字が表示されましたが、すぐに消えてしまい、Edit Schedule:の横が空白になってしまっています。ターミナルの方のエラーは持続してみられます。

Started PUT "/calendars/56/schedules/19" for ::1 at 2024-10-28 16:06:07 +0900
Processing by SchedulesController#update as */*
  Parameters: {"authenticity_token"=>"[FILTERED]", "schedule"=>{"exercise_id"=>"", "date"=>"2024-10-28", "repetitions"=>"3", "sets"=>"5"}, "calendar_id"=>"56", "id"=>"19"}
  Calendar Load (0.8ms)  SELECT "calendars".* FROM "calendars" WHERE "calendars"."id" = $1 LIMIT $2  [["id", 56], ["LIMIT", 1]]
  ↳ app/controllers/application_controller.rb:39:in `set_current_calendar'
  CACHE Calendar Load (0.0ms)  SELECT "calendars".* FROM "calendars" WHERE "calendars"."id" = $1 LIMIT $2  [["id", 56], ["LIMIT", 1]]
  ↳ app/controllers/schedules_controller.rb:92:in `set_calendar'
Set Calendar: #<Calendar id: 56, title: "あ", image: nil, calendar_color: nil, calendar_type: nil, user_type: "User", user_id: 4, created_at: "2024-09-30 08:55:52.401595000 +0000", updated_at: "2024-09-30 09:32:30.371458000 +0000">
  Schedule Load (1.0ms)  SELECT "schedules".* FROM "schedules" WHERE "schedules"."calendar_id" = $1 AND "schedules"."id" = $2 LIMIT $3  [["calendar_id", 56], ["id", 19], ["LIMIT", 1]]
  ↳ app/controllers/schedules_controller.rb:97:in `set_schedule'
Set Schedule: #<Schedule id: 19, calendar_id: 56, exercise_id: 2, date: "2024-10-28", repetitions: 3, duration: nil, created_at: "2024-10-18 07:15:31.853129000 +0000", updated_at: "2024-10-18 07:15:31.853129000 +0000", distance: nil, sets: 2>
UPDATE: Schedule ID: 19, Params: #<ActionController::Parameters {"_method"=>"put", "authenticity_token"=>"7jPhbgzmwxw8-KYzQd6DdgOrUey2yCzQXJSnYotYBJHCYqfZSAb848tE8RwFj9lBjezpywsuLJDf-I8ZznRN8Q", "schedule"=>{"exercise_id"=>"", "date"=>"2024-10-28", "repetitions"=>"3", "sets"=>"5"}, "controller"=>"schedules", "action"=>"update", "calendar_id"=>"56", "id"=>"19"} permitted: false>
Exercise ID is missing.
  Rendering layout layouts/application.html.erb
  Rendering schedules/edit.html.erb within layouts/application
  Rendered schedules/edit.html.erb within layouts/application (Duration: 16.3ms | Allocations: 5216)
  Rendered layout layouts/application.html.erb (Duration: 16.5ms | Allocations: 5292)
Completed 500 Internal Server Error in 27ms (ActiveRecord: 1.8ms | Allocations: 8079)

ActionView::Template::Error (undefined method `schedule_path' for #<ActionView::Base:0x0000000000ffc8>

              recipient.public_send(method, *args, options)
                       ^^^^^^^^^^^^):
    1: <%= form_with(model: @schedule, local: true) do |form| %>
    2:   <div class="field">
    3:     <%= form.label :date %>
    4:     <%= form.date_field :date, value: @schedule.date %>

app/views/schedules/edit.html.erb:1
app/controllers/schedules_controller.rb:56:in `block (2 levels) in update'
app/controllers/schedules_controller.rb:55:in `update'

モーダルの初期化が影響してそうだと思ったのですが、そこからどうしたらいいのかわからない状態です。

kenchasonakai commented 3 days ago

valueの設定を確認するため、app/javascript/packs/schedule.jsに

valueはJS側でセットするのではなくerb上で<%= form.hidden_field :exercise_id, id: 'schedule_exercise_id', value: '入れたいexercise_id' %>のようにセット出来るので調べてみてください

@calendar@scheduleにexercise_idを持たせているなら <%= form.hidden_field :exercise_id, id: 'schedule_exercise_id', value: @schedule.exercise_id %>でセット出来ます

kodamarisa commented 3 days ago

app/views/schedules/_edit_modal.html.erbを

<div class="modal fade" id="editModal" tabindex="-1" aria-labelledby="editModalLabel" aria-hidden="true">
  <div class="modal-dialog modal-dialog-centered">
    <div class="modal-content">
      <div class="modal-header">
        <h1 class="modal-title fs-5" id="editModalLabel">
          Edit Schedule: <span id="exercise_name_display"></span>
        </h1>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
      </div>

      <div class="modal-body">
        <%= form_with model: [@calendar, @schedule], local: true, method: :put, id: "schedule-form" do |form| %>
            **<%= form.hidden_field :exercise_id, id: 'schedule_exercise_id', value: @schedule.exercise_id %>**
          <div class="mb-3">
            <label for="schedule_date" class="form-label">Schedule Date</label>
            <%= form.date_field :date, class: "form-control", id: "schedule_date", required: true %>
          </div>

          <div class="mb-3">
            <label for="reps" class="form-label">Reps/Distance</label>
            <%= form.number_field :repetitions, class: "form-control", id: "reps", min: 1, required: true %>
          </div>

          <div class="mb-3">
            <label for="sets" class="form-label">Sets</label>
            <%= form.number_field :sets, class: "form-control", id: "sets", min: 1, required: true %>
          </div>

          <div class="modal-footer">
            <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
            <%= form.submit "Save changes", class: "btn btn-primary" %>
          </div>
        <% end %>
      </div>
    </div>
  </div>
</div>

このようにしましたが、変化ありませんでした。 他に何かないかとChatGPTに質問を投げてみたところ

function cleanupModal() {
    document.getElementById("exercise_name_display").textContent = "";
    const exerciseIdField = document.querySelector("#schedule-form input[name='schedule[exercise_id]']");
    **if (exerciseIdField) exerciseIdField.value = "";**

    document.body.classList.remove("modal-open");
    const backdrop = document.querySelector(".modal-backdrop");
    if (backdrop) backdrop.remove();
  }

ここをコメントアウトもしくは削除したらどうかと出たため、試したところ、 https://gyazo.com/83b00bfcc6ca6eec337a783465aa1524 この状態でとまり、再読み込みをしたところ https://gyazo.com/7f09f25f65a1f998fa5ec14e744c3d72 このように、回数が編集できました。 どうやら、モーダルを開く際にリセットするようになっていたみたいです。