質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.47%
Ruby on Rails 5

Ruby on Rails 5は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Model

MVCモデルの一部であるModelはアプリケーションで扱うデータとその動作を管理するために扱います。

Q&A

解決済

1回答

884閲覧

unknown attribute '' for It..と出て一括編集できない

renat

総合スコア2

Ruby on Rails 5

Ruby on Rails 5は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Model

MVCモデルの一部であるModelはアプリケーションで扱うデータとその動作を管理するために扱います。

0グッド

0クリップ

投稿2020/09/10 14:23

編集2020/09/13 13:16

前提・実現したいこと

解決したいこと:親モデルに紐づく子モデルを一括編集をしたい

Railsで一括編集する機能を開発しています。
一括で編集する際に、unknown attribute '39' for It.. エラーが出て編集できません。
StrongParameter周辺に問題があるのはわかるのですが、どのようにすればよいかわかりません。
足りない情報があれば指摘していただけると助かりますm(_ _)m

###問題が発生するまでの流れ・手順
一括で編集するボタンを押した時

エラーメッセージ

イメージ説明

ソースコード

app/views/its/new.html.erb

<%= form_with model: @its, url: its_path, local: true do |form| %> <% @its.collection.each do |it| %> <%= fields_for 'its[]', it do |field| %> <%= field.label :situation %> <%= field.text_field :situation, class: 'form-field' %> <br> <%= field.label :behavior %> <%= field.text_field :behavior, class: 'form-field' %> <% end %> <% end %> <%= form.submit %> <%= link_to '戻る', it_path(current_user) %> <% end %>

app/views/its/edit.html.erb

<%= form_with model: @its, url: it_path, method: :patch, local: true do |form| %> <% @its.each do |it| %> <%= fields_for 'its[]', it do |field| %> <%= field.label :situation %> <%= field.text_field :situation, class: 'form-field', required: true %> <br> <%= field.label :behavior %> <%= field.text_field :behavior, class: 'form-field', required: true %> <% end %> <% end %> <%= form.submit '一括編集'%> <%= link_to '戻る', it_path(current_user) %> <% end %>

app/views/its/show.html.erb

<% @user.its.each do |it| %> <div class="wrapper"> <div class="column"> <h1><%= simple_format(it.situation) %></h1> </div> <div class="column"> <h1><%= simple_format(it.behavior) %></h1> </div> </div> <% end %> <%= link_to(content_tag(:i, '', class: "fas fa-trash-alt fa-3x faa-horizontal animated-hover fa-pull-right", style: "color: rgb(80,80,80);"), it_path, method: :delete, data: {confirm: "本当に削除しますか?"}) %> <%= link_to(content_tag(:i, '', class: "fas fa-edit fa-3x faa-vertical animated-hover fa-pull-right", style: "color: rgb(80,80,80);"), edit_it_path ) %>

app/models/user.rb

#== Schema Information # id :bigint not null, primary key # admin :boolean default(FALSE) # email :string(255) # name :string(255) # password_digest :string(255) # remember_digest :string(255) # created_at :datetime not null # updated_at :datetime not null # # Indexes # # index_users_on_email (email) UNIQUE # class User < ApplicationRecord has_many :its, dependent: :destroy end

app/models/it.rb

# == Schema Information # # Table name: its # # id :bigint not null, primary key # behavior :text(65535) # situation :text(65535) # created_at :datetime not null # updated_at :datetime not null # user_id :bigint # # Indexes # # index_its_on_user_id (user_id) # # Foreign Keys # # fk_rails_... (user_id => users.id) # class It < ApplicationRecord belongs_to :user end

app/models/its_collection.rb

# Itのコレクションモデル class ItCollection include ActiveModel::Conversion extend ActiveModel::Naming extend ActiveModel::Translation include ActiveModel::AttributeMethods include ActiveModel::Validations IT_NUM = 3 # 同時にitを作成する数 attr_accessor :collection # 初期化メソッド def initialize(current_user, attributes = []) if attributes.present? self.collection = attributes.map do |value| It.new( user_id: current_user.id, situation: value['situation'], behavior: value['behavior'] ) end else self.collection = IT_NUM.times.map { It.new } end end # レコードが存在するか確認するメソッド def persisted? false end # コレクションをDBに保存するメソッド def save is_success = true ActiveRecord::Base.transaction do collection.each do |result| # バリデーションを全てかけたいからsave!ではなくsaveを使用 is_success = false unless result.save end # バリデーションエラーがあった時は例外を発生させてロールバックさせる raise ActiveRecord::RecordInvalid unless is_success end rescue p 'エラー' ensure return is_success end end

app/controllers/its_controller.rb

class ItsController < ApplicationController before_action :logged_in_user, only: [:create, :destroy] before_action :correct_user, only: :destroy skip_before_action :verify_authenticity_token def show @user = User.find(params[:id]) @its = @user.its end def new @its = ItCollection.new(current_user) end def create @its = ItCollection.new(current_user, its_params) if @its.save flash[:success] = '成功しました!' redirect_to it_path(current_user) else render 'new' end end def destroy @it.destroy flash[:danger] = "#{@its.situation}削除しました!" redirect_to request.referrer || root_url end def edit @its = current_user.its end def update @its = current_user.its if @its.update(its_params) flash[:success] = "編集しました!" redirect_to it_path(current_user) else render 'its/edit' end end private def its_params params.slice(:its).permit(its: [:situation, :behavior]).require(:its) end def correct_user @it = current_user.its.find_by(id: params[:id]) redirect_to root_url if @it.nil? end end

