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

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

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

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

Ruby on Rails

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

オブジェクト指向

オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。

Q&A

解決済

1回答

913閲覧

Formオブジェクトでupdateがうまくいくとnewのビューが開かなくなる

maikoala

総合スコア1

Ruby

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

Ruby on Rails

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

オブジェクト指向

オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。

0グッド

0クリップ

投稿2021/04/05 15:53

前提・実現したいこと

item_categoryというFormオブジェクトで、1つのフォームからitemsテーブル、categoriesテーブルに保存をします。
下記コードで実装すると、編集ページ(items/editのビュー)からupdateはできますが、新規登録するために新規登録ページ(items/newのビュー)にとぼうとすると、下記エラーが出てしまいます。
初心者で恐縮ですが、どの箇所がおかしなことになっているのかご教示願います。

発生している問題・エラーメッセージ

エラーメッセージ NoMethodError in ItemsController#new undefined method `category_name_id' for nil:NilClass ターミナル Started GET "/shops/2/items/new" for ::1 at 2021-04-06 00:11:33 +0900 Processing by ItemsController#new as HTML Parameters: {"shop_id"=>"2"} Owner Load (0.6ms) SELECT `owners`.* FROM `owners` WHERE `owners`.`id` = 3 ORDER BY `owners`.`id` ASC LIMIT 1 Shop Load (0.7ms) SELECT `shops`.* FROM `shops` WHERE `shops`.`id` = 2 LIMIT 1 ↳ app/controllers/items_controller.rb:55:in `set_shop' Owner Load (0.7ms) SELECT `owners`.* FROM `owners` WHERE `owners`.`id` = 3 LIMIT 1 ↳ app/controllers/items_controller.rb:64:in `move_to_index' Completed 500 Internal Server Error in 23ms (ActiveRecord: 1.9ms | Allocations: 4182) NoMethodError (undefined method `category_name_id' for nil:NilClass): app/models/item_category.rb:55:in `default_attributes' app/models/item_category.rb:26:in `initialize' app/controllers/items_controller.rb:12:in `new' app/controllers/items_controller.rb:12:in `new'

該当のソースコード

app/controllers/items_controller.rb

ruby

1class ItemsController < ApplicationController 2 before_action :authenticate_owner!, only: [:new, :create, :edit, :update, :destroy] 3 before_action :set_shop, only: [:index, :new, :create] 4 before_action :set_shop_item, only: [:show, :edit, :update, :destroy] 5 before_action :move_to_index, only: [:new, :create, :edit, :update, :destroy] 6 7 def index 8 @items = @shop.items.order('created_at DESC') 9 end 10 11 def new 12 @item_category = ItemCategory.new 13 end 14 15 def create 16 @item_category = ItemCategory.new(item_params) 17 if @item_category.valid? 18 @item_category.save 19 redirect_to action: :index 20 else 21 render :new 22 end 23 end 24 25 def show 26 end 27 28 def edit 29 @item_category = ItemCategory.new(item: @item) 30 end 31 32 def update 33 @item_category = ItemCategory.new(item_params, item: @item) 34 if @item_category.valid? 35 @item_category.save 36 redirect_to action: :show 37 else 38 render :edit 39 end 40 end 41 42 def destroy 43 redirect_to action: :index if @item.destroy 44 end 45 46 private 47 48 def item_params 49 params.require(:item).permit(:image, :name, :info, :color_id, :price, :category_name_id).merge( 50 owner_id: current_owner.id, shop_id: params[:shop_id] 51 ) 52 end 53 54 def set_shop 55 @shop = Shop.find(params[:shop_id]) 56 end 57 58 def set_shop_item 59 @shop = Shop.find(params[:shop_id]) 60 @item = Item.find(params[:id]) 61 end 62 63 def move_to_index 64 redirect_to root_path unless current_owner == @shop.owner 65 end 66end

app/models/item_category.rb

ruby

