Hatena::ブログ(Diary)

納豆には卵を入れる派です。 このページをアンテナに追加 RSSフィード Twitter

2013-08-17

第27回 #p4d 参加した:omniauth-twitter

前回の続き。おかげさまで、Iteration 周りは自力でも進められそうな感じになってきたので、Twitter でユーザーがログインする機能を作りたいとおもった。 omniauth-twitter を使えば楽にできるけど、楽に出来すぎてよくないので OAuthからちゃんとやった方がいいですよというアドバイスを頂き、どっちがいいのかなあと思っていたのだが、あまり時間もないので omniauth 使うことに。今回、@katton さんに教えていただいたのですが、 OAuth とは?というところからわかりやすく教えていただき、だいぶカバーされた感じなので、下記おすすめ書籍を読んで理解深めたい。

また、@katton さんは、リアルタイムでエディタでお題を書きながら、そのメモをエディタ上で見せながら進めてくださり、さらにそのメモを帰宅後送って下さるなど、大変ありがたく、またこの方法は教えるのに大変よい方法だと思った。頂いたメモをベースに追記する感じで、復習が進められた(下記は、その記録)。ありがとうございました!

0. OAuthとは

リソース保有者が、リソースプロバイダー(Twitterとか)に対して「アプリに自分の情報を教えても良い」と許可すること。

※ 今回はサーバサイドWebアプリケーションフローを採用。

おすすめ書籍

OAuth 2.0をはじめよう(オライリー / 日本語)

1. twitterアプリケーション登録

本番用と開発用両方を登録しておく

dev.twitter.com/apps

  • 本番用 Callback URL: domain/auth/twitter/callback
  • 開発用 Callback URL:(pow.cx を使った場合): APPNAME.dev/auth/twitter/callback

omniauth の callback URL は、/auth/[プロバイダ名]/callback

callback
  get '/auth/:provider/callback', to: 'sessions#create'

2. Figaro使う

laserlemon/figaro · GitHub

なぜ?:アプリ固有の設定をapplication.ymlというカタチで保存、Figaro.env.xxxで読み込みができる。

インストール
gem 'figaro'

$ bundle

$ rails g figaro:install

config/application.yml に先ほどdev.twitter.com で登録したときの、key と secret を書いておく。

こうすることで、各プロバイダにアクセスする用の key 達が一元管理できる。

config/application.yml はインストール時に自動的に.gitignore に追加されるので、ソースコードを公開してもヒミツにしておけるのもナイスだ。

development:
  twitter_key: xxxxxxxxxxxxxxxxxxxxx
  twitter_secret: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

production:
  twitter_key: xxxxxxxxxxxxxxxxxxxxx
  twitter_secret: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Heroku

Herokuに デプロイするときは、この1行コマンド打てばOK

$ bundle exec rake figaro:heroku

3. Omniauth を使う

intridea/omniauth ・ GitHub

arunagw/omniauth-twitter ・ GitHub

※ omniauth-twitter のように、付属機能的な意味合いの場合はGem名の接続子が "-" になる

インストール

Gemfile

gem 'omniauth'
gem 'omniauth-twitter'

$ bundle install

設定ファイルをじぶんで作る

複数プロバイダを使用する場合は、別ファイルに設定を書いたりしないといけなくてめんどい。今回はTwitterだけなので1つのファイルでOK。

config/initializers/omniauth.rb

公式のUsageではこんな感じに、直接KEY と SECRET を書けとなっているが…

Rails.application.config.middleware.use OmniAuth::Builder do
  provider :twitter, "CONSUMER_KEY", "CONSUMER_SECRET"
end

先ほど、Figaro を入れたおかげで、config/application.yml に書いたKEY 達をこのように設定から呼び出せるようになってる。ナイスだ。

Rails.application.config.middleware.use OmniAuth::Builder do
  provider :developer unless Rails.env.production?
  provider :twitter, Figaro.env.twitter_key, Figaro.env.twitter_secret
end

4. Userモデルをつくる

必要なカラムを確認

omniauth-twitter の Authentication Hashを見ると、Twitterから取れる情報が一覧できる。いっぱい取れる情報があるんですねー。

今回は、ログインに使うくらいなので、名前とアイコンくらいがあればいいかなー。

