長いことrailsばっかりやってると他人のコードを「Railsのレール(流儀)にどれだけ乗れてるか、どれだけ流行りの書き方してるか」だけで判断しがち。
見慣れない書き方だったり、他の言語っぽい書き方だったりするとボロカスに評価しているのを見かける。
Railsに浸かり過ぎて、Railsっぽくないもの=悪。レールから外れている=ゴミ。そういった判断は楽だしRailsプロジェクトにおいては大抵あってる(Railsを理解するのを面倒臭がっているゴミコード)んだけど、対象のコードが持つ価値(どんなことをどういう方法で解決してるのか)を判断する力が衰える気がする。
Railsのレールや最近の流行りの書き方とは違うけど、一貫性のあるコードだったり、不具合が出づらく変更に強いコードってのはある。
特にRails経験は浅いけど他の言語・フレームワークに習熟してる人のコードにそういうものが多い。
手癖でやってるとそういう筋肉が落ちる。自戒を込めて。
railsでコメント数の実装の悩み - komagataのブログ
コメント欄で色々アドバイスいただきました。ありがとうございます。
そもそも独立した二つの問題を一度に扱っていました。
- count数が遅い問題。
削除時のdependent: destoryが遅い問題。
counter_cacheやredis云々は1の話で僕の直近の問題である2とは関係無いですね。
2についてはdependent: :delete_all使え!で答えかと思います。(user → post → commentのように多段になってる場合はdelete_allではcallbackが動かないので手でやるべき)
1の方が大きなサービスを作っている方々が気になる問題かと思いますが怖話の規模ではconditional_counter_cacheで十分なので問題になったら考えたいと思います。
逆にdependent: destroyって面倒な処理が宣言的に書けてスゴイなとおもいます。この自動感を追い求めてDBのトリガーとかに解決策を見出してしまうと筋悪臭がすごいので素直に手で書きます。
NSLayoutConstraintのAPIがあまりにも辛いので調べてみるとAutoLayoutを簡単に記述できるライブラリがいくつかあるらしい。
しかしSwiftのライブラリマネージャーはどれがいいんだろう?CocoaPods、Carthage、Swift Package Managerなどがあるらしい。どれがおしゃれなんだろうか。
怖話のiOSアプリをSwift化しようと思ってiOSに再度入門してます。
ヘッダファイルがないだけでも気持ちいいですね。どうせプロジェクトファイルを作りなおすのだからUIWebViewからWKWebViewに移行しようと思っています。ただ、WKWebViewはstoryboardから使えないらしい😢
iOS7からStatusBarやNavigationBarの構造が変わったらしく、デフォルトのViewはStatusBarなどの下に潜り込む形になっていてそのままWKWebViewを追加すると重なってします。
参考:iOS 7の全画面対応 その1 | Cyber Passion for iOS
ViewController.swift:
import UIKit
import WebKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let webView: WKWebView = WKWebView(frame: view.bounds)
view.addSubview(webView)
let url = NSURL(string: "http://kowabana.jp")!
let request = NSURLRequest(URL: url)
webView.loadRequest(request)
}
}
沢山のデバイスサイズがあるこのご時世、AutoLayoutというやつに入門するしかないと調べてみましたがNSLayoutConstraintのクッソ(笑)ややこしいAPIが憎い。
railsでコメント数をどう実装するかで悩んでいます。
ニコ動だとこんな感じ。
怖話でもこんな感じでコメント数/再生数などを保存しています。
一定以上の数になると素朴な処理では速度的に無理が来ます。
怖話での実装方法
怖話でのカウント数の実装の歴史。
- 何もせずDBに1レコードずつ保存時代。
- 一覧ページなどが重いのでrailsのcounter cahcheを使う。
- コメントや閲覧はpolymorphic関連なのでcounter cacheが対応してない。conditional_counter_cacheを使う。
- 削除に時間がかかり過ぎる。 ← イマココ
一覧の表示はconditional_counter_cacheで大丈夫なのですが、削除時の処理がかかりすぎてタイムアップする問題がでてきました。
削除時の問題
ここではわかりやすく閲覧数ではなくコメント数で説明します。
コメント数が1万件ある話を削除すると下記のような処理が走ります。
- storyを削除する。
dependent: :destroyで依存するコメント1が自動的に削除される。- コメントが削除されたのでstoryのcomments_countが-1でUPDATEされる。
dependent: :destroyで依存するコメント2が自動的に削除される。- コメントが削除されたのでstoryのcomments_countが-1でUPDATEされる。
- 以下1万回繰り返し
1件につき100msだとしても1000sかかるので無理がある。
これまでの考え
- memcacheやredisを使うのは手間なので無理が来るまで避けたい。(開発環境の構築の手間が増える)
- ランキングで集計するので時間の情報は欲しい。
- 一番楽な方法で実装しよう。
今の考え
- RDBは無理がある。memcacheやredis、他のストレージもやむなし。
- rails的に一般的な実装はなんだろう?
- ありがちな問題なので一般的な対処方法を構築したい。
皆さんこういうのどう実装されてますか?こんな風にやってるよという方がいらっしゃったら @komagata などにメッセージいただけるとありがたいです。 :bow:
ぼっち演算子を使える2.3系にアップデート。
$ CONFIGURE_OPTS="--with-openssl-dir=`brew --prefix openssl` --with-readline-dir=`brew --prefix readline`" rbenv install 2.3.1
railsのプロジェクトでbundleしたらeventmachineのインストールでコケた。
Gem::Ext::BuildError: ERROR: Failed to build gem native extension.
current directory: /usr/local/var/rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/eventmachine-1.0.7/ext
/usr/local/var/rbenv/versions/2.3.1/bin/ruby -r ./siteconf20160518-21178-1i9l3os.rb extconf.rb
checking for rb_trap_immediate in ruby.h,rubysig.h... no
checking for rb_thread_blocking_region()... no
checking for ruby/thread.h... yes
checking for rb_thread_call_without_gvl() in ruby/thread.h... yes
checking for inotify_init() in sys/inotify.h... no
checking for __NR_inotify_init in sys/syscall.h... no
checking for writev() in sys/uio.h... yes
checking for rb_thread_fd_select()... yes
checking for rb_fdset_t in ruby/intern.h... yes
checking for rb_wait_for_single_fd()... yes
checking for rb_enable_interrupt()... no
checking for rb_time_new()... yes
checking for sys/event.h... yes
checking for sys/queue.h... yes
checking for clock_gettime()... no
checking for gethrtime()... no
creating Makefile
To see why this extension failed to compile, please check the mkmf.log which can be found here:
/usr/local/var/rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/extensions/x86_64-darwin-15/2.3.0-static/eventmachine-1.0.7/mkmf.log
current directory: /usr/local/var/rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/eventmachine-1.0.7/ext
make "DESTDIR=" clean
current directory: /usr/local/var/rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/eventmachine-1.0.7/ext
make "DESTDIR="
compiling binder.cpp
In file included from binder.cpp:20:
./project.h:116:10: fatal error: 'openssl/ssl.h' file not found
#include
^
1 error generated.
make: *** [binder.o] Error 1
make failed, exit code 2
Gem files will remain installed in /usr/local/var/rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/eventmachine-1.0.7 for inspection.
Results logged to /usr/local/var/rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/extensions/x86_64-darwin-15/2.3.0-static/eventmachine-1.0.7/gem_make.out
下記を参考にして設定したらいけました。
$ bundle config build.eventmachine --with-cppflags=-I$(brew --prefix openssl)/include
参照:Ruby2.3.0 igaiga diary(2015-12-25)一日の中で頭を使ってるのが「ご飯何食べるか」な気がして決め打ちすることにしました。
本当はソイレントでいいんですが、なかなか手に入らないですからね。
飯確保・食事のフロー
2ヶ月ぐらい試行錯誤した結果、ニチレイフーズの冷凍弁当ウーディッシュまとめ買いコースが一番便利でした。
これをネットで注文してオフィスに送り、冷凍庫にストックしておきます。冷凍なので9ヶ月持ち、腐る心配はありません。
ウーディッシュまとめ買いコースの良いところは、14食いっぺんに買えるところと、コンパクトで冷凍庫にたくさん入るところです。(写真の手はおもちゃの手なので弁当が大きく見えています)
栄養的には自分で用意するのは不可能なほどバランスが取れていてヘルシーです。味もコンビニや外食で胃もたれするおっさんには優しく美味しいです。量的にはOLが食ってる小さい弁当ぐらいのイメージです。
普段良い物を食べてる人にはメリットが少ないかもしれませんが、味の濃い外食や自分で好きなモノばっかり買うために偏ったコンビニ飯ばかりで胃が持たれてばっかりだった僕にとっては体調は良くなるし、時間も節約できて嬉しい限りです。
ゆくゆくは弁当ストックが減ったら自動で注文するようにしたいです。
怖話でネストしたリソースのクラス名がぶつかってしまうので、どうつけるかで悩んでいます。
ぶつかるページ
- story 1個づつに紐づくcomments(怖い話1のコメント一覧)
- なんらかのstoryに紐づくcomments(怖い話のコメント一覧)
story(怖い話)以外にもcomic(ホラー漫画)とかurban_legend(都市伝説)とかあり、それぞれにもcommentがつく。
# config/routes.rb
Rails.application.routes.draw do
namespace :stories do
resources :comments, only: :index
end
resources :stories, only: :index do
resources :comments, only: :index, controller: 'stories/comments'
end
end
% rake routes
Prefix Verb URI Pattern Controller#Action
stories_comments GET /stories/comments stories/comments#index
story_comments GET /stories/:post_id/comments stories/comments#index
posts GET /stories stories#index
URLの意味的にどちらも上記のようにしたいが、commentsコントローラーが被ってしまう。
これを避けてnamespace無しのcommentsコントローラーを使うと今度はcomicのcommentなどとかぶってしまう。
それを避けるにはAllCommentsとかCommentsByStoryなどといったダサい名前しか思いつかない。まいったなあ。
主にアメトーーク!を録画するのに使っているnasneが容量一杯なので外付けHDDを買いました。
I-O DATA USB 3.0/2.0接続【家電対応】外付ハードディスク 4.0TB HDC-LA4.0
しかしnasne、FAT32しか対応してませんでした。メーカー独自拡張とか以外2TBまでしか対応してない。クソがぁ…。
4.0TBの方はPCで使うことにして2TBの別のを買いました。
WD HDD ポータブル ハードディスク 2TB USB3.0 TV録画対応 Elements Portable WDBU6Y0020BBK-JESN / 3年保証
こっちはいけました。ただ注意するのはFAT32でもGPTではなくMBRでフォーマットしないといけないこと。ちょっとハマっちゃいました。くそがぁ…。
最近やっちゃった買い物が多いのでスペックは注意して買って行きたい。



