티스토리 뷰

프로그래밍 공부/Ruby on Rails : 이론

Ruby on Rails : Scaffold (CRUD 1초컷)

마음 따뜻한 개발자, 나른한 하루 2019. 11. 1. 14:30

해당 글은 https://blog.naver.com/kbs4674/221176581819 로 부터 게시글이 이전되었습니다.

 

과거 MVC 패턴을 배워보고자 노가다 CRUD 게시판 제작법[클릭] 글을 쓰면서 한번 언급을 하긴 했습니다만, 과거에 저술한 방법은 보안에 취약한 단점이 존재합니다.

그 대안으로 떠오른 방법이, 간단한 '1줄의 명령어' 면은 바로 게시판이 만들어지는 'Scaffold' 라는 명령어 입니다.

이번 시간에는 'Scaffold'를 활용하여 게시판을 제작해보겠습니다.

 

 

  • 1초만에 만들어 보는 CRUD

# rails g scaffold [Model이름] [Attributes...]
rails g scaffold post title content:string

레일즈에서는 재밌게도 위 명령어 한 줄 만으로 CRUD를 바로 만들 수 있습니다.

위 명령어를 입력하면 Model, View, Controller가 바로 생성되고, routes.rb에도 자동으로 URI 정의가 이루어집니다.

ㄹㅇ 1초컷

 

 

  • Scaffold 해부학

Scaffold를 쓰면 다양한 변화를 겪을 수 있게 되는데 변화에 대해 한번 살펴보겠습니다.

 

1) routes.rb

Rails.application.routes.draw do	
	resources :posts
end

자동으로 resources가 정의된게 확인이 됩니다.

 참고  resources는 자동으로 Restful API 정의를 해주는 문법입니다. [클릭]

 

2) Controller

더불어 Controller에는 화이트리스트 기능이 있는데, 특정 에트리뷰트 만이 데이터가 기록되는 검증 과정을 거치게 됩니다.

def post_params
	params.require(:post).permit(:title, :content)
end

 

3) View

Render

View 파일 내 코드를 불러오는 기능.

보통 render의 대상은 파일 이름 첫 글자가 _ .

 

 

 

 

 

Render을 쓰는 이유?

  • 코드 분할 (엄청 긴 코드를 줄여줌.) → 가독성 증가
  • 재 사용 (필요하면 언제든 render로 불러오면 그만.)

=> 전공자분들은 어렵다면 C나 자바의 ‘함수’ 기능이랑 얼추 같다고 생각해도 됩니다.

 

 

_form.html.erb

## app/views/posts/_form.html.erb
<%= form_with(model: post, local: true) do |form| %>
  ... (내용 생략)
<% end %>
  • new.html.erb 및 edit.html.erb 파일을 보면 둘 다 공통적으로 _form.html.erb 를 가리키고 있습니다.
  • form_with는 폼 헬퍼의 한 종류로서, 새 글 작성, 글 수정을 알아서 판별해서 기능을 구실합니다. (new, update 기능을 한번에!)
  • 일반적인 폼헬퍼와 공통적으로 CSRF 해킹을 방지해주는 Token이 자동으로 삽입됩니다.

 

json view 자동 지원

Ruby on rails에서는 json 방식으로도 글 열람을 지원합니다.

확인 방법은 주소 끝에 .json을 붙여주면 됩니다.

json viewer

 읽을거리  json 통신이란? [클릭]

 

 

 

  • 초반에 많이할 수 있는 Scaffold 실수 : 에트리뷰트 추가

개발을 하다 보면 간혹 Scaffold에 새로운 에트리뷰트를 추가를 해야하는 상황이 발생할 수 있습니다.

 

상황을 가정해보겠습니다.

1) posts 테이블에는 title과 content 에트리뷰트만 있었는데 새로운 nickname 컬럼이 필요해졌습니다.

2) 그래서 Migrate 파일을 다음과 같이 수정을 했습니다.

class CreatePosts < ActiveRecord::Migration[5.2]
  def change
    create_table :posts do |t|
      t.string :title
      t.text :content
      t.string :nickname

      t.timestamps
    end
  end
end

3) DB를 Drop 하고 Migrate를 합니다.

rake db:drop
rake db:migrate

4)  app/views/posts/_form.html.erb  파일에서 nickname에 대한 input을 추가합니다.

<div class="field">
    <%= form.label :nickname %>
    <%= form.text_field :nickname %>
</div>

5)  app/views/posts/index.html.erb  에 nickname을 보여줄 코드를 추가합니다. (show.html.erb는 생략)

<% @posts.each do |post| %>
    <tr>
        <td><%= post.nickname %></td>
        <td><%= post.title %></td>
        <td><%= post.content %></td>
        <td><%= link_to 'Show', post %></td>
        <td><%= link_to 'Edit', edit_post_path(post) %></td>
        <td><%= link_to 'Destroy', post, method: :delete, data: { confirm: 'Are you sure?' } %></td>
    </tr>