uid, secret, token は必ず必要だよ。ってなわけでとりあえず必要なのは以下の5つとなる。

  • uid
  • name
  • nickname
  • image
  • token
  • secret

$ rails g model user uid name nickname image token secret

全部 string でいいので、並べるだけでOKだった。

uid は必須かつユニークにしておこう。

/db/migrate/20130815115856_create_users.rb

class CreateUsers < ActiveRecord::Migration
  def change
    create_table :users do |t|
      t.string :uid, null: false
      t.string :name
      t.string :nickname
      t.string :image
      t.string :token
      t.string :secret

      t.timestamps
    end
    add_index :users, :uid, unique: true
  end
end

$ rake db:migrate

5. OAuth認証をする

5-1. TwitterへのURLをつくる

= link_to 'Twitterログイン', '/auth/twitter' 

というリンクを仮にTOPのviewに作っておく

5-2. powインストール

Pow: Zero-configuration Rack server for Mac OS X

開発ディレクトリシンボリックリンクを~/.pow に追加しておくだけで、http://APPNAME.dev というURLでアクセスできるというイカしたもの。みんな大好き37signals 製。CoffeeScriptNode.js でできてるらしい。シャレオツだね。

実際のPowの導入は、P4D時間内に間に合わず、帰宅後になったんだけど、少しハマった。

$ curl get.pow.cx | sh

$ cd ~/.pow
$ ln -s /path/to/myapp

だけで、http://APPNAME.dev

でアクセスできるはずなんだけど、

LoadError: no such file to load -- bundler/setup

っていうエラーが出てる。私の環境は、RVMでなくてrbenv(brew インストールでない)なのでおそらく Troubleshootingに書いてある

~/.powconfig に下記パスを追加する

export PATH="$HOME/.rbenv/shims:$HOME/.rbenv/bin:$PATH"

というのをやれば大丈夫なはず…あれ、動かない。。上記対処後アプリ再起動的なものも色々試みてだめだったので、一回powをUninstallしたのち再インストールしたら動いた。

5-3. Callbackを受け取って必要な情報をUserへ

logger.info で確認

app/controllers/session_controller.rb

  def create
    puts '==========='
    logger.info(request.env['omniauth.auth'])
    redirect_to '/'
  end

ログにTwitterからの情報っぽいものが出力されたら成功(puts '=========' は、ログの目印的に付加してる)

5-4. User.find_or_create_from_auth_hash の実装

この辺の半ばでP4Dはタイムアップになったので、@katton さんが書いて下さったメモを参考に、家で続きやる

app/models/users.rb に uidからuserを見つける -> なかったら新規にuser を作る という機能に必要なクラスメソッドを作る

  # find_or_create_by_oauth 既存のoauthを見つける -> 無かったら新しく作る 
  def self.find_or_create_by_oauth(auth)
    if user = User.find_by_oauth(auth)
      user
    else
      User.create_by_oauth(auth)
    end
  end

  # uid を使って 既存の user を見つける
  def self.find_by_oauth(auth)
    user = User.find_by_uid(auth['uid'])
    # user = User.find_by(uid: auth['uid']) # Rails4ではこう書ける
    if user
      user
    else
      nil
    end
  end

  # 新しく user を作る
  def self.create_by_oauth(auth)
    user = User.new
    user.uid = auth['uid']
    user.name = auth.info['name']
    user.nickname = auth.info['nickname']
    user.image = auth.info['image']
    user.token = auth.credentials['token']
    user.secret = auth.credentials['secret']
    user.save
    user
  end

同じく app/controllers/sessions_controller.rbにも authから ユーザーを見つけるクラスメソッドを追加

https://github.com/intridea/omniauth#integrating-omniauth-into-your-application

  def create
    @user = User.find_or_create_by_auth(auth_hash)
    #self.current_user = @user
    redirect_to '/'
  end

  protected

  def auth_hash
    request.env['omniauth.auth']
  end

current_user は まだないのでコメントアウトしておく。さきほど作った、Twitterへのリンクをクリックして確認してみる -> 認証ボタン押して戻ってきたら

