前提・実現したいこと
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/
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/04/09 12:44