<% end %>

6) 글을 써봅니다.

title, Content는 잘 썼는데 nickname은 데이터가 입력이 안됐다.

분명 저는 nickname에 텍스트를 입력하고, submit을 했음에도 불구하고 실제 테이블 내 데이터에는 기록이 안된게 확인됩니다.

그리고 서버 로그를 살펴보면 데이터는 잘 건너왔는데, Unpermitted parameter: :nickname 로그가 문제 발생에 의심됩니다.

 

이런 문제가 발생하게 된 원인은 바로 Controller에 있습니다.

## app/controllers/posts_controller.rb

def post_params
	params.require(:post).permit(:title, :content)
end

Controller 내 화이트리스트에 nickname 에트리뷰트가 없다보니 DB에 등록이 안된겁니다.

해당 문제에 대해 실수하지 않도록 주의해주세요.

 

 

  • Devise와 연계되는 Scaffold 게시판 제작

 실습 유의사항 

  • 해당 주제는 Devise Gem이 설치되어 있어야 합니다. [Devise Gem 설치법 클릭]
  • 본 설명의 Scaffold 이름은 Post로 하겠습니다.
  • 위 주제와는 전혀 다르게 처음부터 설명을 해나가겠습니다.

1. 다음 명령어를 입력해줍니다. (Post라는 이름의 CRUD가 생성될 겁니다.)

rails g scaffold Post title content:text user:references

 

2.  app/controllers/posts_controller.rb  파일을 열람합니다.

def post_params
  params.require(:post).permit(:title, :content, :user_id)
end

Controller에서 위 코드를

아래와같이 수정해주세요. (코드가 1줄 추가되었습니다.)

def post_params
  params[:post][:user_id] = current_user.id
  params.require(:post).permit(:title, :content, :user_id)
end

글 쓰기(Submit) 를 하고, create 액션으로 넘어가면 Controller 내부에서 자동으로 user_id에 정보가 입력됩니다.

 

params[:post][:user_id] : Post 모델의 user_id 에트리뷰트를 의미하고,

current_user.id : 현재 유저의 정보 중 id 에트리뷰트 정보를 따로 빼옵니다.

 

3.  app/views/posts/_form.html.erb  파일을 열람 후,

<div class="field">
  <%= form.label :user_id %>
  <%= form.number_field :user_id, id: :post_user_id %>
</div>

위 코드를 아예 지워주세요.

 

4. 일단 여기까지 해내고 게시글을 쓰면 user_id가 잘 입력이 되는게 확인이 됩니다.

하지만 제가 최종적으로 원하는건

위 사진과 같이 누가 입력을 했는지 유저 이메일이 보여지는 겁니다.

 

5.  app/models/post.rb  파일을 열람 후 코드를 한번 봐보세요!

class Post < ApplicationRecord
    belongs_to :user
end

위와같이 belongs_to 관계가 이미 정의가 된게 확인됩니다.

이는 저희가 처음에 scaffold를 생성할 때  user:references  라고 정의했기 때문입니다.

 

더불어 저희의 기획에 있어 Post 모델이 가지고 있는 user_id를 통해 이메일 정보를 알아내기 위해선 User 모델을 참고해서 데이터 정보를 가져와야 합니다.

 

 

6.  app/views/index.html.erb  파일을 열람을 하면 보이는 내용 들 중

<% @posts.each do |post| %>
    <tr>
        <td><%= post.title %></td>
        <td><%= post.content %></td>
        <td><%= post.user_id %></td>
        <td><%= link_to 'Show', post %></td>
        <td><%= link_to 'Edit', edit_post_path(post) %></td>
        <td><%= link_to 'Destroy', post, method: :delete, data: { confirm: 'Are you sure?' } %></td>
    </tr>
<% end %>

위 코드에서 user_id를 보여주는 코드가 있습니다.

<td><%= post.user_id %></td>

위 코드를 다음 아래와 같이 수정해주세요.

<td><%= post.user.email %></td>

그럼 이제 Post 모델은 User 모델의 ID값을 참고하고, user_id의 정보 중 email 정보를 가져오게 될겁니다.

 

DB 테이블에서 보면 저희가 만든 scaffold는 위와같은 구조로 되어있습니다.

그런데 User Email정보 대체 뭘 토대로 알았는가 하니, 위 데이터의 User 번호를 쫓아서 User 테이블로 가보면...

 

이렇게 유저 ID에 따른 이메일 계정이 있죠??

어떻게 User의 ID만으로 Email 알아가는가 하니 유저 번호를 추적해서 알아내는 방식이었습니다.

 

 

  • 자료 참고

1. Scaffold 자세한 설명 [클릭]

 

루비온 레일즈 Ruby on Rails ROR

댓글
댓글쓰기 폼
공지사항
Total
156,759
Today
59
Yesterday
130
링크
«   2021/11   »
  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30        
글 보관함