1class ItemCategory 2 include ActiveModel::Model 3 attr_accessor :image, :name, :info, :category_name_id, :color_id, :price, :owner_id, :shop_id 4 5 with_options presence: true do 6 validates :image 7 validates :name, length: { maximum: 40 } 8 validates :info, length: { maximum: 1500 } 9 validates :category_name_id, numericality: { message: 'select' } 10 validates :color_id, numericality: { message: 'select' } 11 validates :price, numericality: { only_integer: true, 12 with: /\A[0-9]+\z/, 13 message: 'half-width number' } 14 validates :owner_id 15 validates :shop_id 16 end 17 validates :price, numericality: { greater_than_or_equal_to: 100, 18 less_than_or_equal_to: 9_999_999, 19 message: 'out of setting range' } 20 21 delegate :persisted?, to: :item 22 23 def initialize(attributes = nil, category: Category.new, item: Item.new) 24 @category = category 25 @item = item 26 attributes ||= default_attributes 27 super(attributes) 28 end 29 30 def save 31 ActiveRecord::Base.transaction do 32 @category.update(category_name_id: category_name_id) 33 @item.update(image: image, name: name, info: info, color_id: color_id, price: price, owner_id: owner_id, shop_id: shop_id, 34 category_id: @category.id) 35 end 36 end 37 38 def to_model 39 item 40 end 41 42 private 43 44 attr_reader :item, :category 45 46 def default_attributes 47 { 48 image: item.image, 49 name: item.name, 50 info: item.info, 51 color_id: item.color_id, 52 price: item.price, 53 owner_id: item.owner_id, 54 shop_id: item.shop_id, 55 category_name_id: item.category.category_name_id 56 } 57 end 58end

app/models/item.rb

ruby

1class Item < ApplicationRecord 2 has_one_attached :image 3 belongs_to :owner 4 belongs_to :shop 5 belongs_to :category, dependent: :destroy 6 has_one :order 7 8 extend ActiveHash::Associations::ActiveRecordExtensions 9 belongs_to :color 10end

app/models/category.rb

ruby

1class Category < ApplicationRecord 2 has_many :items 3 4 extend ActiveHash::Associations::ActiveRecordExtensions 5 belongs_to :category_name 6end

app/models/category_name.rb

ruby

1class CategoryName < ActiveHash::Base 2 self.data = [ 3 { id: 1, name: 'ベッド&マットレス' }, 4 { id: 2, name: 'クッション、寝具' }, 5 { id: 3, name: 'ソファ' }, 6 { id: 4, name: 'カーテン' }, 7 { id: 5, name: 'テーブル、机' }, 8 { id: 6, name: 'イス、チェア' }, 9 { id: 7, name: 'テレビ台、リビング収納' }, 10 { id: 8, name: '本棚、シェルフ、収納家具' }, 11 { id: 9, name: 'ラグ、カーペット' }, 12 { id: 10, name: '照明' }, 13 { id: 11, name: 'キッチン収納' }, 14 { id: 12, name: '調理家具、食器' }, 15 { id: 13, name: '洗濯用品、掃除グッズ' }, 16 { id: 14, name: 'トイレ用品、バス用品' }, 17 { id: 15, name: 'インテリア雑貨、日用品' }, 18 { id: 16, name: '家電、電化製品' }, 19 { id: 17, name: '子供家具、ベビー用品' }, 20 { id: 18, name: 'ペット用品' }, 21 { id: 19, name: 'ガーデニング用品、ガーデンファニチャー' }, 22 { id: 20, name: 'その他' } 23 ] 24 25 include ActiveHash::Associations 26 has_many :categories 27end

app/views/items/new.html.erb

ruby

