まりぴよこのブログ

日々の日記。技術ネタでまとまりきってないものの記録、伝わる文章の書き方を練習とか。

コピーアプリ 1 : ヤフオク!のまとめ

2個目のコピーアプリ実装完了。 今回は目標の12時間を下回って、11時間で実装出来た!

コピーした機能リスト

ログインすると使える機能

  • ユーザーはログインできる
  • ログインユーザーはオークションを作成できる
  • ログインユーザーはオークションに参加できる(入札)
  • オークション終了日に最高額の入札者は落札できる
  • 落札者は出品者を評価できる

ログインしなくても使える機能

  • 全オークションを閲覧できる
  • 出品者の過去の評価(コメント)を閲覧できる

前回からの改善点

前回のモデリングで苦戦(大幅手戻り発生)したので、今回はちょっと慎重にモデリングしてみた。

以下をコーディング前に意識して取り組んだ。

  • データモデリングに対する考え方(Railsに限らず)な参考資料を見れたので、その手順に従ってちゃんと図を書いた
  • モデル・コントローラーを作る前にroute.rbに欲しいURLの形を書いてみた

ルーティング

わりかし素直なルーティングになったかと思う。

ログインユーザー用のルーティングを namespace :my 以下に置いてみた。

Rails.application.routes.draw do
  devise_for :users
  root 'auctions#index'

  resources :auctions, only: [ :show, :index ] do
    resource :bid, only: [ :new, :create, :destroy ]
  end

  namespace :my do
    resources :products
    resources :auctions
    resources :bids, only: [:index] do
      resource :comment
    end
  end
end

・・・と、今改めて書いてみたら、namespace外に置いたルーティングが、ログインユーザー用のものになってる箇所があった・・

/auctions/bid はログインしてないと使えない。 Singular resource にした理由は、ログインユーザー1人に対して1つのオークションに1回しか入札できないことを表したかったから。

/my/bids の方では、自分が落札した入札を一覧表示してる。(落札商品の評価コメントを付けるための親として使ってる)

・・ちょっと説明無いとわかりづらいかも・・・・(ちゃんと出来たと思ったんだけどな・・)

悩んだ箇所(指定時間に○○を実行)

オークションが終了する時の締め処理的なものが、最初にユーザーがオークション締切日に設定した日に発生させなきゃいけないイベントだったので、どうやって実現するかちょっと悩んだ。

普通だったら、指定日時に実行させるジョブみたいの・・? まだRailsで試したことがなかったので、色々調べてみたところ、Rails4.2以降だとActiveJobとやらを使って、バックグラウンド実行してくれるgem達と連携して実現するっぽい。

・・目標時間の半分くらい経過した頃にこの辺りをどうするか考えだしたので、このままではまた時間が大幅オーバーしてしまう;;

ということで、仕様を単純にして間に合わせる方式にスイッチしてみた。

採用した実装方針

  • 締め処理が必要なオークションがあれば締め処理するメソッドを用意
  • 最初の実装では、オークションに入札できる画面表示時に締め処理メソッドを呼び出してチェック

最後まで終わって、時間が残ればジョブ版に挑戦してみることに。 (結果11時間で終わったので、出来るか出来ないか微妙そうな時間が残ったけど、結局最初の実装でやった方法がさほど悪くないかも!と気に入ってきたので、ジョブ版にスイッチしなかった)

オークション入札画面が表示された時に、締め処理が必要なオークションを探す処理が走るため、 なるべく単純に絞り込めるように、オークションに終了しているかしていないかのフラグを持たせることにした。

オークションの締め処理でハマった箇所

オークション終了日時に関して

何故かモデルのオークション終了日を :date で作ってたらしく、時間が指定出来ない状態になってた

直し(マイグレーションでカラムの修正)

def change
  change_column :auctions, :deadline_date, :datetime
end

タイムゾーンの指定をしてなかった

時間が指定出来るようになったら、やっと気づいた・・ 普通に9時間ズレてた;;

日時関係で悩むと何度か見てるページ。

qiita.com

オークション終了日時の値にオークションの終了状態を追従させたい

モデルのコールバックを初めて使ってみた。

メソッド名・・長っ・・

class Auction < ActiveRecord::Base
  # ...
  before_update :check_deadline_date_and_set_closed_if_needed
  # ...
  def check_deadline_date_and_set_closed_if_needed
    if self.deadline_date < Time.current
      self.closed = true
    else
      self.closed = false if self.can_reopen?
      true # 注意!
    end
  end

  # 既に一度クローズされているオークションを再オープンする場合のチェック
  # 落札がなければ再オープンできる
  def can_reopen?
    self.closed && self.successful_bid.nil?
  end
end

コメントの注意!(↓が怖いので値セット後にtrueを返すようにした)

qiita.com

コード全体

github.com