ActiveRecordで日付の範囲指定
ActiveSupportのコア拡張を使うとめちゃ綺麗に書けて感動した。
- 今日
from = Time.now.at_beginning_of_day to = from + 1.day items = Item.where(created_at: from...to).order(created_at: :desc)
- 今月
from = Time.now.at_beginning_of_month to = from + 1.month items = Item.where(created_at: from...to).order(created_at: :desc)
RailsのセッションをJSONで
Railsのセッション情報はこちらの記事にあるように、RubyのMarshalでシリアライズされ、Base64エンコードされたものがクッキーなどに保存される。
ただ、Ruby以外では復元が難しいため、Node.jsなど別言語で書かれたサーバーアプリケーションとセッションを共有しづらい。
なので、こちらの記事を参考にJSONで保存できるようにしてみた(というかほとんどそのまま)。
セッション情報の保存先にはredis-storeライブラリを使ってRedisに保存する。
redis-storeは、RubyGemsにあがっているものだとRails4で動かない(Rails3でもredisライブラリのバージョンが新しいと動かない)。
GitHubを見てみたら、forkされたものが最近のRackのバージョンアップ含めてRails4対応していたので、それを使う。
Gemfile
gem 'redis' gem 'redis-store', github: 'bricker/redis-store' gem 'redis-rails', github: 'bricker/redis-store'
config/initializer/session_store.rb
require 'action_dispatch/middleware/session/redis_store' # # デフォルトだとRubyのMarshalでセッションオブジェクトを保存するため、Node.js側で扱えない # JSONで保存するためにモンキーパッチをあてる # module ActionDispatch module Session class RedisStore # override def get_session(env, sid) with_lock(env, [nil, {}]) do unless sid and session = @pool.get(sid) sid, session = generate_sid, {} unless /^OK/ =~ @pool.set(sid, JSON.generate(session)) raise "Session collision on '#{sid.inspect}'" end end session = JSON.parse(session) unless session == {} if session.has_key?('flash') session['flash'] = ActionDispatch::Flash::FlashHash.new.update(Hash[*session['flash']]) end [sid, session] end end # override def set_session(env, session_id, new_session, options) with_lock(env, false) do jsonize_session = JSON.generate(new_session) @pool.set session_id, jsonize_session, options session_id end end end end end # セッションの生存期間は1週間 Sample::Application.config.session_store :redis_store, servers: { host: "localhost", port: 6379, namespace: "_sessions", db: 10, expire_in: 60 * 60 * 24 * 7 }
redis-store、もう1年くらい更新されてないしissuesもpull reqも溜まってるけど作者の人やる気もうないのかな。。。
Railsでセレクトボックスの出力
selectとかselect_tagとかcollection_selectとかいろいろあってオプションの指定も微妙に違ってたり分かりにくい。
ActiveRecordの配列と普通の配列を同じように扱えて、name属性を自由に定義したい。
いろいろ試してみたところ、select_tagとoptions_for_selectを使うのがよさげな感じがした。
<!-- ActiveRecordの配列を受け取る --> <%= select_tag "user", options_for_select(@users.map {|u| [u.name, u.id]}), prompt: t('user') %> <!-- 配列([name, id])を受け取る --> <%= select_tag "status", options_for_select(@statuses), prompt: t('status') %>
selectとcollection_selectはname属性が"オブジェクト名[プロパティ名]"になる。
promptは未選択時の項目、空欄でよければinclude_blankをオプションに指定する。
デザイン変えた
テーマストア見てたらなんか意欲が湧いてきたのでデザインを弄ってみた。
ブログのテーマデザインを弄くるのは楽しい。
まだプログラムの勉強やり始めてまもない頃、バイトでMTのテーマとかプラグインやら作ってたのを思い出す。
そういえばあのころ、ブログが広まりだしたころって3カラム全盛期だったなあ。
今はあまり見かけないけど、よく調整されたやつは下にスクロールすると1カラムぽく見えるので、2カラムを下にスクロールするのに比べて違和感なくて好きだった。
vagrantとknife-soloで開発環境構築を自動化するやつ
最近vagrantとknife-soloで、ってのが流行ってるみたいなのでやってみた。
waka/auto-dev-env
ベースBoxは、vagrantbox.esからUbuntu12.10 server minimalってのを落とせるけど、knife-soloはOmibus Chef Packagingのものをインストールしてくれるのでchefは入ってる必要なかったり、Boxのディスクサイズが10GBと少なかったので、Veeweeを使って作った。
vagrantはポートフォワーディングの設定が簡単で便利ですね。
とにかく、これでムシャクシャしたとき「sudo rm -rf /」がいつでも出来るようになったぞ!
Opscodeのレシピ見ててもRedhat系かDebian系かで動かなくなりそうなもの多いので、もし作ったレシピを配布して開発環境合わせるとかやろうとすると、実行するマシンのOSと仮想環境のディストリビューションを統一するのが大事なんだろうな。