티스토리 뷰
해당 글은 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 정의가 이루어집니다.
-
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 통신이란? [클릭]
-
초반에 많이할 수 있는 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) 글을 써봅니다.
분명 저는 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
'프로그래밍 공부 > Ruby on Rails : 이론' 카테고리의 다른 글
Ruby on Rails : Active Storage (5) | 2019.11.01 |
---|---|
Ruby on Rails : turbolink는 jQuery를 싫어한다. (0) | 2019.11.01 |
Ruby on Rails : 최소한의 bundle update (conservative 옵션) (0) | 2019.11.01 |
Ruby on Rails : Gem 개념 (0) | 2019.11.01 |
Ruby on Rails : 환경(Environment) (2) | 2019.11.01 |