Rails - Scaffold

uglyduck.dev·2022년 3월 26일
0

개념 모아 🗂

목록 보기
38/40

scaffold 기초

정의

  • Rails에서 제공하는 CRUD 구현 명령어 방식
  • 뼈대, 기반이라는 뜻을 가지고 있으며, 이 뜻에 걸맞게 CRUD와 더불어 CRUD와 연관된 기본 기능들을 갖춘 프로젝트의 뼈대를 만들어 줌
  • 기존에 작성했던 CRUD 코드보다 더 다양한 기능을 사용할 수 있는 코드를 완성할 수 있음

scaffold 실행하기

rails new scaffold_app
cd scaffold_app
rails g scaffold Post title:string content:text
rake db:migrate
  • scaffold는 모델을 생성하는 명령어와 다르게 CRUD 기능을 하는 view와, controller, routes도 자동 생성하는 점에서 차이가 있음

config/routes.rb

Rails.application.routes.draw do
  root "posts#index"
  resources :posts
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end

scaffold 이해하기1: RESTful과 resources

scaffold 자동 생성

  • rails g scaffold Post title:string content:text 와 같은 명령어를 실행하면 해당하는 파일을 자동 생성해주며 명령어 하나로 active_record, 경로, 컨트롤러, 뷰파일, helper, jbuilder, assets 등이 자동으로 생성됨

active_record

  • scaffold로 인해 생성한 Post 모델에 관한 부분

resource_route

  • /config/routes.rb 파일에 추가된 경로

scaffold_controller

  • scaffold controller 파일

erb

  • 생성되는 뷰 파일들

jbuilder

  • html 형태가 아닌 json 형태로 출력하기 위한 부분

assets

  • scaffold에 필요한 scss나 script 요소들

이와 같이 Model, Controller, View 뿐만 아니라 디자인 요소까지 함께 만들어짐

config/routes.rb

Rails.application.routes.draw do
  root "posts#index"
  resources :posts
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end
  • resources :posts코드로 8개의 주소가 설정됨.
  • resources 메서드는 RESTful한 라우트를 생성
  • REST
    • Representational State Transfer의 약어로 주소(리소스)와 HTTP 메서드를 통해 그 동작의 의미를 표현하는 방법
    • HTTP 메서드의 조합으로 리소스를 어떻게 할 지 표현하는 방법

리소스의 제약조건

  1. 리소스는 동사를 사용하지 않고 명사로 작성
    • 행위를 표현하지 않고 행위의 주체, 즉 자원만 표현
    • 행위 부분은 HTTP 메서드로 대신
  2. 리소스는 콜렉션과 도큐멘트로 이루어짐
    • 콜렉션을 표현할 땐 복수형으로, 도큐먼트를 표현할 땐 단수형 또는 콜렉션 뒤에 id 값을 입력하여 표현

scaffold 이해하기2: controller

app/controllers/posts_controller.rb

class PostsController < ApplicationController
  before_action :set_post, only: [:show, :edit, :update, :destroy]

	[...]

  # GET /posts/1
  # GET /posts/1.json
  def show
  end
	
	[...]
	
  private
    # Use callbacks to share common setup or constraints between actions.
    def set_post
      @post = Post.find(params[:id])
    end
	
	[...]
end

before_action

  • 최상단의 before_action :set_post, only: [:show, :edit, :update, :destroy] 부분을 통해 filter 메서드인 것을 예상할 수 있음
  • filter method
    • 특정 메서드를 액션 직전(before), 직후(after) 또는 모두(arround)에 실행시키는 메서드
  • 액션 직전에 :set_post 실행
  • :set_post 선언부
private
# Use callbacks to share common setup or constraints between actions.
def set_post
	@post = Post.find(params[:id])
end
  • 라우트 파라미터를 통해 넘어오는 post의 id 값으로 특정 게시글을 찾아주는 역할 수행
  • Rails의 controller에서 메소드를 만들면 action method로 생성
  • action method는 액션의 이름과 동일하게 자동 생성된 view와 연결
  • view와 연결을 원하지 않을 경우 최상단 블럭에 private 혹은 protected 선언

only: [:show, :edit, :update, :destroy]

before_action :set_post, only: [:show, :edit, :update, :destroy]
after_action :set_post
before_action :set_post, except: [:show, :edit, :update, :destroy]
  • 지정한 action에서만 before_filter를 설정
  • only 설정이 없으면 모든 action에서 filter 적용, except는 지정한 action 이외에 filter 적용

respond_to

def create
	@post = Post.new(post_params)

	respond_to do |format|
		if @post.save
			format.html { redirect_to @post, notice: 'Post was successfully created.' }
			format.json { render :show, status: :created, location: @post }
		else
			format.html { render :new }
			format.json { render json: @post.errors, status: :unprocessable_entity }
		end
	end
end
  • 서버에서 응답의 종류를 분기하고 싶을 때 사용
  • respond_to do | format | 내부 블록에서 format.type 형식으로 원하는 형식 지정

