質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Q&A

解決済

3回答

4118閲覧

Railsにて、セレクトボックスで制限時間を選び、DBに収め、現在の時刻と比較したい

tm_rhcp

総合スコア17

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

1グッド

1クリップ

投稿2016/01/15 15:36

###前提・実現したいこと
Rails4系にて、投票受付時間をセレクトボックスで選択できる、選択肢型のアンケート機能を作ろうとしています。
投票受付時間を超えていたら回答出来なくなる、という想定です。

###発生している問題
アンケート機能自体はひと通り出来たのですが、各アンケート作成時に制限時間を設定する部分でつまづいています。
form_forで回しているフォームの中でアンケートのタイトル、詳細、選択肢を入力する欄が有り、その中に制限時間を選択するセレクトボックスを置きました。

制限時間の選択肢として、アンケートを作成した時間から30分後、1時間後、3時間後など、最長で24時間後まで選べるものにしたいです。

1.hours.from_nowなど、相対的な時間がとれるメソッドがあるのは見つけたのですが、今回の場合これをどの部分に置けば良いのか(view? controller?)、もしくは、他に良い方法があるのか、アドバイスを頂きたいです。
よろしくお願いします。

また、上記問題をクリアしたあとについてなのですが、制限時間を過ぎたかどうかは、DBに収めた制限時間の時刻と現在時間の比較は不等号機能でシンプルに調べられそうだなぁと見ていますが、もし違っていたらアドバイス頂ければと思います。
よろしくお願いしますm(_ _)m

###補足情報

  • Rails 4.2.5で作成しています。
  • 現在DBはSQLite3を使用していますが、公開時は別なDBを使う予定です。
  • 制限時間を選んだらDBに現在時刻+制限時間の日時がtime型で収まるのかなと考え、time型のカラムを用意しています。
  • WebPackにてES6も導入しています。
dddd_gond👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

アンケート(下のサンプルではParent)の制限時間用の変数(limit)に分単位で制限時間を持たせておき、作成時間としてcreated_atを使えばできそうです。これで投票(Child)の登録時にpassed_limit?で制限時間を超えていないかバリデーションをかければどうでしょうか。

ruby

1class Parent < ActiveRecord::Base 2 has_many :children 3end

ruby

1class Child < ActiveRecord::Base 2 belongs_to :parent 3 validates :parent, presence: true, if: :passed_limit? 4 5 private 6 7 def passed_limit? 8 if self.parent.created_at+(self.parent.limit*60) < Time.now 9 errors.add(:parent, "Exceeded the time limit") 10 end 11 end 12end

投稿2016/01/16 00:49

編集2016/01/16 00:50
jinco

総合スコア432

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tm_rhcp

2016/01/18 16:14

「passed_limit?」の部分、まだ盛り込めていないですが使わせていただきますー! ありがとうございました!
guest

0

時刻の演算

Time は 秒単位で 足し算、引き算ができます。
↓では now という変数の 30 分後を now_after_30_min という変数に設定しています。
そして now_after_30_min と now の差が 1800 秒(30分) であることを計算しています。

1] pry(main)> now = Time.now => 2016-01-16 08:49:21 +0900 [2] pry(main)> after_30_min = now + 30 * 60 => 2016-01-16 09:19:21 +0900 [3] pry(main)> puts after_30_min - now 1800.0 => nil

時刻の範囲で DB を検索する

時刻の範囲を絞って検索ができます。
Model.where(col: form..to)

時間が保持されている col が from .. to の間にあるものを検索する)

時刻を扱う際は timezone について注意が必要です。
↓の例では DB には時間が UTC で入っています。
getlocal メソッドをつかって DB の時間の日本語時間を確認しています。
local メソッドをつかって適切な時間指定のSQLが発行されるようにしています。
(Rails での時間の扱いについては TimeWithZone クラスを参照してください)

