내가 한 노력들

[ Ruby On Rails ] CRUD 구현하기 (Create) 본문

IT 공부/Ruby On Rails

[ Ruby On Rails ] CRUD 구현하기 (Create)

JONGI-N CHOI 2021. 9. 8. 03:51

DB설정

우선 CRUD를 구현하기 위해서 필요한 것이 DB입니다. 

 

Ruby On Rails 환경설정할 때, 

gem install sqlite3

명령어를 통해서 sqlite3 DB를 설치를 한 적이 있는데

 

Gemfile을 확인해보면 

gem 'sqlite3', '~> 1.4'

파일에 추가되어있는 것을 볼 수 있습니다.

 

 

rails-db

하지만, DB를 시각적으로 보고 관리하기 위해서 필요한 것이 있습니다. 

rails-db를 설치해야 하는데 

https://rubygems.org/ 싸이트에서 

rails-db를 검색하여 우측에 보이는 GEMFILE에 있는 코드를 복사합니다. 

 

 

복사한 코드를 gemfile에 추가해줍니다.

gem 'rails_db', '~> 2.4', '>= 2.4.1'

 

빌드

bundle install

방금 gemfile에 추가한 rails_db 라이브러리를 우리의 rails 프로젝트에 추가해서 사용하기 위해서는 빌드작업이 필요합니다. 

 

위의 명령어를 입력하면, 자동적으로 빌드작업을 해줍니다. 

 

 

 

그러면, 이젠 DB를 시각적으로 어떻게 확인하는지?! Rails 서버의 기본 로컬주소에 /rails/db를 붙히면 된다.

localhost:3000/rails/db

그럼 메인 화면에서 테이블도 선택할 수 있고 

 

테이블의 상세내용도 시각적으로 쉽게 관리할 수 있습니다. 

 


테이블 생성

MVC구조에서 M인 model이 DB와의 접근을 담당하고 있기 때문에, 새로운 model을 생성해야 한다.

rails g model posts

 

위의 명령어를 실행하면, model폴더에 새롭게 post라는 파일과, db의 migration 폴더에 posts라는 파일이 생김

 

 

migration/posts.rb

class CreatePosts < ActiveRecord::Migration[6.1]
  def change
    create_table :posts do |t|
      t.string :title
      t.text :description
      t.timestamps
    end
  end
end

위의 코드는 새로운 테이블을 만들고, 그 테이블의 속성을 선언을 해줍니다, 

title이라는 속성명으로 타입은 string 

description이라는 속성명으로 타입은 text

timestamps는 created_at과 updated_at 속성을 자동적으로 생성을 해줍니다. 

 

 

그러면, 선언한 테이블을 실제로 DB에 적용하기 위해서는 

rake db:migrate

위의 명령어를 실행합니다.

 


CRUD - C(create)

 

Form생성

이젠 사용자의 입력값을 받아서 DB에 저장하는 CRUD에서 C(create)를 구현하기 위한 Form이 필요합니다.

 

 

routes.rb

get "/home" => "blog#index"

URL이 "/home"일 경우에 blog controller의 index 함수를 실행한다. 

 

 

blog_controller.rb

class BlogController < ApplicationController
    def index    
    end
 end

 

views/blog/index.erb

<%= form_tag "/create", method: :post do %>
    <label for="title">제목</label>
    <input type="text" name="title" /><br />
    <label for="description">내용</label>
    <input type="text" name="description" />
    <button type="submit">제출</button>
<% end %>

 

조금 낯선 문법인데, 위는 rails에서 제공하는 폼헬퍼를 이용하여 form태그를 만든 것 입니다,

 

왜? 이렇게 만들었는지는 rails 6버전 부터는 CSRF공격을 막기위해서 Authenticity Token라는 것을 사용합니다. 

사용자가 GET 이외의 PUT / POST / DELETE (내용을 수정할 수있는 메소드) 요청을 하면 사용자가 제출하는 form의 숨겨진 필드에도 authenticity_token이 저장됩니다.

서버는 액션을 실행하기 전에 폼 안의 authenticity_token과 세션에 저장된 authenticity_token를 비교해서 유효성을 검증합니다. 두 토큰이 같지 않으면 요청을 실행하지 않습니다.

 

그래서, authenticity_token을 지정해줘야 하는데, 위의 폼헬퍼를 사용하면, 자동적으로 만들어주는 것이고 위의 방법 말고도 다양한 방법이 존재합니다. 

 

참고문헌 : https://haereeroo.tistory.com/2

 

 

 

