Open taiti101112 opened 1 month ago
ControllerからFormObjectを呼び出している部分がカットされてしまっているのですべて記載してもらえると助かります
また、binding.pry等を使ってどこまでご自身が意図しているデータがわたっているのか確認してみるとよいかなと思います
ご返信ありがとうございます。 スクリーンショットで全体が表示されているものを上げ直しましたのでご確認のほどよろしくお願いいたします。
binding.pryでデータがどこで自分の意図したものではないものになっているのかを確認してみようと思いますのでまた分からないことが出てきたらよろしくお願いいたします。
お疲れ様です。 先日教えていただいたようにデバックを行いどのようなデータが渡っているのかの確認を行いました。 その結果、自分の意図したデータが送られていましたがそれでも尚、「Unpermitted parameters」が出てしまい、データを正しく保存することができません。 原因としてはストロングパラメーターで各曜日それぞれの営業時間を指定していないからではないかと考え、以下のようにストロングパラメーターにそれぞれの曜日の営業時間を指定したものを追加したしましたが解決には至りませんでした。
また、チャットGPTにもエラー解決のための質問をした結果、上記に記載したようなことが原因ということで何度も修正を行いましたが解決することができませんでした。
これ以上は原因が考えつきませんので他に何か原因があれば教えていただけますでしょうか? 以下に該当書のコードとログとデバック結果を記載しましたのでご確認のほどよろしくお願い致します。
# app/controllers/admin/shops_controller.rb
module Admin
class ShopsController < ApplicationController
before_action :authenticate_admin!
before_action :set_shop, only: [:show, :edit, :update, :destroy, :edit_hours, :update_hours]
before_action :set_is_admin
def index
@q = Shop.ransack(params[:q])
if params[:q].present?
@shops = @q.result(distinct: true)
else
@shops = Shop.all
end
if params[:tag_name]
@shops = @shops.tagged_with(params[:tag_name])
end
end
def show
@tags = @shop.tag_counts_on(:tags)
end
def new
@shop_business_hour_form = ShopBusinessHourForm.new
@form_url = admin_shops_path
@form_method = :post
end
def edit
shop_params = @shop.attributes.symbolize_keys.slice(*ShopBusinessHourForm::ATTRIBUTES)
shop_params[:tag_list] = @shop.tag_list.join(",") if @shop.tag_list.present?
@shop_business_hour_form = ShopBusinessHourForm.new(shop_params, @shop)
@form_url = admin_shop_path(@shop)
@form_method = :patch
end
def create
@shop_business_hour_form = ShopBusinessHourForm.new(shop_business_hour_form_params)
@shop_business_hour_form.user_id = current_user.id # 現在のユーザーのIDを設定
@form_url = admin_shops_path
@form_method = :post
binding.pry
if @shop_business_hour_form.save
redirect_to [:admin, Shop.find_by(name: @shop_business_hour_form.shop_name)], notice: 'Shop and business hours were successfully created.'
else
Rails.logger.error(@shop_business_hour_form.errors.full_messages)
render :new
end
end
def update
@shop_business_hour_form = ShopBusinessHourForm.new(shop_business_hour_form_params, @shop)
@form_url = admin_shop_path(@shop)
@form_method = :patch
if @shop_business_hour_form.update(@shop)
redirect_to [:admin, @shop], notice: 'ショップの更新が完了しました'
else
render :edit
end
end
def destroy
@shop.destroy
redirect_to admin_shops_url, notice: 'ショップの削除が完了しました'
end
private
def set_shop
@shop = Shop.find(params[:id])
end
def shop_business_hour_form_params
params.require(:shop_business_hour_form).permit(
:shop_name, :address, :phone_number, :duel_space_available, :opening_hours, :official_hp, :twitter, :instagram, :tag_list,
business_hours_attributes: [
:day_of_week,
:_destroy,
'opening_time(1i)', 'opening_time(2i)', 'opening_time(3i)', 'opening_time(4i)', 'opening_time(5i)',
'closing_time(1i)', 'closing_time(2i)', 'closing_time(3i)', 'closing_time(4i)', 'closing_time(5i)'
]
).merge(user_id: current_user.id)
end
def set_is_admin
@is_admin = current_user&.admin?
end
end
end
# app/forms/shop_business_hour_form.rb
class ShopBusinessHourForm
include ActiveModel::Model
ATTRIBUTES = [:shop_name, :address, :phone_number, :duel_space_available, :opening_hours, :official_hp, :twitter, :instagram, :tag_list, :business_hours_attributes, :user_id]
attr_accessor(*ATTRIBUTES)
validate :validate_business_hours
def initialize(params = nil, shop = nil)
if shop
@shop = shop
self.shop_name = shop.name
self.address = shop.address
self.phone_number = shop.phone_number
self.duel_space_available = shop.duel_space_available
self.opening_hours = shop.opening_hours
self.official_hp = shop.official_hp
self.twitter = shop.twitter
self.instagram = shop.instagram
self.tag_list = shop.tag_list.join(",") if shop.tag_list.present?
self.business_hours_attributes = shop.business_hours.map { |bh| bh.attributes.symbolize_keys.slice(:day_of_week, :opening_time, :closing_time) }
else
@shop = Shop.new
self.business_hours_attributes = (0..6).map { |day| { day_of_week: day, opening_time: '09:00', closing_time: '18:00' } }
end
if params
filtered_params = params.slice(*ATTRIBUTES)
Rails.logger.info(filtered_params.inspect) # パラメータの内容を確認
super(filtered_params)
else
super()
end
end
def save
return false unless valid?
# business_hours_attributesの内容を確認
Rails.logger.info(business_hours_attributes.inspect)
shop = Shop.new(
name: shop_name,
address: address,
phone_number: phone_number,
duel_space_available: duel_space_available,
opening_hours: opening_hours,
official_hp: official_hp,
twitter: twitter,
instagram: instagram,
tag_list: tag_list,
user_id: user_id # ユーザーIDを設定
)
if shop.save
business_hours_attributes.each do |bh_attr|
Rails.logger.info(bh_attr.inspect) # データの内容をログに出力
shop.business_hours.create(bh_attr)
end
true
else
errors.merge!(shop.errors)
false
end
end
def update(shop)
return false unless valid?
shop.assign_attributes(
name: shop_name,
address: address,
phone_number: phone_number,
duel_space_available: duel_space_available,
opening_hours: opening_hours,
official_hp: official_hp,
twitter: twitter,
instagram: instagram,
tag_list: tag_list
)
if shop.save
shop.business_hours.destroy_all
business_hours_attributes.each do |bh_attr|
shop.business_hours.create(bh_attr)
end
true
else
errors.merge!(shop.errors)
false
end
end
def business_hours
business_hours_attributes
end
private
def validate_business_hours
business_hours_attributes.each do |bh|
errors.add(:base, "Business hours Opening time can't be blank") if bh[:opening_time].blank?
errors.add(:base, "Business hours Closing time can't be blank") if bh[:closing_time].blank?
end
end
end
<!-- app/views/admin/shops/_form.html.erb -->
<%= form_with(model: @shop_business_hour_form, url: @form_url, local: true, method: @form_method) do |form| %>
<% if @shop_business_hour_form.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@shop_business_hour_form.errors.count, "error") %> prohibited this shop from being saved:</h2>
<ul>
<% @shop_business_hour_form.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= form.label :shop_name %>
<%= form.text_field :shop_name, value: @shop_business_hour_form.shop_name %>
</div>
<div class="field">
<%= form.label :address %>
<%= form.text_field :address, value: @shop_business_hour_form.address %>
</div>
<div class="field">
<%= form.label :phone_number %>
<%= form.number_field :phone_number, value: @shop_business_hour_form.phone_number %>
</div>
<div class="field">
<%= form.label :duel_space_available %>
<%= form.number_field :duel_space_available, value: @shop_business_hour_form.duel_space_available %>
</div>
<div class="field">
<%= form.label :opening_hours %>
<%= form.text_field :opening_hours, value: @shop_business_hour_form.opening_hours %>
</div>
<div class="field">
<%= form.label :official_hp %>
<%= form.text_field :official_hp, value: @shop_business_hour_form.official_hp %>
</div>
<div class="field">
<%= form.label :twitter %>
<%= form.text_field :twitter, value: @shop_business_hour_form.twitter %>
</div>
<div class="field">
<%= form.label :instagram %>
<%= form.text_field :instagram, value: @shop_business_hour_form.instagram %>
</div>
<div class="field">
<%= form.label :tag_list, "タグ" %>
<%= form.text_field :tag_list, value: @shop_business_hour_form.tag_list || "", class: "form-control", data: { role: "tagsinput" } %>
</div>
<h3>Business Hours</h3>
<% @shop_business_hour_form.business_hours.each_with_index do |bh, index| %>
<div class="field">
<%= form.label "business_hours_attributes_#{index}_day_of_week", "Day of the Week" %>
<%= form.select "business_hours_attributes_#{index}_day_of_week", Date::DAYNAMES.each_with_index.map { |name, index| [name, index] }, selected: bh[:day_of_week] %>
</div>
<div class="field">
<%= form.label "business_hours_attributes_#{index}_opening_time", "Opening Time" %>
<%= form.time_select "business_hours_attributes_#{index}_opening_time", default: bh[:opening_time].to_time.change(year: 2000, month: 1, day: 1) || Time.zone.parse('09:00') %>
</div>
<div class="field">
<%= form.label "business_hours_attributes_#{index}_closing_time", "Closing Time" %>
<%= form.time_select "business_hours_attributes_#{index}_closing_time", default: bh[:closing_time].to_time.change(year: 2000, month: 1, day: 1) || Time.zone.parse('18:00') %>
</div>
<% end %>
<div class="actions">
<%= form.submit %>
</div>
<% end %>
From: /app/app/controllers/admin/shops_controller.rb:45 Admin::ShopsController#create:
39: def create
40: @shop_business_hour_form = ShopBusinessHourForm.new(shop_business_hour_form_params)
41: @shop_business_hour_form.user_id = current_user.id # 現在のユーザーのIDを設定
42: @form_url = admin_shops_path
43: @form_method = :post
44:
45: binding.pry
46:
47: if @shop_business_hour_form.save
48: redirect_to [:admin, Shop.find_by(name: @shop_business_hour_form.shop_name)], notice: 'Shop and business hours were successfully created.'
49: else
50: Rails.logger.error(@shop_business_hour_form.errors.full_messages)
51: render :new
52: end
53: end
[1] pry(#
portfolio-web-1 | Started POST "/admin/shops" for 192.168.65.1 at 2024-08-14 13:42:29 +0900
portfolio-web-1 | Cannot render console from 192.168.65.1! Allowed networks: 127.0.0.0/127.255.255.255, ::1
portfolio-web-1 | Processing by Admin::ShopsController#create as TURBO_STREAM
portfolio-web-1 | Parameters: {"authenticity_token"=>"[FILTERED]", "shop_business_hour_form"=>{"shop_name"=>"テスト643", "address"=>"新潟県新発田市大栄町2-5-12", "phone_number"=>"", "duel_space_available"=>"", "opening_hours"=>"", "official_hp"=>"", "twitter"=>"", "instagram"=>"", "tag_list"=>"", "business_hours_attributes_0_day_of_week"=>"0", "business_hours_attributes_0_opening_time(1i)"=>"2000", "business_hours_attributes_0_opening_time(2i)"=>"1", "business_hours_attributes_0_opening_time(3i)"=>"1", "business_hours_attributes_0_opening_time(4i)"=>"11", "business_hours_attributes_0_opening_time(5i)"=>"00", "business_hours_attributes_0_closing_time(1i)"=>"2000", "business_hours_attributes_0_closing_time(2i)"=>"1", "business_hours_attributes_0_closing_time(3i)"=>"1", "business_hours_attributes_0_closing_time(4i)"=>"13", "business_hours_attributes_0_closing_time(5i)"=>"00", "business_hours_attributes_1_day_of_week"=>"1", "business_hours_attributes_1_opening_time(1i)"=>"2000", "business_hours_attributes_1_opening_time(2i)"=>"1", "business_hours_attributes_1_opening_time(3i)"=>"1", "business_hours_attributes_1_opening_time(4i)"=>"09", "business_hours_attributes_1_opening_time(5i)"=>"00", "business_hours_attributes_1_closing_time(1i)"=>"2000", "business_hours_attributes_1_closing_time(2i)"=>"1", "business_hours_attributes_1_closing_time(3i)"=>"1", "business_hours_attributes_1_closing_time(4i)"=>"18", "business_hours_attributes_1_closing_time(5i)"=>"00", "business_hours_attributes_2_day_of_week"=>"2", "business_hours_attributes_2_opening_time(1i)"=>"2000", "business_hours_attributes_2_opening_time(2i)"=>"1", "business_hours_attributes_2_opening_time(3i)"=>"1", "business_hours_attributes_2_opening_time(4i)"=>"09", "business_hours_attributes_2_opening_time(5i)"=>"00", "business_hours_attributes_2_closing_time(1i)"=>"2000", "business_hours_attributes_2_closing_time(2i)"=>"1", "business_hours_attributes_2_closing_time(3i)"=>"1", "business_hours_attributes_2_closing_time(4i)"=>"18", "business_hours_attributes_2_closing_time(5i)"=>"00", "business_hours_attributes_3_day_of_week"=>"3", "business_hours_attributes_3_opening_time(1i)"=>"2000", "business_hours_attributes_3_opening_time(2i)"=>"1", "business_hours_attributes_3_opening_time(3i)"=>"1", "business_hours_attributes_3_opening_time(4i)"=>"09", "business_hours_attributes_3_opening_time(5i)"=>"00", "business_hours_attributes_3_closing_time(1i)"=>"2000", "business_hours_attributes_3_closing_time(2i)"=>"1", "business_hours_attributes_3_closing_time(3i)"=>"1", "business_hours_attributes_3_closing_time(4i)"=>"18", "business_hours_attributes_3_closing_time(5i)"=>"00", "business_hours_attributes_4_day_of_week"=>"4", "business_hours_attributes_4_opening_time(1i)"=>"2000", "business_hours_attributes_4_opening_time(2i)"=>"1", "business_hours_attributes_4_opening_time(3i)"=>"1", "business_hours_attributes_4_opening_time(4i)"=>"09", "business_hours_attributes_4_opening_time(5i)"=>"00", "business_hours_attributes_4_closing_time(1i)"=>"2000", "business_hours_attributes_4_closing_time(2i)"=>"1", "business_hours_attributes_4_closing_time(3i)"=>"1", "business_hours_attributes_4_closing_time(4i)"=>"18", "business_hours_attributes_4_closing_time(5i)"=>"00", "business_hours_attributes_5_day_of_week"=>"5", "business_hours_attributes_5_opening_time(1i)"=>"2000", "business_hours_attributes_5_opening_time(2i)"=>"1", "business_hours_attributes_5_opening_time(3i)"=>"1", "business_hours_attributes_5_opening_time(4i)"=>"09", "business_hours_attributes_5_opening_time(5i)"=>"00", "business_hours_attributes_5_closing_time(1i)"=>"2000", "business_hours_attributes_5_closing_time(2i)"=>"1", "business_hours_attributes_5_closing_time(3i)"=>"1", "business_hours_attributes_5_closing_time(4i)"=>"18", "business_hours_attributes_5_closing_time(5i)"=>"00", "business_hours_attributes_6_day_of_week"=>"6", "business_hours_attributes_6_opening_time(1i)"=>"2000", "business_hours_attributes_6_opening_time(2i)"=>"1", "business_hours_attributes_6_opening_time(3i)"=>"1", "business_hours_attributes_6_opening_time(4i)"=>"09", "business_hours_attributes_6_opening_time(5i)"=>"00", "business_hours_attributes_6_closing_time(1i)"=>"2000", "business_hours_attributes_6_closing_time(2i)"=>"1", "business_hours_attributes_6_closing_time(3i)"=>"1", "business_hours_attributes_6_closing_time(4i)"=>"18", "business_hours_attributes_6_closing_time(5i)"=>"00"}, "commit"=>"Create Shop business hour form"}
portfolio-web-1 | User Load (1.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2 [["id", 2], ["LIMIT", 1]]
portfolio-web-1 | ↳ app/controllers/application_controller.rb:23:in `authenticate_admin!'
portfolio-web-1 | Unpermitted parameters: :business_hours_attributes_0_day_of_week, :business_hours_attributes_0_opening_time(1i), :business_hours_attributes_0_opening_time(2i), :business_hours_attributes_0_opening_time(3i), :business_hours_attributes_0_opening_time(4i), :business_hours_attributes_0_opening_time(5i), :business_hours_attributes_0_closing_time(1i), :business_hours_attributes_0_closing_time(2i), :business_hours_attributes_0_closing_time(3i), :business_hours_attributes_0_closing_time(4i), :business_hours_attributes_0_closing_time(5i), :business_hours_attributes_1_day_of_week, :business_hours_attributes_1_opening_time(1i), :business_hours_attributes_1_opening_time(2i), :business_hours_attributes_1_opening_time(3i), :business_hours_attributes_1_opening_time(4i), :business_hours_attributes_1_opening_time(5i), :business_hours_attributes_1_closing_time(1i), :business_hours_attributes_1_closing_time(2i), :business_hours_attributes_1_closing_time(3i), :business_hours_attributes_1_closing_time(4i), :business_hours_attributes_1_closing_time(5i), :business_hours_attributes_2_day_of_week, :business_hours_attributes_2_opening_time(1i), :business_hours_attributes_2_opening_time(2i), :business_hours_attributes_2_opening_time(3i), :business_hours_attributes_2_opening_time(4i), :business_hours_attributes_2_opening_time(5i), :business_hours_attributes_2_closing_time(1i), :business_hours_attributes_2_closing_time(2i), :business_hours_attributes_2_closing_time(3i), :business_hours_attributes_2_closing_time(4i), :business_hours_attributes_2_closing_time(5i), :business_hours_attributes_3_day_of_week, :business_hours_attributes_3_opening_time(1i), :business_hours_attributes_3_opening_time(2i), :business_hours_attributes_3_opening_time(3i), :business_hours_attributes_3_opening_time(4i), :business_hours_attributes_3_opening_time(5i), :business_hours_attributes_3_closing_time(1i), :business_hours_attributes_3_closing_time(2i), :business_hours_attributes_3_closing_time(3i), :business_hours_attributes_3_closing_time(4i), :business_hours_attributes_3_closing_time(5i), :business_hours_attributes_4_day_of_week, :business_hours_attributes_4_opening_time(1i), :business_hours_attributes_4_opening_time(2i), :business_hours_attributes_4_opening_time(3i), :business_hours_attributes_4_opening_time(4i), :business_hours_attributes_4_opening_time(5i), :business_hours_attributes_4_closing_time(1i), :business_hours_attributes_4_closing_time(2i), :business_hours_attributes_4_closing_time(3i), :business_hours_attributes_4_closing_time(4i), :business_hours_attributes_4_closing_time(5i), :business_hours_attributes_5_day_of_week, :business_hours_attributes_5_opening_time(1i), :business_hours_attributes_5_opening_time(2i), :business_hours_attributes_5_opening_time(3i), :business_hours_attributes_5_opening_time(4i), :business_hours_attributes_5_opening_time(5i), :business_hours_attributes_5_closing_time(1i), :business_hours_attributes_5_closing_time(2i), :business_hours_attributes_5_closing_time(3i), :business_hours_attributes_5_closing_time(4i), :business_hours_attributes_5_closing_time(5i), :business_hours_attributes_6_day_of_week, :business_hours_attributes_6_opening_time(1i), :business_hours_attributes_6_opening_time(2i), :business_hours_attributes_6_opening_time(3i), :business_hours_attributes_6_opening_time(4i), :business_hours_attributes_6_opening_time(5i), :business_hours_attributes_6_closing_time(1i), :business_hours_attributes_6_closing_time(2i), :business_hours_attributes_6_closing_time(3i), :business_hours_attributes_6_closing_time(4i), :business_hours_attributes_6_closing_time(5i). Context: { controller: Admin::ShopsController, action: create, request: #
ストロングパラメーター側を頑張るよりもform側で送る値をコントローラーで受け取りやすい値にするのがいいかもですね fields_forとか調べてみて何か良い形に出来ないか考えてみるのが良いかもです 解決につながるかはわかりませんがいくつか記事貼っておきます https://qiita.com/gotchane/items/6f595911333a8cf69c48 https://takaokouji.github.io/output/form-object/
お忙しところありがとうございます! 確認いたしました🙇
前提条件 shopモデルがあり、shopモデルに月曜日〜日曜日の営業時間の情報を与えるためにShopBusinessHourFormというフォームオブジェクトを作成しました。 新規登録画面と編集画面には_form.html.erbを使用していて画像のように問題なく表示されています。 また、ここの最下部に該当箇所のコード3つとログを添付しましたのでご確認のほどよろしくお願い致します。
実装したいもの ショップの新規作成と編集をフォームオブジェクトを使用して実行したいのですがフォームオブジェクト部分(ShopBusinessHourForm)がデータベースに登録されないのでこれを登録できるようにしたいです。
エラー内容 新規作成と編集自体はできる(saveできている)のですがフォームオブジェクト部分のbusiness_hours(月曜日〜日曜日の営業時間の情報)がデータベースに正常に登録されません。 また編集画面から編集完了ボタンを押下した際には上記のエラーに加えて「DELETE FROM "business_hours」とログに表示されており、business_hours(shopモデルの営業時間情報)が削除されてしまいます。
エラーの意味とエラー内容から推測される原因 新規作成と編集の際のshopの営業時間が正常に登録されないエラーはログに「Unpermitted parameters」と表示されており、ストロングパラメータで許可されていない値が弾かれているからだと推測されます。 解決策としてチャットGPTにログとストロングパラメーターを渡して現在弾かれている値を渡してストロングパラメーターを修正して弾かれないようにするように依頼しましたがこれで解決せず同じエラーが続いています。 また僕自身もチャットGPTの回答を元にログで弾かれている値とストロングパラメーターの許可している値を確認して、許可されているのを確認しましたが実行される際になぜ許可されないのかが分かりません。 また編集画面から編集完了ボタンを押下した際に「DELETE FROM "business_hours」とログに表示され、business_hours(shopモデルの営業時間情報)が削除されてしまうのは1つ目の質問でbusiness_hoursがストロングパラメーターによって弾かれてしまっており、それにより既存の値を見つけることができず、business_hoursが初期化されてしまったのではないかと推測されます。 また、それ以外ではネットで調べてみたところフォームオブジェクトを使用した際のupdateがうまくいかない事象があるらしくそれも関連しているのかと思います(エラーを解決するために調べた資料を参照)
実装する際に参考にした資料
[Rails]大変便利なFormオブジェクトはご存知でしょうか?
[【備忘録】Formオブジェクトについて] (https://zenn.dev/adverdest/articles/form_object_article)
Railsで #update のできるFormObjectを作る
以下は「Unpermitted parameters」が出るエラーに対してのチャットGPTの回答になります。