Bucket Place/Ruby on Rails

[Ruby on Rails] form_for() Helper

Cloud Travel 2014. 5. 1. 15:05

  시작하며... 

 

 지금까지 Rails를 프로젝트를 진행하면서 데이터를 입력하는 Form이 자동으로 생성되었던 모습을 볼 수 있다. 예를들어 scaffold를 이용하여 데이터베이스를 하나 추가하면, 추가된 테이블에 대해서 데이터를 입력하는 부분이 자동으로 생성되는 것을 볼 수 있을 것이다.

 

 예를 들어, rails generate scaffold friend name:string phone:string introduce:text 라는 것으로 데이터베이스를 하나 생성을 해주면 "http://localhost:3000/friends/new" 페이지에 새로운 친구를 추가할 때 사용하는 form이 자동으로 생성되는 것을 볼 수 있다. 물론, 링크를 들어가기전에 rake db:migrate를 실행하는 것을 잊지말자!


 오늘은 이 form을 뜯어보면서 어떻게 돌아가는지를 한번 알아볼려고 한다.



  form을 구성하는 정체는 무엇인가?


 자. 이제 위에 명령어를 작성했다고 생각하고 다음을 진행하겠다. new에서 사용하는 form은 대체 어딛는 것일가? 이를 알기 위해서 처음으로는  app/views/friend/new.html.erb 파일을 열어보자.

 

 파일을 열어보면 눈에 익숙한 문구가 보인다.  <%= render 'form' %> 이전 글에 partial template에 대해서 알아보았다. new에서 사용하기 위한 form은 미리 정의된 템플릿을 가져다 사용하는 것을 알 수 있다. 테이블과 관련 없는 템플릿은 같은 폴더의  _[NAME] 에 존재하며, 위와 같이  <%= render '[NAME] %> 형식으로 가져와 사용을 한다.


 이 사실을 통해  app/views/friend/_form.html.erb 에 form 의 정체가 나타날 것이라고 기대가 된다. 파일을 열어보자.

<%= form_for(@friend) do |f| %>
  <% if @friend.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@friend.errors.count, "error") %> prohibited this friend from being saved:</h2>

      <ul>
      <% @friend.errors.full_messages.each do |msg| %>
        <li><%= msg %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= f.label :name %><br>
    <%= f.text_field :name %>
  </div>
  <div class="field">
    <%= f.label :phone %><br>
    <%= f.text_field :phone %>
  </div>
  <div class="field">
    <%= f.label :intorduce %><br>
    <%= f.text_area :intorduce %>
  </div>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

 에러 처리와 css를 위해서 div를 여러개 사용한 것을 볼 수 있다. 이 것을 간단하게 변형시켜 보겠다. 쓸데없는 에러처리를 지우고 form만 보기좋게 바꿔보면 다음과 같다.

<%= form_for(@friend) do |f| %>
  <p>
    <%= f.label :name %>
    <%= f.text_field :name %>
  </p>
  <p>
    <%= f.label :phone %>
    <%= f.text_field :phone %>
  </p>
  <p>
    <%= f.label :intorduce %><br />
    <%= f.text_area :intorduce %>
  <p>
    <%= f.submit %>
  </p>
<% end %>

 이제 눈에 form을 형성하는 부분이 보일 것이다. form을 형성해주는 것은 form_for() helper였다. 그렇다면 이 helper에 대해서 알아보자. 



  form_for() helper


 일단은 form_for() helper의 첫 정의 부분을 알아보자.

 

  <%= form_for([TABLE]) do |f| %> 형식이라는 것을 알 수 있다. @friend가 컨트롤러에서 새로운 테이블 클래스를 객체화 한 것이라는 것을 보면 알 수 있을 것이다. 여기서 가져온 Table의 형식과 아래 체워지는 form의 형식은 같아야 할 필요가 있다. 왜냐하면, 이 form이 서버로 전송될때 해당 테이블에 넣으려고 시도를 할 것 이기 때문이다.


 즉, f.text_field :name에서의 name이 friend 테이블에 존재하는 Attribute이어야 한다는 것이다. 이는 매우 중요하다. 이를 안지켜주고 다른 이름을 지정하게 되면 전송이 실패되기 때문이다.



  마치며...


 간단하게 form_for() 에대해서 파해쳐보았는데... 먼가 사용은 할 수 있겠는데 의문점도 있다. 여러 테이블에 대한 데이터를 한번의 폼에 입력하여 전송하는 법은 없을까? 라는 궁금증도 들었다. 일단, form_for() helper 하나의 테이블에 대해서 데이터를 입력시키는 강력한 존재로 보인다.