Skip to content

Instantly share code, notes, and snippets.

@wagurano
Last active November 15, 2015 15:10
Show Gist options
  • Save wagurano/d31f25dd6bdef42f00af to your computer and use it in GitHub Desktop.
Save wagurano/d31f25dd6bdef42f00af to your computer and use it in GitHub Desktop.
Nested form rails

입력 폼 중첩

설문조사 사례로 살펴보는 모델 관계에 따라 중첩하는 입력 폼

준비

설문조사 서식으로 입력폼을 만듭니다.

rails new surveyform

설문조사(survey)의 기본틀을 만듭니다.

rails g scaffold survey name:string
rake db:migrate

설문조사의 각 문항(question)의 모델을 만듭니다.

rails g model question content:text survey:references
rake db:migrate

survey 모델을 수정합니다.

  • dependent 옵션을 :destory로 설정하여 survey를 삭제하면 question 도 삭제합니다.
  • accepts_nested_attributes_for 는 survey 에서 question을 여러개 만들어서 붙일 수 있습니다.

/app/models/survey.rb

class Survey < ActiveRecord::Base
  has_many :questions, :dependent => :destroy
  accepts_nested_attributes_for :questions
end

입력 폼 구성

survey form

fields_for 는 questions 에 대한 폼을 생성합니다.

/app/views/survey/_form.html.erb

<div>
<%= f.fields_for :questions do |builder| %>
<p>
  <%= builder.label :content, "Question" %><br />
  <%= builder.text_area :content, :rows => 3 %>
</p>
<% end %>
</div>

survey 콘트롤러에서 question 을 생성해줍니다.

/app/controllers/surveys_controller.rb

# GET /surveys/new
def new
  @survey = Survey.new
  3.times { @survey.questions.build }
end
...
def survey_params
  params.require(:survey).permit(:name, questions_attributes: [:id, :content])
end

데이타 입력하여 설문조사 생성

제목: 시청율 조사

내용:

  1. 시청하는 티비 프로그램의 수는 몇편입니까?

  2. 어떤 드라마를 좋아합니까?

/app/views/survey/show.html.erb

<p id="notice"><%= notice %></p>

<p>
  <strong>Name:</strong>
  <%= @survey.name %>
</p>

<ol>
  <% for question in @survey.questions %>
  <li><%= question.content %></li>
  <% end %>
</ol>

<%= link_to 'Edit', edit_survey_path(@survey) %> |
<%= link_to "Destroy", @survey, :confirm => 'Are you sure?', :method => :delete %> |
<%= link_to 'Back', surveys_path %>

문항 수정

'시청하는 티비 프로그램의 수는 몇편입니까?'을 '시청하는 서울방송 프로그램의 수는 몇편입니까?'로 수정

설문조사의 비어있는 문항 삭제

기존의 문항을 삭제하지 못합니다. 설문조사를 새로 만들 때 비어있는 문항을 제외합니다.

/app/models/survey.rb

class Survey < ActiveRecord::Base
  has_many :questions, :dependent => :destroy
  accepts_nested_attributes_for :questions, reject_if: proc { |a| a['content'].blank? }
end

삭제 필드 추가

/app/views/survey/_form.html.erb

<div class="field">
<%= f.fields_for :questions do |builder| %>
<p>
  <%= builder.label :content, "Question" %><br />
  <%= builder.text_area :content, :rows => 3 %>
  <%= builder.check_box :_destroy %>
  <%= builder.label :_destroy, "Remove Question" %>
</p>
<% end %>
</div>

/app/models/survey.rb

class Survey < ActiveRecord::Base
  has_many :questions, :dependent => :destroy
  accepts_nested_attributes_for :questions, reject_if: proc { |a| a['content'].blank? }
end

/app/controllers/surveys_controller.rb

def survey_params
  params.require(:survey).permit(:name, questions_attributes: [:id, :content, :_destroy])
end

문항의 선택지 추가

선택지(answer) 모델 생성

rails g model answer content:string question:references
rake db:migrate

question 모델 수정

설문조사(survey)에 문항(question)을 추가했듯이 문항(question)에 달릴 선택지(answer)에 대해 question 모델 수정

/app/models/question.rb

class Question < ActiveRecord::Base
  belongs_to :survey
  has_many :answers, :dependent => :destroy
  accepts_nested_attributes_for :answers, reject_if: proc { |a| a['content'].blank? }, allow_destroy: true
end

survey 입력 폼 뷰에서 question 부분을 파샬로 떼어냅니다.

/app/views/surveys/_question_fields.html.erb 파일을 새로 만듭니다.

<p>
  <%= f.label :content, "Question" %><br />
  <%= f.text_area :content, rows: 3 %><br />
  <%= f.check_box :_destroy %>
  <%= f.label :_destroy, "Remove Question" %>
</p>

/app/views/surveys/_form.html.erb

<div class="field">
  <%= f.label :name %><br>
  <%= f.text_field :name %>
</div>
<div class="field">
<%= f.fields_for :questions do |builder| %>
  <%= render 'question_fields', f: builder %>
<% end %>
</div>

선택지(answer)에 대해서도 파샬을 만듭니다.

/app/views/surveys/_answer_fields.html.erb 파일을 새로 만듭니다.

<p>
  <%= f.label :content, "Answer" %>
  <%= f.text_field :content %>
  <%= f.check_box :_destroy %>
  <%= f.label :_destroy, "Remove" %>
</p>

/app/views/surveys/_question_fields.html.erb

<p>
  <%= f.label :content, "Question" %><br />
  <%= f.text_area :content, rows: 3 %><br />
  <%= f.check_box :_destroy %>
  <%= f.label :_destroy, "Remove Question" %>
</p>
<%= f.fields_for :answers do |builder| %>
  <%= render 'answer_fields', f: builder %>
<% end %>

콘트롤러에서 선택지(answer)를 문항(question)마다 비어있는 객체를 생성합니다.

/app/controllers/surveys_controller.rb

# GET /surveys/new
def new
  @survey = Survey.new
  3.times do
    question = @survey.questions.build
    4.times { question.answers.build }
  end
end
...
def survey_params
  params.require(:survey).permit(:name,
    questions_attributes: [
      :id, :content, :_destroy,
      answers_attributes: [
        :id, :content, :_destroy
      ]
    ]
  )
end

데이타 입력

제목: 사이트 만족도 조사

문항: 최근에 레일스를 사용해본 적이 있습니까?

선택지:

자주

가끔

글쎄요

전혀 사용하지 않아요

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment