0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Formオブジェクトの記述方法

Posted at

丸3日データベースに保存されない状態に悩んだ部分です。
モデル間の関係性、記述方法、メソッドの使い方がややこしかった部分です。
モデルファイルに絞ってまとめます。

購入機能があるアプリで購入すると配送先情報がorderテーブルへ、購入履歴がpurchaseテーブルへそれぞれ保存される状態を目指します。

1.model配下にorder_fomr.rbを作成

このファイルにorder.rbとpurchase.rbに記述するべきカラム、バリデーション、保存する処理を記述していく。

order_form.rb
class OrderForm
  include ActiveModel::Model
end

新たなクラスを定義し、include ActiveModel::Modelでform_with や render などのヘルパーメソッドの引数として扱え、バリデーションの機能を使用できるようにする。

2.それぞれのモデルで扱うカラムをすべて記述

order_form.rb
class OrderForm
  include ActiveModel::Model
  #orderテーブル、purchasesテーブルのカラムを書く
  attr_accessor :post_code, :region_id, :city, :house_number, :building_name, :tel, :item_id, :user_id
end

ここで、orderテーブルにはpurchase_idが入りそうな気がしますが、purchase_idはorderが保存されてから生成されるのでこの時点で記述の必要はない。
purchaseは購入履歴なのでorderが済んでから、という考え方。

3.バリデーション

order_form.rb
class OrderForm
  include ActiveModel::Model
  #orderテーブル、purchasesテーブルのカラムを書く
  attr_accessor :post_code, :region_id, :city, :house_number, :building_name, :tel, :item_id, :user_id
  #purchase_idはorderが保存されてから生成されるので不要

  with_options presence: true do
    validates :post_code, format: { with: /\A[0-9]{3}-[0-9]{4}\z/, message: "はハイフンあり7桁で入力して下さい" }
    validates :region_id, numericality: { other_than: 1, message: 'を選択してください' }
    validates :city
    validates :house_number
    validates :tel, format: { with: /\A\d{10,11}\z/, message: "はハイフンなし10桁か11桁で入力して下さい" }
    validates :item_id
    validates :user_id
  end

with_options presence: true doでdo ~ end内のバリデーションはpresence: trueであることをまとめられる。
order.rbとpurchase.rbにバリデーションを記述する必要はない。

4.データ保存の処理

order_form.rb
class OrderForm
include ActiveModel::Model
#orderテーブル、purchasesテーブルのカラムを書く
attr_accessor :post_code, :region_id, :city, :house_number, :building_name, :tel, :item_id, :user_id
#purchase_idはorderが保存されてから生成されるので不要

with_options presence: true do
  validates :post_code, format: { with: /\A[0-9]{3}-[0-9]{4}\z/, message: "はハイフンあり7桁で入力して下さい" }
  validates :region_id, numericality: { other_than: 1, message: 'を選択してください' }
  validates :city
  validates :house_number
  validates :tel, format: { with: /\A\d{10,11}\z/, message: "はハイフンなし10桁か11桁で入力して下さい" }
  validates :item_id
  validates :user_id
end
  
def save  #attr_accessorの値をそれぞれのテーブルに分ける
  
  #購入履歴を保存。orderでpurchase_idを使うので代入しておく。
  purchase = Purchase.create(item_id: item_id, user_id: user_id)
  #配送先情報を保存
  Order.create(post_code: post_code, region_id: region_id, city: city, house_number: house_number, building_name: building_name, tel: tel, purchase_id: purchase.id, user_id: user_id, item_id: item_id)
  
end
end

ここで先ほどattr_accessorでは記述不要としたpurchase_idが出てくる。
Orderがcreateされたタイミングでpurchase_idは必要になるのでpurchase.idとして追加する。

attr_accessorの値を各テーブルに一つずつもれなく振り分ける、というイメージでいたのでOrder.createにitem_id,user_idの記述が足りないことに気づけず苦戦しました。

そしてpurchase.idの生成されるタイミングも難しかったポイントです。
紙に書きだして、一つずつ理解しながら進めていって解決できました。
頭の中でイメージするだけではうまく組み立てられないので、今後も紙ベースは使っていこうと思います。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?