【Rails】날짜・기간을 지정한 투고를 톱 페이지에 자동적으로 표시한다

개인 개발 웹 앱 "마치카도 루트"을 곧 v5.0 정식 버전으로 버전 업합니다.

그 v5.0 정식판에 맞추어 현재 v5.0rc1로 테스트 중인 것이, 투고에 미리 일자・기간을 지정해 두고, 그 일자・기간이 오면 톱 페이지에 자동적으로 표시되는 기능입니다.

프로그래밍에 입문해 7개월 미만. 처음 도전이었기 때문에 메모로 남깁니다.

데이터베이스



먼저 기간의 시작일start_on과 종료일end_on이라는 열을 Posts 테이블에 만듭니다.
$ rails g migration AddStartToPosts start_on:date
$ rails g migration AddEndToPosts end_on:date
$ rails db:migrate

두 열 모두 date 형식으로 둡니다.

입력 양식



new.html.erb
期間の開始日
<%= date_field_tag 'post[start_on]', nil %>
期間の終了日
<%= date_field_tag 'post[end_on]', nil %>
date_field_tag 를 사용하면 아래 사진과 같이 캘린더 형식으로 날짜를 지정할 수 있으므로 편리합니다.



controller



밸리데이션



시작 및 종료 날짜가 올바르게 지정되었는지 확인하는 유효성 검사는 모델이 아닌 controller에서 수행됩니다.

posts_controller.rb
def create
(中略)

sabun = (@post.start_on - Date.today).to_i
unless sabun >= 1
  flash[:error] = "開始日は明日以降で!"
  render 'new'
  return
end

sabun = (@post.end_on - @post.start_on).to_i
unless sabun <= 10
  flash[:error] = "期間は最長10日間まで!"
  render 'new'
  return
end
unless sabun >= 0
  flash[:error] = "終了日は開始日以降で!"
  render 'new'
  return
end

(中略)
end

시작일은 내일 이후이므로 위와 같이 오늘Date.today과의 날짜의 차이sabun를 1일 이상으로 하도록 검증하고 있습니다.

그 밖에도, 지정 기간을 최장 10일간으로 하기 때문에 차분을 10일 이하로 하거나, 종료일은 개시일 이후로 하기 위해서 차분을 0 이상으로 되어 있습니다.

지정된 기간에 일치하는 게시물을 DB에서 검색



posts_controller.rb
def index
(中略)

special_post_ids = Post.where.not(start_on: nil).pluck(:id)
@special_posts = Post.where(id: special_post_ids).where('start_on <= ?', Date.today).where('end_on >= ?', Date.today)

(中略)
end

톱 페이지의 view인 index에 투고의 데이터를 넘기기 위해, controller로 위의 처리를 실시합니다.

먼저 모든 게시물 중에서 기간이 지정된 게시물만 id를 추출하여special_post_ids에 저장합니다.

계속해서, 그 id를 기초로 개시일 start_on 과 종료일 end_on 의 기간내에 매치하는 투고 데이터를 검색해 @special_posts 에 격납한다, 라고 하는 흐름입니다.

특히 where('start_on <= ?', Date.today) 라는 검색 방법을 사용한 적이 없었기 때문에 고생했습니다. Date.today 라고 하는 서식을 사용하면 거기에 오늘의 일자가 자동적으로 대입되어 start_onend_on와의 일자를 비교하면서 DB로부터 찾아 주는군요. 매우 편리합니다.

톱 페이지



index.html.erb
<%= render partial: 'special_posts', collection: @special_posts, as: :post %>

톱 페이지의 view인 index.html.erb 에는 위의 코드를 썼습니다. 지정된 기간이 일치하는 게시 데이터 @special_posts를 부분 템플릿 special_posts에 표시합니다.

그건 그렇고, @special_posts에 저장된 모든 데이터를 반복적으로 렌더링하기 위해 collection를 사용합니다. each do 보다 N+1 문제에 대응할 수 있다고 합니다.

_special_posts.html.erb
タイトル
  <%= post.title %>
本文
  <%= post.body %>
期間開始日
  <%= post.start_on %>
期間終了日
  <%= post.end_on %>

후기



이상이 대근의 흐름이 됩니다. 이렇게 써 버리면 간단하게 생각됩니다만, 지분에 있어서는 어려웠습니다. 아직 미숙하네요. 앞으로도 필요에 따라 배워 갑니다.

좋은 웹페이지 즐겨찾기