[1] pry(main)> Team.all.each{|t| puts t.created_at.getlocal} Team Load (5.8ms) SELECT "teams".* FROM "teams" ORDER BY "teams"."name" ASC 2016-01-10 07:34:42 +0900 2016-01-16 08:03:35 +0900 +----+--------+-----------------+-------------------------+-------------------------+ | id | name | description | created_at | updated_at | +----+--------+-----------------+-------------------------+-------------------------+ | 1 | Team A | In China | 2016-01-09 22:34:42 UTC | 2016-01-09 22:34:42 UTC | | 2 | Team B | In Tokyo, japan | 2016-01-15 23:03:35 UTC | 2016-01-15 23:03:40 UTC | +----+--------+-----------------+-------------------------+-------------------------+ 2 rows in set [2] pry(main)> from = Time.local(2016, 1,10, 7) => 2016-01-10 07:00:00 +0900 [3] pry(main)> to = Time.local(2016, 1,10, 8) => 2016-01-10 08:00:00 +0900 [4] pry(main)> Team.where(created_at: from..to) Team Load (0.3ms) SELECT "teams".* FROM "teams" WHERE ("teams"."created_at" BETWEEN '2016-01-09 22:00:00.000000' AND '2016-01-09 23:00:00.000000') ORDER BY "teams"."name" ASC +----+--------+-------------+-------------------------+-------------------------+ | id | name | description | created_at | updated_at | +----+--------+-------------+-------------------------+-------------------------+ | 1 | Team A | In China | 2016-01-09 22:34:42 UTC | 2016-01-09 22:34:42 UTC | +----+--------+-------------+-------------------------+-------------------------+ 1 row in set

投稿2016/01/16 00:08

katoy

総合スコア22324

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tm_rhcp

2016/01/18 16:16

アドバイス頂きましてありがとうございました! 時間に足し算引き算できるのはまだ知りませんでした…。 TimeWithZoneクラスについても参考にさせていただきます!
guest

0

自己解決

katoyさん、jincoさんアドバイスを頂きありがとうございました。
教えていただいた事を参考にしつつ、ここまで作って来たものとを照らし合わせて下記のようにして解決しました。
ちょっと泥臭い気もするんですが、動いているのは間違いないので共有致します。

まず、投票受付日時のカラム(limit)をtime型ではなく、text型に変更しました。

view部分は下記のようにしました。
セレクトボックスにはただの文字列が入るようになっています。

Ruby

1# view 2<%= form.label :limit, '期限' %> 3<%= form.select :limit, options_for_select(%w(15分 30分 1時間 3時間 6時間 12時間 24時間)) %>

そして、選択された文字列を受け取るmodelの方で、
下記のようにコールバックを使い、セーブ直前で時間の形式に変更しました。

Ruby

1# model 2before_save :limit_to_time 3 4private 5def limit_to_time 6 if self.limit == '15分' 7 self.limit = Time.current.since(15.minute) 8 elsif self.limit == '30分' 9 self.limit = Time.current.since(30.minute) 10 elsif self.limit == '1時間' 11 self.limit = Time.current.since(1.hours) 12 elsif self.limit == '3時間' 13 self.limit = Time.current.since(3.hours) 14 elsif self.limit == '6時間' 15 self.limit = Time.current.since(6.hours) 16 elsif self.limit == '12時間' 17 self.limit = Time.current.since(12.hours) 18 elsif self.limit == '24時間' 19 self.limit = Time.current.since(24.hours) 20 end 21 puts self.limit 22end

そしてコントローラの方には、投票受付時間を超えていたら投票画面ではなく投票結果画面にリダイレクトするように仕掛けました。

Ruby

1# controller 2def show 3 redirect_to result_path, notice: '投票は締め切りました' if @poll.limit < Time.current 4end

jincoさんから頂いたアドバイス(:passed_limit?)も必要なのでそちらはこれから取り込ませて頂きますー!

投稿2016/01/18 16:52

tm_rhcp

総合スコア17

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問