$ rails c
User.find(:all)
[#<User id: 9, uid: "5652122", name: "TAE", nickname: "ken_c_lo", image: "http://a0.twimg.com/profile_images/3788000001102151...", 

・・・・

おー、ユーザー情報入ってるーヾ(*'ω'*)ノ゙

5-5. sessionにuser_idを保存して、「ログイン」をさせる

参考)https://speakerdeck.com/takai/login-form-from-scratch

app/controllers/sessions_controller.rb に session[:user_id] = @user.id を追加

  def create
    @user = User.find_or_create_by_oauth(auth_hash)
    #self.current_user = @user
    session[:user_id] = @user.id
    redirect_to '/'
  end
5-6. ログインの確認

app/controllers/application_controller.rbに current_user の メソッドを追加

  def current_user
    if session[:user_id]
      User.find(session[:user_id]) 
    else
      nil
    end

確認してみようー

app/controllers/sessions_controller.rb で loggers.info を書いて確認

  def create
		・
		・
		・
    logger.info("========current_user.name: #{current_user.name}")
    #self.current_user = @user
  end

※ 結局 この self.current_user の行は、別のところで current_user を定義したのでいらなさそげだ

ログに、Twitterの名前が出てきたら成功っぽい!

と、そんなわけで、一連のログイン機能のベースができたっぽいので、ここから、user と task や iteration を紐付けたり、ログインページを作ったりする。公開に一歩近づいた感じが嬉しい。

