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

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

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

Vue.jsは、Webアプリケーションのインターフェースを構築するためのオープンソースJavaScriptフレームワークです。

JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

Ruby on Rails

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

保存

保存(save)とは、特定のファイルを、ハードディスク等の外部記憶装置に記録する行為を指します。

Q&A

解決済

1回答

1522閲覧

assign_attributesメソッドでDBに保存しようとしてしまう

tenten11055

総合スコア67

Vue.js

Vue.jsは、Webアプリケーションのインターフェースを構築するためのオープンソースJavaScriptフレームワークです。

JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

Ruby on Rails

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

保存

保存(save)とは、特定のファイルを、ハードディスク等の外部記憶装置に記録する行為を指します。

0グッド

0クリップ

投稿2019/12/05 12:55

編集2019/12/05 14:09

#解決したいこと
編集画面でボタン押下時にバリデーションを表示させたいのですが、
アクション内のassign_attributesでDBに保存しようとしてしまいます。
(編集確認画面遷移前のバリデーションです)

##ソース

controller

1module Api 2 module V1 3 class SuAccountsController < ApiController 4 before_action :set_su_account, only: [:show, :edit, :update_confirm] 5 6 def show 7 end 8 9 def edit 10 end 11 12 def update_confirm 13 # debugger 14 @su_account.assign_attributes(update_su_account_params) 15 if @su_account.validate 16 render json: @su_account, status: :ok 17 else 18 render json: { errors: @su_account.errors.keys.map { 19 |key| [ key, @su_account.errors.full_messages_for(key) ] 20 }.to_h, render: 'show.json.jbuilder' }, status: :unprocessable_entity 21 end 22 end 23 24 def update 25 end 26 27 private 28 29 def set_su_account 30 @su_account = params[:su_account].present? ? 31 SuAccount.find(params[:su_account][:id]) : SuAccount.find(params[:id]) 32 end 33 34 def update_su_account_params 35 params.require(:su_account).permit( 36 :id, 37 :group_name, 38 :image_url, 39 su_company_attributes: [ 40 :su_account_id, 41 :company_name, 42 :company_hp, 43 :establishment_on, 44 :establishment_year, 45 :establishment_month, 46 :establishment_date, 47 :representative, 48 :business_description, 49 :capital, 50 :capital_unit, 51 :address 52 ], 53 user_attributes: [ 54 :su_account_id, 55 :email, 56 :last_name, 57 :first_name, 58 :tel 59 ] 60 ).tap do |v| 61 year = params[:su_account][:su_company_attributes][:establishment_year] 62 month = params[:su_account][:su_company_attributes][:establishment_month] 63 date = params[:su_account][:su_company_attributes][:establishment_date] 64 v[:su_company_attributes][:establishment_on] = "#{year}/#{month}/#{date}" 65 end 66 end 67 end 68 end 69end

APIで「update_confirm」アクションにパラメータをPOSTしています。

params

