おもしろwebサービス開発日記

Ruby や Rails を中心に、web技術について書いています

iphone のカメラを修理した

iphone6 plus で写真を撮るときに、フォーカスが合わずにぼやけた写真しか撮れなくなってしまいました。

ググるとどうやらハードウェアの不具合の模様。

iPhone 6 Plusのカメラのピントが合わない不具合が発生 - 非天マザー by B-CHAN

ジーニアスバーに持って行こうと思って調べるも、予約可能な日時を考えると一週間ほど待つことになりそうなので、宅配便を使った修理サービスを使用してみることにしました。apple のことだから代替機とかも用意してくれるのではと勝手に思い込んでいたのですが、普通に iphone を持って行かれてしまい、しばらく電話なし生活を余儀なくされました。

普段ほとんど電話を使うことはないので基本的には問題ないのですが、一点困ることがありました。僕の家はインターフォンがないので、宅配のものを受け取るのに電話が必須だったのです…><

つまり iphone を受け取るのに iphone が必要という詰んだ状況に。困った。

部室にあった検証用のSIMフリーのAndroid端末をお借りして、iphone の SIM を入れればなんとかなる…と思いきや、SIMのサイズが合わない。

そこで電気屋に行ってSIMサイズを変更するアダプタ購入した*1ら電話を使うことができるようになりました。

ググったらどうもiphoneのSIMはアダプタを使っても、端末によって使えたり使えなかったりするようなので、今回電話が使えたのは運が良かったようです*2

というわけでなんとかiphoneを修理することができました。どうやらググると代替機を用意してくれるプランもあったようです。次回はこれを使うか、おとなしくジーニアスバーを利用したいと思います…。

Apple - サポート - 修理サービス Q&A センター

*1:新宿の大きい電気屋を二軒まわりました。SIMアダプタの在庫は少ないようですね…

*2:ただ、インターネットは使えませんでした。

nested attributes なレコードを、特定の属性が空の時に削除する

nested attributes なレコードを削除したい場合、accepts_nested_attributes_forallow_destroy: true オプションを渡すと削除可能になります。削除するには、対象となる対象に { _destroy: 1 } のようなパラメータを渡します。

これを踏まえて素直にフォームを作ろうとすると、削除用のチェックボックスをつける事になるでしょう。しかし次のようなフォームにチェックボックスをつけると、ユーザにとってわかりづらいUIになってしまいます。単純にテキストフィールドを空にして更新したらレコードが削除されて欲しい。

f:id:willnet:20150725173208p:plain

そこで次のようにします。

class User < ActiveRecord::Base
  accepts_nested_attributes_for :family_members,
                                reject_if: :reject_family_member,
                                allow_destroy: true

  def reject_family_member(attributes)
    exists = attributes[:id].present?
    empty = attributes[:email].blank?
    attributes.merge!(_destroy: 1) if exists && empty
    !exists && empty
  end
end

reject_if の手続きの中で、レコードとして保存済みでかつメールアドレスが空のものに { _destroy: 1 } を追加しています。これでチェックボックスなしで nested attributes なレコードを削除することが出来ました。

参考

ruby on rails - Destroy on blank nested attribute - Stack Overflow

ActiveJob はまだちょっと使うには早いかも

Rails 4.2 から導入された ActiveJob は、sidekiq や resque などのバックグラウンドジョブ系 gem を、同じ利用方法で扱えるようにしてくれます。

これは便利だなーと思い、sidekiq を ActiveJob を通じて使ってみたのですが、しばらく使った後に「まだ本格的に使うのは早いかも」と感じました。

リトライ機能が貧弱

sidekiq は、ジョブが失敗した時にリトライする機能があります。失敗するたびに次にリトライする間隔が伸び、一定回数失敗したら完全に失敗として扱われます。リトライ間隔や、完全に失敗になるまでの回数はもちろん変更可能です。

Web上でリトライしているジョブや完全に失敗したジョブを確認することもできます。

ActiveJob を使うと、この細やかなリトライ機能を失うことになります。例えば、次のように例外を拾って再度キューにジョブを入れることはできますが、リトライ間隔や最大のリトライ回数などはサポートしていません。この場合は無限にリトライすることになってしまいますね。

class SiteScrapperJob < ActiveJob::Base
  rescue_from(ErrorLoadingSite) do
    retry_job queue: :low_priority
  end

  def perform(*args)
    raise ErrorLoadingSite if cannot scrape
  end
end

リトライをサポートしてくれる gem

gocardless/activejob-retry という gem があります。これを使えば問題は解決しそうですが、READMEを読むと

This is an alpha library in active development, so the API may change.

