LoginSignup
56
48

More than 5 years have passed since last update.

accepts_nested_attributes_forで指定した関連先のvalidationに自身のidがpresence: trueだとnested_formが使えない件

Last updated at Posted at 2015-03-26

(タイトルがルー語っぽくなりました)

はじめに

以下の様なhas_many throughな関係があるとします

class User < ActiveRecord::Base
  has_many :memberships

  has_many :groups, through: :memberships
end

class Membership < ActiveRecord::Base
  belongs_to :user

  belongs_to :group

  validates :user_id, presence: true
  validates :group_id, presence: true
end

class Group < ActiveRecord::Base
  has_many :memberships
  accepts_nested_attributes_for :memberships, allow_destroy: true

  has_many :users, through: :memberships
end

Userが複数のGroupに所属できるモデルの関連です
Groupの作成時に所属Userを選択できるようにaccepts_nested_attributes_for :membershipsを設定しました

formは以下のようにnested_formを使ってfields_forを作ります

= nested_form_for @group do |f|

  = f.fields_for :memberships do |nf|
    = nf.hidden_field :id
    = nf.collection_select :user_id, User.all, :id, :name
    = nf.link_to_remove 'Remove'
  = f.link_to_add 'Add User', :memberships

  = f.text_field :name

  = f.submit

こうしておくとGroupのformからUserを複数選択してGroup作成と同時に所属Userも登録できるはずなんですが…

関連先でvalidationエラーする

なんとMembershipにvalidates :group_id, presence: trueが設定されているため、Groupの作成時にMembership上にgroup_idが必要です、というエラーが発生してしまいます。。。

Membership group は必須項目です

いや、知ってますが……

inverse_ofとvalidationを関連の名前にする

以下のようにするとidが存在しなくても、オブジェクト同士の関係があればvalidationエラーにならないことがわかりました

class Group
+  has_many :memberships, inverse_of: :group
-  has_many :memberships
end

class Membership
+  validates :group, presence: true
-  validates :group_id, presence: true
end

inverse_ofを使用するとbelongs_to側からsave前でも関連先が確認できるようにあるみたいです、その上でgroup_idではなく関連の名前でvalidationを書いておくとちゃんとpresence: trueを確認できるようになるので通るみたいです。

56
48
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
56
48