그럼 "/home" URL로 접속하면, 제목과 내용을 입력할 수 있는 폼이 정상적으로 만들어진 것을 확인 할 수 있습니다. 

 

 

DB에 저장

 

위의 폼태그를 보면, 제출하게 될 때 "/create"로 전송하는 것을 볼 수 있습니다.

 

routes.rb

post "/create" => "blog#create"

"/create"일 경우에는 blog controller의 create 함수를 실행 

 

controllers/blog_controller.rb

def create
  post = Post.new
  post.title = params[:title]
  post.description = params[:description]
  post.save

  redirect_to '/home'
end

post = Post.new 는 post 모델의 인스턴스를 하나 생성을 합니다.

그리고 post 테이블에서 속성값들인 title값과 description 값을 form태그에서 받아온 값으로 저장을 합니다. 

여기서 form태그에서 보낸 값을 받는 방법으로는 params[:파라미터 이름] 형태로 받아 올 수 있습니다.

 

그리고 마지막으로 "post.save"를 통해서 DB에 실질적으로 저장이 되게 됩니다.

그리고 redirect_to 를 이용하면, 지정한 주소로 브라우저를 refresh 시킬 수 있습니다. 

 

 

그러면, 제목과 내용을 작성하고 제출을 눌러보면 

 

다시 "/home"화면으로 refresh되는 것을 확인할 수 있습니다. 

 

그리고 "rails/db"로 가서 posts테이블을 확인해보면, 방금 작성한 내용이 DB에 저장된 것을 확인할 수 있습니다. 

 

 


form 빌더

<%= form_with model: @article do |form| %>
  <div>
    <%= form.label :title %><br>
    <%= form.text_field :title %>
  </div>

  <div>
    <%= form.label :body %><br>
    <%= form.text_area :body %>
  </div>

  <div>
    <%= form.submit %>
  </div>
<% end %>

 빌더를 사용하여 최소한의 코드를 작성하여 완전히 구성되고 Rails 규칙을 따르는 양식을 출력할 수 있습니다.

 

<form action="/articles" accept-charset="UTF-8" method="post">
  <input type="hidden" name="authenticity_token" value="...">

  <div>
    <label for="article_title">Title</label><br>
    <input type="text" name="article[title]" id="article_title">
  </div>

  <div>
    <label for="article_body">Body</label><br>
    <textarea name="article[body]" id="article_body"></textarea>
  </div>

  <div>
    <input type="submit" name="commit" value="Create Article" data-disable-with="Create Article">
  </div>
</form>

위의 코드를 HTML코드로 변환하면 위와 같은 코드와 같아집니다. 


strong typing

 

form태그를 통해서 받은 data는 params를 통해서 받아올 수 있지만, 이대로 받아오게 된다면 나쁜용도로 악용하고자 하는 사람들에게 이용당할 수 있다.

 

이것을 해결하기 위해서 strong typing이라는 강력한 매개변수를 통해 params를 필터링합니다.

 

  def create
    @article = Article.new(article_params)

    if @article.save
      redirect_to @article
    else
      render :new
    end
  end

  private
    def article_params
      params.require(:article).permit(:title, :body)
    end

article_params를 private로 따로 선언해주어 strong typing 처리를 해줍니다. 

 

 


검증(validate)

Model/Article.rb

class Article < ApplicationRecord
  validates :title, presence: true
  validates :body, presence: true, length: { minimum: 10 }
end

title이라는 속성이 presence: true => 존재하는지 안하는지 확인 

빈칸도 없는 것으로 간주합니다. 

 

그리고, body는 존재하는지를 확인하고 length를 통해서 최소한 10글자 이상이되도록 validate를 합니다. 

 

 

에러메세지

<div>
    <%= form.label :title %><br>
    <%= form.text_field :title %>
    <% @article.errors.full_messages_for(:title).each do |message| %>
      <div><%= message %></div>
    <% end %>
  </div>

  <div>
    <%= form.label :body %><br>
    <%= form.text_area :body %><br>
    <% @article.errors.full_messages_for(:body).each do |message| %>
      <div><%= message %></div>
    <% end %>
  </div>

위의 검증과정에서 만족하지 못하는 속성에 대해서는 따로 에러메세지를 보여주는 것이 가능합니다. 

full_messages_for 메소드는 지정된 속성에 대해 사용자에게 친숙한 오류 메세지 배열을 반환합니다.

해당 속성에 오류가 없으면 배열이 비어있습니다.