GoRails Nested form — — Rails 5

Yeng Tsan
4 min readFeb 13, 2017

--

Model

首先要先有一個root instance

class ForumThread < ApplicationRecord
belongs_to :user
has_many :forum_posts
accepts_nested_attributes_for :forum_posts validates :subject, presence: true
validates_associated :forum_posts
end

接著有關聯

class ForumPost < ApplicationRecord
belongs_to :user
belongs_to :forum_thread, optional: true
validates :body
end

Controller

def new
@thread = ForumThread.new
@thread.forum_posts.new
end
def create
@thread = current_user.forum_threads.new forum_thread_params
@thread.forum_posts.first.user_id = current_user.id
if @thread.save
redirect_to @thread
else
render 'new'
end
end

必須要在controller 中new出 nested attribute的物件,才會在view中被顯示出來。

view

<%= form_for @forum_thread do |f| %>
<%= f.text_field :subject %>
<%= f.fields_for :forum_posts do |p| %>
<%= p.text_area :body %>
<% end %>


<%= f.submit %><% end %>

送出去的params 中,除了 form_thread table 的column當key之外,還多了 forum_posts_attributes 來傳nested_attribute的值

江湖一點訣,說破不值錢 — — nested form in Rails 5

在Rails5中,如果有關聯性的資料要被產生而缺少foreign key的話,會產生錯誤,例如

=> #<ActiveModel::Errors:0x007fa862ee5298 @base=#<ForumThread id: nil, user_id: 1, subject: "subject", created_at: nil, updated_at: nil>, @messages={:"forum_posts.forum_thread"=>["must exist"], :forum_posts=>["is invalid"]}, @details={:"forum_posts.forum_thread"=>[{:error=>:blank}], :forum_posts=>[{:error=>:invalid, :value=>#<ActiveRecord::Associations::CollectionProxy [#<ForumPost id: nil, forum_thread_id: nil, user_id: 1, body: "I amm body", created_at: nil, updated_at: nil>]>}]}>
irb(main):014:0> post

以ForumThread跟ForumPost為例,在nested_form中,forum_thread還沒有被create出來,只是被new出來的而已;因此,forum_post還無法抓取到forum_thread的id,但由於forum_post是被forum_thread的instance給new出來的,產生

「forum_thread找得到forum_post,但forum_post找不到forum_thread」

的窘境

因此,必須要在 ForumPost的model中修改條件

class ForumPost < ApplicationRecord
belongs_to :user
belongs_to :forum_thread, optional: true
validates :body, presence: true
end

必須加入 optional: true

讓forum_post被產生的時候,不一定要有foreign_key

--

--

Yeng Tsan
Yeng Tsan

Written by Yeng Tsan

Software developer, Career consultant, Product manager.開啟你的海外職涯,從日本開始 https://engineer.taiwan-career.com/

No responses yet