1app/controllers/api/v1/su_accounts_controller.rb:14:in `update_confirm' 2Started POST "/api/v1/su_accounts/update_confirm" for 127.0.0.1 at 2019-12-05 12:36:02 +0000 3Cannot render console from 172.18.0.1! Allowed networks: 127.0.0.0/127.255.255.255, ::1 4Processing by Api::V1::SuAccountsController#update_confirm as JSON 5 Parameters: {"su_account"=>{"id"=>1, "group_name"=>"良い部署", "image_url"=>"", "su_company_attributes"=>{"su_account_id"=>1, "company_name"=>"", "company_hp"=>"https://hoge.com", "establishment_year"=>2019, "establishment_month"=>11, "establishment_date"=>1, "representative"=>"ほげ太郎", "business_description"=>"ほげほげの開発", "capital"=>2000000, "capital_unit"=>"us_dollar", "address"=>"ほげ県ほげ市"}, "user_attributes"=>{"email"=>"hogehugaa@example.com", "last_name"=>" ほげ太郎", "first_name"=>"ほげまつ", "tel"=>nil}}} 6

そしてアクション内の@su_account.assign_attributes(update_su_account_params)

log

1 SuAccount Load (1.1ms) SELECT `su_accounts`.* FROM `su_accounts` WHERE `su_accounts`.`deleted_at` IS NULL AND `su_accounts`.`id` = 1 LIMIT 1 2 ↳ app/controllers/api/v1/su_accounts_controller.rb:31:in `set_su_account' 3 SuCompanyInfo Load (0.6ms) SELECT `su_company_infos`.* FROM `su_company_infos` WHERE `su_company_infos`.`deleted_at` IS NULL AND `su_company_infos`.`su_account_id` = 1 LIMIT 1 4 ↳ app/controllers/api/v1/su_accounts_controller.rb:14:in `update_confirm' 5 (0.4ms) BEGIN 6 ↳ app/controllers/api/v1/su_accounts_controller.rb:14:in `update_confirm' 7 SuCompanyInfo Update (1.6ms) UPDATE `su_company_infos` SET `su_company_infos`.`su_account_id` = NULL, `su_company_infos`.`updated_at` = '2019-12-05 12:36:02.686532' WHERE `su_company_infos`.`id` = 1 8 ↳ app/controllers/api/v1/su_accounts_controller.rb:14:in `update_confirm' 9 (0.6ms) ROLLBACK 10 ↳ app/controllers/api/v1/su_accounts_controller.rb:14:in `update_confirm' 11Completed 500 Internal Server Error in 112ms (ActiveRecord: 12.3ms | Allocations: 26144) 12 13 14 15ActiveRecord::NotNullViolation (Mysql2::Error: Column 'su_account_id' cannot be null): 16 17app/controllers/api/v1/su_accounts_controller.rb:14:in `update_confirm'

しっかり保存しようとしています。
nullだから保存できないカラムは更新したくないカラムだし、
そもそもassign_attributesって保存はしないんじゃないの・・・と思っています。

@su_accountにパラメータを渡し、保存はせずにバリデーションをかけ、
エラー内容をjsonで受け取りたいのです。

なぜ保存されてしまうのか、教えていただけると助かります。
宜しくお願い致します。

※ストロングパラメーターのsu_account_idはあってもなくても同じ結果でした。

モデルを追記しました。
リレーションが怪しい気はしています。。

model

1class SuAccount < ApplicationRecord 2 # 論理削除使用 3 acts_as_paranoid 4 5 ## 6 # relations 7 ## 8 9 has_one :su_company, class_name: 'SuCompanyInfo' 10 has_one :user, class_name: 'User' 11 12 accepts_nested_attributes_for :su_company, allow_destroy: true 13 accepts_nested_attributes_for :user, allow_destroy: true 14 15 ## 16 # validates 17 ## 18 19 # 部署名 20 validates :group_name, 21 presence: true, 22 length: { maximum: 100 } 23 24 # URL形式チェック 25 if Rails.env == 'production' 26 validates :image_url, format: /\A#{URI::regexp(%w(http https))}\z/ 27 end 28end 29
class SuCompanyInfo < ApplicationRecord # 論理削除用 acts_as_paranoid ## # relations ## belongs_to :su_account, optional: true ## # validates ## # 企業名 validates :company_name, presence: true, length: { maximum: 100 } # 企業HP validates :company_hp, length: { maximum: 2048 }, format: /\A#{URI::regexp(%w(http https))}\z/ # 設立年月日 validates :establishment_on, date: true, reduce: true validates :establishment_year, presence: true, if: -> { establishment_month.presence || establishment_date.presence } validates :establishment_month, presence: true, if: -> { establishment_year.presence } validates :establishment_date, presence: true, if: -> { establishment_year.presence } # 代表者 validates :representative, length: { maximum: 50 } # 事業内容 validates :business_description, length: { maximum: 500 } # 資本金 validates :capital, length: { maximum: 20 }, numericality: { only_integer: true, allow_blank: true } # 通貨単位 validates :capital_unit, presence: true, if: -> { capital.presence } # 所在地 validates :address, length: { maximum: 200 } ## # enums ## enum capital_unit: { us_dollar: 1, yen: 2, yuan: 3 } attribute :establishment_year attribute :establishment_month attribute :establishment_date end

model

1class User < ApplicationRecord 2 # 論理削除使用 3 acts_as_paranoid 4 5 devise :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable, :lockable, :password_expirable, :secure_validatable, :password_archivable, :expirable 6 include DeviseTokenAuth::Concerns::User 7 8 ## 9 # relations 10 ## 11 12 belongs_to :su_account, optional: true 13 14 ## 15 # enums 16 ## 17 18 enum account_type: { DTVS: "01", DTVSCM: "02", Company: "11", CompanyPIC: "12", SUUser: "21" }, _prefix: true 19 20 ## 21 # validates 22 ## 23 24 validates :account_type, 25 presence: true 26 27 validates :password, 28 password_complexity: true, 29 if: :password_required? 30 31 # 姓 32 validates :last_name, 33 presence: true, 34 length: { maximum: 20 } 35 36 # 名 37 validates :first_name, 38 presence: true, 39 length: { maximum: 20 } 40 41 # メールアドレス 42 validates :email, 43 presence: true, 44 length: { maximum: 256 }, 45 email: true, 46 uniqueness: true, on: :create 47 48 49 # 電話番号 50 validates :tel, 51 allow_blank: true, 52 length: { maximum: 25 }, 53 format: { with: /(\d|-|+).*/ } 54 55end 56

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

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

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

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

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

guest

回答1

0

自己解決

モデルのリレーションで

accepts_nested_attributes_for :su_company, allow_destroy: true, update_only: true accepts_nested_attributes_for :user, allow_destroy: true, update_only: true

のようにupdate_only: trueを付与したところ解決しました。

参考にした記事
has_oneな関連をaccepts_nested_attributes_forしている場合にattributesで代入した場合idが無いとdestroyされる

投稿2019/12/05 14:44

編集2019/12/05 14:45
tenten11055

総合スコア67

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問