Strong Parameter

def create
	@post = Post.new(post_params)
	
	[...]
end

[...]

def post_params
	params.require(:post).permit(:title, :content)
end
  • params.require(:post).permit(:title, :content)
    • 화이트리스트 방식으로 보안을 설정하는 코드
    • 모델 코드에서 사용자가 입력 가능한 속성을 명시
    • 사용자의 레벨 등 보안 이슈로 인해 입력하면 안 되는 정보들이 클라이언트 측에서 넘어오더라도 컨트롤러에서 그 속성을 명시하지 않았기 때문에 모델의 해당 컬럼은 변경되지 않음
  • 설정 방법
    1. params.require(:모델명)으로 먼저 필터링할 모델 설정
    2. .permit(:허용할 컬럼 리스트)들을 작성
  • 동작 방식
    1. 서버가 파라미터를 전달 받은 이후 params.require(:post).permit(:title, :content) 코드로 인해 전달 받은 파라미터 형식

    2. {title: "안녕", content: "하세요"}로 변경

    3. create action에서 아래와 같이 동작

      def create
          @post = Post.new(title: "안녕", content: "하세요")
          
          [...]
      end

scaffold 이해하기3: view

render

app/views/posts/new.html.erb

    <h1>New Post</h1>
    
    <%= render 'form', post: @post %>
    
    <%= link_to 'Back', posts_path %>
    ```
    

app/views/posts/edit.html.erb

    <h1>Editing Post</h1>
    
    <%= render 'form', post: @post %>
    
    <%= link_to 'Show', @post %> |
    <%= link_to 'Back', posts_path %>
    ```
    
    - `<=% render 'form', post: @post %>`는 뷰 헬퍼 코드로, 뷰에서 반복되는 부분이 존재할 때 반복되는 부분을 재사용하기 위해 사용
    - 반복되는 부분을 조각 템플릿(partial)로 만든 뒤 이를 메인 템플릿에서 호출하는 방식을 사용
    - prefix → '_'
    - 조각 템플릿 호출 → render 메서드 사용
    `<%= render "조각 파일명" %>`
    - 조각 파일 호출 및 변수 전달
    `<%= render "form", post: @post %>`와 같이 작성
        - post라는 변수에 @post의 값을 담아 _form 조각 파일에 전달
  • link_to는 a tag의 뷰 헬퍼
  • <%= link_to 'Back', posts_path %>
  • <a href="/posts">Back</a>
    • Back a tag 감싸질 요소
    • posts_path 클릭 시 이동하는 주소
  • Rails는 route에서 생성한 주소를 메서드화 하는데 사용 → 라우트 헬퍼

💡 라우트 헬퍼 확인하는 법

  • [Terminal]로 확인하기
    1. rake routes 명령어 실행
    2. Prefix 데이터 → 라우트 헬퍼 확인
    3. Rails에서 사용하고 싶다면 끝에 _path 붙여 사용
  • [브라우저]로 확인
    1. 주소/rails/info/routes로 접속

app/views/posts/index.html.erb

   <% @posts.each do |post| %>
   	<tr>
   		<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 %>

<td><%= link_to 'Show', post %></td>

  • post
    • link_to 메서드에 모델 객체를 그대로 사용하면, Rails는 코드를 작성했다는 가정을 하고 그 모델의 특정 데이터를 바라보는 멤버 주소를 호출
    • /posts/:id 주소로 이동

<td><%= link_to 'Edit', edit_post_path(post) %></td>

  • edit_post_path(post)는 edit_post_path에서 :id 라우트 파라미터르 받아옴
  • edit_post_path(post.id)로 작성 가능

form_with

  • form의 뷰헬퍼
    app/views/posts/_form.html.erb
    <%= form_with(model: post, local: true) do |form| %>
      <% if post.errors.any? %>
        <div id="error_explanation">
          <h2><%= pluralize(post.errors.count, "error") %> prohibited this post from being saved:</h2>
    
          <ul>
          <% post.errors.full_messages.each do |message| %>
            <li><%= message %></li>
          <% end %>
          </ul>
        </div>
      <% end %>
    
      <div class="field">
        <%= form.label :title %>
        <%= form.text_field :title %>
      </div>
    
      <div class="field">
        <%= form.label :content %>
        <%= form.text_area :content %>
      </div>
    
      <div class="actions">
        <%= form.submit %>
      </div>
    <% end %>

form_with

  • form_authenticate_token과 같이 Rails에서 form을 사용할 때 필요한 설정을 자동 설정
  • Model 속성에 모델 객체의 값으로 action과 method를 설정

form_with(model: post, local: true)

  • form 요소인 action과 method를 설정
  • post는 new 액션 → Post.new, edit 액션 → Post.find(params[:id])

Reference

profile
시행착오, 문제해결 그 어디 즈음에.

0개의 댓글