との事なので、まだ実践で使うには早いのかなと思います。また、仮に alpha でなくなったとしても、ActiveJobの性質上、sidekiq の WebUI でリトライしているジョブの数を確認したりはできないはず。

まとめ

ActiveJob を使うと、様々なバックグラウンドジョブ系の gem を意識せず同じ使い方で使えるのがメリットだと思います。しかし1つの gem をずっと使うのであれば、その gem 特有の機能が使えなくなるデメリットが大きいように思えます。個人的には、今の段階ではなるべく ActiveJob は避けていくのがよいのかなと思います*1

*1:deliver_later くらいなら問題ないと思います

色彩検定2級を受けてきた

6月28日(日)に色彩検定2級の試験を受けてきました。

色彩検定協会/カラーコーディネーター

webサービスを作るときに、どんな色を使ったらキマるのか全然わからず適当に勘で決めていたのですが、色彩検定の勉強をする中である程度のセオリーをつかめた気がします。

まず去年受けた3級の試験勉強を通じて、色には色相とトーン(彩度、明度)があり、それぞれの種類と人に与える印象の違いについて学びました。

これがわかると、例えばビジネス関連のサービスを作りたかったら、色相は誠実な印象を与える青で、トーンは落ち着いた印象のライトグレイッシュを使おうか…などと、論理的に色を絞り込むことができます。今書いたような例がぴったりハマるようになるには経験が必要ですが、勘で決めていた頃よりはだいぶ前進できた気がします。

2級では、複数の色をどのように組み合わせると調和して見えやすいか学びました。例えば同系のトーンの組み合わせだと調和するとか。webサービスを作るには複数色必要なので、2級の範囲までは学んで損はないように思います。色とかどうやって決めたらいいのという人にはオススメです。

色彩検定の範囲には、色の分類の仕方などのwebデザインに直接使える項目以外にも、目の構造とか光の波長についてとかファッション、インテリアなどの項目もあります。僕は雑学を学ぶつもりでひと通りやりましたが、無駄なことをしたくない人は、色の分類のところだけ拾い読みするのもいいんじゃないかと思います。

勉強したいけどモチベーションが続かない!という人は毎月やっているデザインビギナーズのミートアップに来るとよいと思います ;-)

プロフィールサイトを作った

先日ブログをはてなに戻したのですが、はてなブログはいわゆる naked ドメインに対応していないため、ドメインを willnet.in から blog.willnet.in に変更しました。

結果として willnet.in が空いてしまったので、プロフィールっぽい感じのページとして利用することにしました。

willnet.in

各エントリのリダイレクトをする必要があったので、sinatra で簡単に実装。heroku に置いてサーバは Passenger にしています。

willnet/willnet_in

これでようやく落ち着いてブログ書ける環境になったかな…

はてなに出戻りました

3年ほど Lokka + heroku でブログを書いていましたが、この度はてなに戻ることにしました。

もともと Lokka を使おうとしたのは、

  1. markdown が使いたかった
  2. 自分でカスタマイズしたかった

という理由からでした。

しかし

  • 1 については今のはてなブログでは普通に markdown が使える
  • 2 については、今は他のプロダクトを複数持っており、そっちを優先したいので、ブログについてはなるべくカスタマイズせずに済ませたくなってしまった

というわけで出戻ることにしたのでした。

以前の willnet.in で書いていた記事はインポートしてきましたが、URLが変わってしまったため以前の記事にブックマークをつけていた場合はリンク切れになってしまっています*1。追記: リダイレクトするように修正しました。

最近は昔ほどエントリを書けていませんが、数は少なくてもなるべく質の高いものを書いていきたいなと思っております。これからもご愛顧のほどよろしくお願いしますm(__)m

*1:これがあったためなかなかブログの引っ越しに踏み切れなかった

find_by_sql したレコードで preload する方法

どうしても AR の query methods だけでは要求を満たせない場合の最後の手段として、find_by_sql メソッドがあります。皆さんよく使ってると思うのですが、戻り値のレコードからさらに association をロードしようとすると N+1 になるケースがあります。かといって

User.preload(:comments).find_by_sql(sql)

のようにしても期待通りには動きません。単純に preload 部分が無視されるだけです。

ではどのように書いたらよいでしょうか。

次のように書くと期待通りに動きます(Rails 4.2.1 で試しています)。

records = User.find_by_sql(sql)
ActiveRecord::Associations::Preloader.new.preload(
  records, :comments
)
records # comments が preload されている

:comments の部分は、通常の preload と同じように、配列やハッシュを指定できます。

これで N+1 の心配をせずに済みそうです。

参考

preload associations with find_by_sql · Prathamesh Sonpatki