第25回 #p4d 参加した

http://connpass.com/event/2907/

もう25回なのだなあ。。。すごい
前回の続き。ほにゃタルトラッカーの簡易版的なものをRailsで作ってる。お陰様で今回も実り多く、今日書かないと色々忘れそう・・・

便利Gemを入れる

better_errors

エラーの画面がかっこ良くなる
https://github.com/charliesome/better_errors

binding_of_caller

かっこ良くなったエラー画面にフォームが出て、そこからデバッグとかできる(便利〜
https://github.com/banister/binding_of_caller

group :development, :test do
  gem 'better_errors'
  gem 'binding_of_caller'
end

Iteration をどう作るか?

前回作ったthis_iterationメソッド(taskをdoneにした時の週のはじまりとstart_dateと一致するiterationと紐付ける)

app/controllers/tasks_controller.rb

def index
  @this_iteration = Iteration.where(start_date: Time.now.in_time_zone.beginning_of_week.to_date).first

これだと、該当するイテレーションがない場合に例外になってしまう
.first_or_create ってやると「該当するIterationがなかったら作る」ってできるらしい

def index
  @this_iteration = Iteration.where(start_date: Time.now.in_time_zone.beginning_of_week.to_date).first_or_create
Iteration、将来的に、未来1ヶ月分くらいまで必要なので、今日から数えて4週間先の分まで作ることを考える

1週間先のIterationのstart_dateはこう書ける(つまり、今日より1週間後の日が該当する週の月曜日)

i.start_date = Time.now + 1.week.in_time_zone.beginning_of_week.to_date

4週間先のIterationのstart_dateはこうなる

i.start_date = Time.now + 4.week.in_time_zone.beginning_of_week.to_date
未来のIterationまで作れるメソッドをモデルに作っておくとよい

app/models/iteration.rb

def self.for_week(w=0)
  self.where(start_date: (Time.now + w.week).in_time_zone.beginning_of_week.to_date, end_date: (Time.now + w.week).in_time_zone.end_of_week.to_date).first_or_create
end

※ここでいうself は Iteration自身

一行長くて見づらいので改行する

def self.for_week(w=0)
  self.where(start_date: (Time.now + w.week).in_time_zone.beginning_of_week.to_date)
    .where(end_date: (Time.now + w.week).in_time_zone.end_of_week.to_date)
    .first_or_create
end

さらに(Time.now + w.week)で同じ事書いてる!DRYじゃないヽ(`Д´)ノので、変数にまとめるか

def self.for_week(w=0)
  time = Time.now + w.week
  self.where(start_date: time.in_time_zone.beginning_of_week.to_date
    .where(end_date: time.in_time_zone.beginning_of_week.to_date)
    .first_or_create
end

そして、controllerの@this_iteration メソッドでこの for_week を使う
app/controllers/tasks_controller.rb

  @this_iteration = Iteration.for_week

console で for_week が動くかどうかためしてみる

現状存在するIterationの数を確認
irb(main):003:0> Iteration.count
   (0.2ms)  SELECT COUNT(*) FROM "iterations" 
=> 2
Iteration.for_week(1) (つまり来週のIteration)
irb(main):004:0> Iteration.for_week(1)
  Iteration Load (0.1ms)  SELECT "iterations".* FROM "iterations" WHERE "iterations"."start_date" = '2013-07-22' AND "iterations"."end_date" = '2013-07-28' LIMIT 1
   (0.1ms)  begin transaction
  SQL (0.5ms)  INSERT INTO "iterations" ("created_at", "end_date", "start_date", "updated_at") VALUES (?, ?, ?, ?)  [["created_at", Thu, 18 Jul 2013 17:41:03 UTC +00:00], ["end_date", Sun, 28 Jul 2013], ["start_date", Mon, 22 Jul 2013], ["updated_at", Thu, 18 Jul 2013 17:41:03 UTC +00:00]]
   (0.6ms)  commit transaction
=> #<Iteration id: 5, start_date: "2013-07-22", end_date: "2013-07-28", created_at: "2013-07-18 17:41:03", updated_at: "2013-07-18 17:41:03">

07/22〜07/28 まで -> このIterationはなかったので新しく作られてINSERTされた

Iteration.for_week(2) (つまり再来週のIteration)
irb(main):005:0> Iteration.for_week(2)
  Iteration Load (0.2ms)  SELECT "iterations".* FROM "iterations" WHERE "iterations"."start_date" = '2013-07-29' AND "iterations"."end_date" = '2013-08-04' LIMIT 1
   (0.1ms)  begin transaction
  SQL (0.5ms)  INSERT INTO "iterations" ("created_at", "end_date", "start_date", "updated_at") VALUES (?, ?, ?, ?)  [["created_at", Thu, 18 Jul 2013 17:41:37 UTC +00:00], ["end_date", Sun, 04 Aug 2013], ["start_date", Mon, 29 Jul 2013], ["updated_at", Thu, 18 Jul 2013 17:41:37 UTC +00:00]]
   (6.7ms)  commit transaction
=> #<Iteration id: 6, start_date: "2013-07-29", end_date: "2013-08-04", created_at: "2013-07-18 17:41:37", updated_at: "2013-07-18 17:41:37">

07/29〜8/4 まで -> このIterationもなかったので新しく作られてINSERTされた

Iteration.for_week(0) (じゃ、今週は?)
irb(main):006:0> Iteration.for_week(0)
  Iteration Load (0.2ms)  SELECT "iterations".* FROM "iterations" WHERE "iterations"."start_date" = '2013-07-15' AND "iterations"."end_date" = '2013-07-21' LIMIT 1
=> #<Iteration id: 4, start_date: "2013-07-15", end_date: "2013-07-21", created_at: "2013-07-18 11:25:37", updated_at: "2013-07-18 11:25:37">

07/15〜07/21 まで このIterationはすでにあったので、INSERTされない

ここでIterationの数を再確認
irb(main):007:0> Iteration.count
   (0.2ms)  SELECT COUNT(*) FROM "iterations" 
=> 4

最初2つでその後2つ作られたので合計4つ。あってる

そんなわけで、for_week で、該当するIterationがなかった場合は新規に作れ、かつ未来の分まで作れることが確認できた。

sandbox
rails c --sandbox

ってやると、ここでやったものはDBに残らないので、素振りに最適

exit

rails c、抜けるときはexit (ずっと control + d 使ってた)

Heroku にpushする前に、assets:precompile しないとassetsの変更が反映されない問題

Sassのimportの仕方が悪い

今まで
applicaiton.css にこう書いて

/*
 * This is a manifest file that'll automatically include all the stylesheets available in this directory
 * and any sub-directories. You're free to add application-wide styles to this file and they'll appear at
 * the top of the compiled file, but it's generally better to create a new file per style scope.
 *= require_self
 *= require basic
*/

basic.sass で 各Sassファイルを順番にimportしてた

@charset "utf-8"

@import compass/reset
@import compass/utilities
@import compass/css3
@import font-awesome
@import font-awesome-ie7

@import variables
@import mixin
@import style

これを application.css.sass にして普通にimportすれば、require とかなくてもいけるらしい
application.css.sass

@charset "utf-8"

@import compass/reset
@import compass/utilities
@import compass/css3
@import font-awesome
@import font-awesome-ie7

@import variables
@import mixin
@import style
  • ほんで、今まで使ってた application.css と basic.sass は削除
  • そして public/assets 配下のファイルを全削除
  • .gitignore に public/assets を追加

これでpublic/assets なしでもSassをちゃんと順番に読むようになったので解決したっぽい

感想とか

  • 今回は久しぶりにP4Dにいらした @ppworks さんにとてもわかりやすく教えていただいて、ありがとうございました m(__)m
  • DRY、同じ事繰り返して書いちゃった時にこれアカンと思う感覚が大事なのだなあ。
  • modelにメソッド書くと色々汎用的に使えてステキなのだな。(なんでもviewでやろうとしてしまうのをやめたい。。
  • また教えてもらうばかりになってしまった・・・Sassの話とかは全然できず、すいません。。途中で時間を区切った方が良さそう。
  • エラー画面がかっこ良くなって、さらにデバッグもできるようになって感激だ!
  • 焼きそばナポリ味は粉チーズかけるとうまい。
  • GitHubの鍵のトラブルに見舞われたが、いつの間にか鍵のファイルの中身が消えてしまってたので、鍵を同じ名前で作りなおしたら解決した。鍵こわい。