1<h2>商品の出品</h2> 2 3<%= form_with model: @item_category, url: shop_items_path, local: true do |form| %> 4 <%= render "shared/error_messages", model: form.object %> 5 6 <div> 7 <%= form.label :image, '商品画像' %> 8 <%= form.file_field :image %> 9 </div> 10 <div> 11 <%= form.label :name, '商品名' %> 12 <%= form.text_field :name %> 13 </div> 14 <div> 15 <%= form.label :info, '商品情報' %> 16 <%= form.text_area :info %> 17 </div> 18 <div> 19 <%= form.label :category_name_id, 'カテゴリー' %> 20 <%= form.collection_select(:category_name_id, CategoryName.all, :id, :name, {include_blank: "--"}, {}) %> 21 </div> 22 <div> 23 <%= form.label :color_id, '色' %> 24 <%= form.collection_select(:color_id, Color.all, :id, :name, {include_blank: "--"}, {}) %> 25 </div> 26 <div> 27 <%= form.label :price, '価格' %> 28 <%= form.text_field :price %> 29 </div> 30 <div> 31 <%= form.submit '出品する' %> 32 </div> 33<% end %>

app/views/items/edit.html.erb

ruby

1div> 2<%= @shop.name %> 3</div> 4<div> 5<%= @item.name %> 6</div> 7 8<%= form_with model: @item_category, url: shop_item_path(@shop.id, @item.id), local: true do |form| %> 9 <%= render "shared/error_messages", model: form.object %> 10 11 <div> 12 <%= form.label :image, '商品画像' %> 13 <%= form.file_field :image %> 14 </div> 15 <div> 16 <%= form.label :name, '商品名' %> 17 <%= form.text_field :name %> 18 </div> 19 <div> 20 <%= form.label :info, '商品情報' %> 21 <%= form.text_area :info %> 22 </div> 23 <div> 24 <%= form.label :category_name_id, 'カテゴリー' %> 25 <%= form.collection_select(:category_name_id, CategoryName.all, :id, :name, {include_blank: "--"}, {}) %> 26 </div> 27 <div> 28 <%= form.label :color_id, '色' %> 29 <%= form.collection_select(:color_id, Color.all, :id, :name, {include_blank: "--"}, {}) %> 30 </div> 31 <div> 32 <%= form.label :price, '価格' %> 33 <%= form.text_field :price %> 34 </div> 35 <div> 36 <%= form.submit '変更する' %> 37 </div> 38 <div> 39 <%= link_to 'もどる', shop_item_path(@shop.id, @item.id) %> 40 </div> 41<% end %>

試したこと

おそらく、newアクションでFormオブジェクトの

def initialize end

の箇所が動かないのは、

def default_attributes { image: item.image, name: item.name, info: item.info, color_id: item.color_id, price: item.price, owner_id: item.owner_id, shop_id: item.shop_id, category_name_id: item.category.category_name_id } end

のせいと考えて、ここを

def default_attributes { image: item.image, name: item.name, info: item.info, color_id: item.color_id, price: item.price, owner_id: item.owner_id, shop_id: item.shop_id } end

として、category_name_idの記述を削除すれば、newもeditもビューを開けて、create、updateどちらも可能でした。
ただし、 category_name_id: item.category.category_name_idを消去すると、editのビューページ(編集フォーム)を開いた時category_name_id内の既存の文言はなくなり「ーー」となってしまいます(他のnameからinfoまでの内容は残ったままです。ActiveStorageでつけた写真は消えます)。

category_name_idを残したまま実装することは難しいでしょうか。

参考にしたページ

https://laptrinhx.com/formobujekutode-fu-shuteburuhe-zhino-bao-cun-539823778/

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

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

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

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

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

guest

回答1

0

ベストアンサー

item.category が nil の状態のときに category_name_id を呼んでいるのでエラーになっています。

以下のようにすると item.category が nil のときは category_name_id が呼ばれません。

ruby

1category_name_id: item.category && item.category.category_name_id

item.category が nil のときは category_name_id は nil になります。
item.category が存在する場合は item.category.category_name_id の値になります。

また、以下のようにちょっと短く書くこともできます。

ruby

1category_name_id: item.category&.category_name_id

投稿2021/04/08 14:20

neko_daisuki

総合スコア2090

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

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

maikoala

2021/04/09 12:44

ありがとうございます! item.categoryがnilなのに、category_name_idは呼べないよって言われていたということなのですね…! 問題なくnewもeditも動きました。 大変助かりました。 ご丁寧にありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問