感想とか

  • omniauth 使うと簡単だと聞いたけど、私のレベルだとそれでもかなり苦労したので、結果 omniauth 使ってよかったのではないかと思う・・・
  • 今回も、@katton さんに大感謝だ・・・本当に、ありがとうございましたm(__)m
  • Pow便利だなー。Powいかすー。
  • 毎回、違うプログラマさんに教えていただくが、プログラマさんによってやり方も色々だったりするので、結果、色んな方法やアイデア、色んなツールが知れることになり、これはかなり素晴らしいのではないかと思った!(ありがたい・・・
  • find_or_create_by_auth はできたけど、これだけだとユーザーネームやアイコンを変えた時とかに更新されないので、それ用のメソッドがまた必要なんだろうなー
  • また、時間いっぱい教わってしまい、こちらからデザインの話とかすることができずに申し訳なす・・・
  • 今回、半分の時間で交代で区切っていただいたのだけど、やっぱり教わるとなると時間が足りずにフルに教わることになってしまう。
  • ので、前回教わった人は次回教えればいいんじゃないか、ってことにもなったので、次回はなにか教える側に回ります。

2013-08-11

Middleman で link_to_if っぽいことをやる

ナビゲーションで、現在地を表すナビだけリンクをつけないみたいなことをやる時、Railsだと、link_to_ifとかlink_to_unlessとかを使うと便利だが、Middlemanのヘルパーにはそういうのは特にないっぽかったので、どうにかして似たような事をやろうと思ったらこんな感じになった。

https://gist.github.com/taea/6204099

index, concept, product, contact みたいな4つのページが仮にあったとして、それぞれ同じナビゲーション用のパーシャル source/partials/_nav.html.haml を呼び出すとする。

Middlemanのデフォルトレイアウトは、ページごとにファイル名と同じ名前(index.html だったら "index" という名前)の class が外側の body につくようになってて 、これが "#{page_classes}" という 変数で呼び出されるようになってるので、これを利用して、この page_classes が、データで指定した page.name と一緒だったら、current ページを表すナビゲーションとして処理するという感じにした。三項演算子のところは、もっとシンプルに書けるんでは?という気もするのだけど、これ以外に思いつかなかった。

ナビゲーションの内容は、マークアップとは別のYamlファイルにdata/nav.yml みたいにして置いておく。Frontmatter でもいいんだけど、複数ページで共通の要素なので、外部に置いた方がキレイに共通化できる。コンテンツを外出しするとマークアップがこれだけで済むのがステキですね。Middlemanステキですね。

マークアップ、Slimでもいいんだけど、Gistで色がつかないのが悲しいのでHamlで書いた。

2013-08-09

Alfred力高め隊

最近、@ruedap さんが神ワークフローを作ったのを見て、これが使いたくてAlfredの1から Alfred 2に乗り換えてPowerPackにお布施した。

Font Awesomeのアイコンフォントを検索できるAlfred 2のWorkflowを作ってみた

その時点で、1日平均 15回程度の使用というお粗末なアルフレッド力だったのだけど、お布施もしたことだし、Alfred力を上げてやろうと思って、全てのアプリ切り替えをAlfred力経由でやることにして鍛えることにした。

普段はWitch に ⌘ + Tab を割り当ててて、アプリ切り替えにはそっちを使ってしまうことが多いのだけど(これはこれで便利)、気づくと⌘ + Tabを連打して次のアプリを探してしまってることが多くて、なんだかなあという感じがあったので、ここはキー一発でAlfredで切り替えられた方がカッコイイ気がする。

で、2〜3日修行した結果…アルフレッド力はちょっと高まった! ヾ(*'ω'*)ノ゙

1日平均190.6回。前と比べるとかなりの進歩である。もう、ふとしたときに⌘ + Tabを押すことがなくなった。JISキーボードからUSキーボードに乗り換えたときも思ったけど、こういった瞬時に押すキーの違いとかは、2〜3日気をつけてるとだいぶ慣れますね。(でもVimは慣れるのに1ヶ月くらいかかった。)

アプリ切り替えにAlfred使うようにしてみてもう一つ思ったのは、ホットキー押した時に瞬時に次の動作のイメージが頭のなかで明確になってないと素早い使い方が出来ない時があり、脳みその回転があまりよろしくない私は、Alfredを立ち上げたまま、何秒か、えっと。。。みたいに固まってしまう時がたまにある。というか、よくある。⌘ + Tabだとその辺、UI上に選択肢が羅列されているので、⌘ + Tabを連打してるうちに視覚的な補助が手伝って次にやることを思い出せたりする。初期状態ではレコメンド的な補助がないのがCUI同様、コマンドランチャーの欠点かなあとも思うが、しかし頭の回転が良く脳のクロック数が高い感じの人はそれだけ、コマンドランチャーを効率よく使えそうだなあと思った。アルフレッド王、すごく頭の性能良さそう。

これがアルフレッド王のアルフレッド力だ… 1日平均651.4回!!日本一なのでは……とても追いつける気がしない。というかグラフよく見ると1日3000回くらいAlfredしてる日があってヤバい。人間の手にそんなことが可能なのだろうかと思うレベルだ。

Alfred Hotkey アンケートをしてみた

というか、現在過去に渡ってTLで見かけた事のあるAlfred のHotkeyを集計した結果、今のところこうなった。

  • control + space ×5
  • option + space ×3
  • ⌘ + ; ×3
  • double control ×1
  • ⌘ + space ×1
  • ⌘ + _ ×1

※ 新しい情報が入り次第随時更新中

私は⌘ + ; なんだけど、押しやすくて他ともかぶらずかなり気に入ってる。

アンケートは引き続き募集中です。

2013-08-04

Slimでセレクタを追加するときの書き方、及び Middleman の素晴らしさ。

よく、要素につけるidやclassを動的にしたい時とかに、Hamlだとこんな感じの書き方をする

%li{class: "item #{item.name}"}

この書き方がSlimだとダメっぽくてつまずいた。

Slimだとこんな感じの書き方になるらしい

li[class="item #{item.name}"]

こういうのもいけるっぽい。割と素のHTMLに近い感じで書けるのですね。

li class="item #{item.name}"

そして条件つけるとこうなるっぽい

li class=(if item.present? ? "#{item.name}" : 'no-item')
li class=("#{item.name}" if item.present?)

classを複数付け、かつ1つのclassにのみ条件を付加する場合はこのように入れ子にすればよいみたい。

li class="item #{if item.present? ? "#{item.name}" : 'no-item'}"
li class="item #{"#{item.name}" if item.present?}"

Slim + Middleman で静的サイト作ってみたのけど、MiddlemanはコンテンツをYamlに置いて外部化して、簡易CMSっぽいものを作るのがとても簡単で驚いている。これにより、コンテンツとテンプレートをキレイに分離できる。静的サイトなのに、工夫次第で一切類似要素をコピペせずにDRYに作れるのがとても素晴らしい。RailsActionView::Helpers(に似たようなの ※追記参照)も使えるし、SassもHamlCompassCoffeeScriptもすぐに使える。middleman buildってコマンド打つだけでhtmlの静的サイト一式をガガーっと一瞬で吐き出してくれるし、書きだすサイトのリンクや画像などのアセット相対パスなのか絶対パスなのかも設定で用意されてて、configに一行書くだけで変えられる。必要に応じてzip納品可能なサイト一式もbuildですぐに吐き出せもすれば、Herokuとかにデプロイもできるのだ。

Middlemanはまさしく常日頃からこういうの欲しいなーと思ってたそのものだった。怠けたいWebデザイナーにとってのライフチェンジングだ。

Slim も初めて書いたけど、これもシンプルで見た目キレイで良いですね。Hamlと対して違わないので、HamlやJadeに慣れた人なら、 群馬の Middleman + Slim エヴァンジェリストである @yterajima さんのこれとか読めば5分で書けるようになる。|(パイプ)を使った表記にだけ最初少し慣れなかったけど、これもよく出来ていて、視覚的にも縦棒が入ることによって階層構造がわかりやすくなるのがカッコイイ。

しかし、Middlemanもそうですけど、Sassやその周辺といい、HamlやSlimといい、Ruby周りは、全部コマンドラインが必要であるという入り口の障壁以外は、とことんデザイナーにとって優しく思いやりのある環境なのではないか?…と思ったけど、これおそらく別にデザイナーのためにってわけでもなくて、HTMLとかCSSとかを触るはめになったプログラマ達が、あまりの効率の悪さへの苦痛から、なんとかこれをアレしてやろうとアレした結果なのだろうと思った。彼らのコピペに対する憎しみが世界を良りよい場所へと変えているのだ。感動的であり、大変ありがたい。

おかげさまで、そろそろ素のHTMLとかもう書かないでも生きていけるような気がしてきたので、とてもうれしい。とてもうれしいです。

#追記

ご指摘いただきました。そうか、ActionView::Helpers そのものではなくて、それに似せて作られたヘルパーが使えるということですね。言われてみればそうだよなあ。。

今は padrino-helpers と sprockets-helpers の併用らしい。ありがとうございました!

# 追記その2

メモ程度に書いたものが思ったよりも人に読まれてしまい照れている。。ものを書くのがこんなに辛いのにどうしてメモ程度のものなら書けるんだろうか…そしてそういうものほどたまに読まれたりするのなぜなんだろう(ありがたいけど)。

そうそう、Middleman他にもいい所ありすぎて書ききれないのだけど、自分のようなプログラミング素人が、Railsほど難しくなく、普段の仕事の静的サイト作りとかの中で、比較的気軽にプログラミングっぽい気分の断片を味わえるのも、すごく良いところの一つだと思う。私はほんのちょっとしかやったことがないのでわからないのだけど、Middleman のベースである Sinatra がそもそもそういう感じなのかもしれない。

先日の初心者はRailsから入るべきでないという盛り上がった話題を思い出す。自分も素人Railsやってて確かにわけわからんこと多くて難しいし(でも半分趣味だしやってておもしろいしまあいいのではとも思ってるから辞めはしない、Rails好きだし。)、プログラミング覚えたいデザイナーやマークアッパーにもし最初の一歩として何か勧めるなら 今は Middleman かもなーって思った。普通に自分の仕事の範囲内で、無理も危険もあまりなくプログラミングエッセンスが味わえるし、結果的に普段の仕事も楽になるんだから一石二鳥で素晴らしい。こういうの欲しかった!ってきっと思えると思う。データとビューを分割することの意義も身近な所で実感できそうだ。ViewだけならかなりRailsに近い要素あるし、Middlemanを経てRailsっていうのは良さそう。納得だ。日本語ドキュメントも @yterajima さんの尽力のおかげでかなり充実しており、そんなに困ることがなかった。

なんかそのうち、デザイナー(っていうか自分)が静的サイトのワークフローをさらに楽にこなすための Middleman のカスタムフレームワーク 的なものとかを作ってみたい気もしてきた。そのうち、そのうち。。

2013-07-18

第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.cssbasic.sass は削除
  • そして public/assets 配下のファイルを全削除
  • .gitignore に public/assets を追加

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

感想とか

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