app/helpers/sessions_helpers.rb

module SessionsHelper # 渡されたユーザーでログインする def log_in(user) session[:user_id] = user.id end # ユーザーのセッションを永続的にする def remember(user) user.remember cookies.permanent.signed[:user_id] = user.id cookies.permanent[:remember_token] = user.remember_token end # 記憶トークンcookieに対応するユーザーを返す def current_user if (user_id = session[:user_id]) @current_user ||= User.find_by(id: user_id) elsif (user_id = cookies.signed[:user_id]) user = User.find_by(id: user_id) if user && user.authenticated?(cookies[:remember_token]) log_in user @current_user = user end end end # 渡されたユーザーがログイン済みユーザーであればtrueを返す def current_user?(user) user == current_user end # ユーザーがログインしていればtrue、その他ならfalseを返す def logged_in? !current_user.nil? end # 永続的セッションを破棄する def forget(user) user.forget cookies.delete(:user_id) cookies.delete(:remember_token) end # 現在のユーザーをログアウトする def log_out forget(current_user) session.delete(:user_id) @current_user = nil end end

ログ

web_1 | Started PATCH "/its/8" for 172.19.0.1 at 2020-09-11 05:52:21 +0000 web_1 | Cannot render console from 172.19.0.1! Allowed networks: 172.18.0.1, 127.0.0.0/127.255.255.255, ::1 web_1 | Processing by ItsController#update as HTML web_1 | Parameters: {"utf8"=>"✓", "authenticity_token"=>"/MDK5kbE0pqSh6uHKcWA==", "its"=>{"39"=>{"situation"=>"Situation1", "behavior"=>"Behavior1"}, "40"=>{"situation"=>"Situation4", "behavior"=>"Behavior4"}, "41"=>{"situation"=>"Situation8", "behavior"=>"Behavior8"}}, "commit"=>"一括編集", "id"=>"8"} web_1 | User Load (0.2ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 8 LIMIT 1 web_1 | It Load (0.4ms) SELECT `its`.* FROM `its` WHERE `its`.`user_id` = 8 ORDER BY `its`.`created_at` DESC web_1 | (0.2ms) BEGIN web_1 | (0.2ms) ROLLBACK web_1 | Completed 500 Internal Server Error in 112ms (ActiveRecord: 3.2ms) web_1 | ActiveModel::UnknownAttributeError - unknown attribute '39' for It.: web_1 | app/controllers/its_controller.rb:44:in `update'

環境

rails: 5.2.3 ruby: 2.5.7

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

まず気になることは、

@its = current_user.its.where(params[:id])

末尾のwhere(params[:id])は無意味な条件式となっていますが、何を条件としているのでしょうか?


Rails wayに修正

Rails wayな方法としてはaccepts_nested_attributes_forを用いて更新することになります。

ruby

1class User < ApplicationRecord 2 has_many :its, dependent: :destroy 3 accepts_nested_attributes_for :its 4end

erb

1<%= form_with model: current_user, url: it_path, method: :patch, local: true do |form| %> 2 <%= form.fields_for :its do |field| %> 3 <%= field.label :situation %> 4 <%= field.text_field :situation, class: 'form-field', required: true %> 5 <br> 6 <%= field.label :behavior %> 7 <%= field.text_field :behavior, class: 'form-field', required: true %> 8 <% end %> 9 <%= form.submit '一括編集'%> 10 <%= link_to '戻る', it_path(current_user) %> 11<% end %>

ruby

1def edit 2end 3 4def update 5 if current_user.update(user_its_params) 6 flash[:success] = "編集しました!" 7 redirect_to it_path(current_user) 8 else 9 render 'its/edit' 10 end 11end 12 13private 14def user_its_params 15 params.require(:user).permit(its_attributes: [:situation, :behavior, :id]) 16end

投稿2020/09/10 22:34

編集2020/09/11 07:51
asm

総合スコア15147

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

renat

2020/09/11 00:02

回答ありがとうございます。 指摘されたところの修正をしたところ、(質問欄も修正) found unpermitted parameters:とエラーの内容が変わりました。
renat

2020/09/11 01:20 編集

指摘されたところの修正 ① def its_params params.slice(:its).permit(its: [:situation, :behavior] end を試したところ、(質問欄も修正) ActiveModel::UnknownAttributeError - unknown attribute 'its' for It.というエラーが発生しました。 ② def its_params params.require(:its).each_value{|v| v.permit(:situation, :behavior) } end を試したところ undefined method `each_value' for #<ActionController::Parameters:0x00007fccdc09d070> Did you mean? each_pair というエラーが発生しました。
asm

2020/09/11 05:03

ありがとうございます。 5.2系のみeach_valueがないんですね。初めて知りました。
renat

2020/09/11 06:02 編集

指摘されたところの修正をしました(質問欄も修正) ① def its_params params.slice(:its).permit(its: [:situation, :behavior]).require(:its) end を試したところunknown attribute '39' for It.というエラーが発生しました。 ② def its_params params.require(:its).transform_values{|v| v.permit(:situation, :behavior)} end を試したところActiveModel::ForbiddenAttributesError というエラーが発生しました。 ③ def its_params params.require(:its).permit! end を試したところunknown attribute '39' for It. というエラーが発生しました(①と同じ?)
renat

2020/09/11 08:14

モデルとビューとコントローラーを指摘されたように修正しましたところ 期待していた機能(一括編集)になりました! 長時間付き合っていただきありがとうございましたm(_ _)m
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.47%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問