Xcode6.3とXcode6.2を併用してる環境でApp StoreへのSubmitが途中で止まる問題の解決策
元ネタはこちら。
普通にXcodeからアプリをSubmitするときって、OrganizerのSubmitボタンからやると思うんですが、別な方法を使うことでこのバグ?らしき挙動をバイパスできるってことみたいです。たぶん。
- OrganizerでExportを押下
- "Save for iOS AppStore" からRipaファイルを生成、適当なとこに保存
- ドックのXcodeを右クリック →
Developer tools
→Application Loader
- この
Application Loader
を使ってsubmitすると問題ない
誰かの参考になれば幸い。
Application Loader
ってなんだろ。
herokuにRails4.2.0 with mongoid & angularjsなプロジェクトをデプロイ
地雷だらけで死にそうだったのでメモ
- config/production.rb のjs_compressor書き換え (後述)
- public/assets 以下はgitに入れちゃった方がいい
- heroku config で RAILS_SERVE_STATIC_FILES に true を設定しておく
- mongoid.yml の設定が必要 (後述)
- pumaにしとく (Procfile , config/puma.rb を設定)
config/production.rb のjs_compressor書き換え
Angular.jsが動かなくなるのを防ぐためにmangleをfalseにしたUglifierを使う
config.assets.js_compressor = Uglifier.new(:mangle => false)
mongoid.yml の設定
以下のようにする
production: sessions: default: uri: <%= ENV['MONGOLAB_URI'] %>
MongoHQを使ってる場合は環境変数名が違うだけ。 production直下にuriを書けるって情報があるけど、古いようで今のバージョンでは動かない。
雑感
そこそこ使われてそうな組み合わせの割に情報あんまりないし、最近ネット上に技術メモ流す人減ってないか?Twitterに書いて満足するのやめてこの程度にはまとめて書こうな!?
参考: バージョン情報
ruby 2.1.3
Gemfile.lock
GEM remote: https://rubygems.org/ specs: actionmailer (4.2.0) actionpack (= 4.2.0) actionview (= 4.2.0) activejob (= 4.2.0) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 1.0, >= 1.0.5) actionpack (4.2.0) actionview (= 4.2.0) activesupport (= 4.2.0) rack (~> 1.6.0) rack-test (~> 0.6.2) rails-dom-testing (~> 1.0, >= 1.0.5) rails-html-sanitizer (~> 1.0, >= 1.0.1) actionview (4.2.0) activesupport (= 4.2.0) builder (~> 3.1) erubis (~> 2.7.0) rails-dom-testing (~> 1.0, >= 1.0.5) rails-html-sanitizer (~> 1.0, >= 1.0.1) activejob (4.2.0) activesupport (= 4.2.0) globalid (>= 0.3.0) activemodel (4.2.0) activesupport (= 4.2.0) builder (~> 3.1) activerecord (4.2.0) activemodel (= 4.2.0) activesupport (= 4.2.0) arel (~> 6.0) activesupport (4.2.0) i18n (~> 0.7) json (~> 1.7, >= 1.7.7) minitest (~> 5.1) thread_safe (~> 0.3, >= 0.3.4) tzinfo (~> 1.1) angularjs-rails (1.3.10) arel (6.0.0) autoprefixer-rails (5.1.7) execjs json binding_of_caller (0.7.2) debug_inspector (>= 0.0.1) bootstrap-sass (3.3.3) autoprefixer-rails (>= 5.0.0.1) sass (>= 3.2.19) bson (2.3.0) builder (3.2.2) byebug (3.5.1) columnize (~> 0.8) debugger-linecache (~> 1.2) slop (~> 3.6) coffee-rails (4.1.0) coffee-script (>= 2.2.0) railties (>= 4.0.0, < 5.0) coffee-script (2.3.0) coffee-script-source execjs coffee-script-source (1.9.1) columnize (0.9.0) connection_pool (2.1.1) debug_inspector (0.0.2) debugger-linecache (1.2.0) erubis (2.7.0) execjs (2.3.0) globalid (0.3.3) activesupport (>= 4.1.0) hike (1.2.3) i18n (0.7.0) jbuilder (2.2.8) activesupport (>= 3.0.0, < 5) multi_json (~> 1.2) jquery-rails (4.0.3) rails-dom-testing (~> 1.0) railties (>= 4.2.0) thor (>= 0.14, < 2.0) json (1.8.2) loofah (2.0.1) nokogiri (>= 1.5.9) mail (2.6.3) mime-types (>= 1.16, < 3) mime-types (2.4.3) mini_portile (0.6.2) minitest (5.5.1) mongoid (4.0.2) activemodel (~> 4.0) moped (~> 2.0.0) origin (~> 2.1) tzinfo (>= 0.3.37) moped (2.0.4) bson (~> 2.2) connection_pool (~> 2.0) optionable (~> 0.2.0) multi_json (1.10.1) nokogiri (1.6.6.2) mini_portile (~> 0.6.0) optionable (0.2.0) origin (2.1.1) puma (2.11.1) rack (>= 1.1, < 2.0) rack (1.6.0) rack-test (0.6.3) rack (>= 1.0) rails (4.2.0) actionmailer (= 4.2.0) actionpack (= 4.2.0) actionview (= 4.2.0) activejob (= 4.2.0) activemodel (= 4.2.0) activerecord (= 4.2.0) activesupport (= 4.2.0) bundler (>= 1.3.0, < 2.0) railties (= 4.2.0) sprockets-rails rails-deprecated_sanitizer (1.0.3) activesupport (>= 4.2.0.alpha) rails-dom-testing (1.0.5) activesupport (>= 4.2.0.beta, < 5.0) nokogiri (~> 1.6.0) rails-deprecated_sanitizer (>= 1.0.1) rails-html-sanitizer (1.0.1) loofah (~> 2.0) railties (4.2.0) actionpack (= 4.2.0) activesupport (= 4.2.0) rake (>= 0.8.7) thor (>= 0.18.1, < 2.0) rake (10.4.2) rdoc (4.2.0) json (~> 1.4) sass (3.4.12) sass-rails (5.0.1) railties (>= 4.0.0, < 5.0) sass (~> 3.1) sprockets (>= 2.8, < 4.0) sprockets-rails (>= 2.0, < 4.0) tilt (~> 1.1) sdoc (0.4.1) json (~> 1.7, >= 1.7.7) rdoc (~> 4.0) slim (3.0.2) temple (~> 0.7.3) tilt (>= 1.3.3, < 2.1) slim-rails (3.0.1) actionmailer (>= 3.1, < 5.0) actionpack (>= 3.1, < 5.0) activesupport (>= 3.1, < 5.0) railties (>= 3.1, < 5.0) slim (~> 3.0) slop (3.6.0) spring (1.3.2) sprockets (2.12.3) hike (~> 1.2) multi_json (~> 1.0) rack (~> 1.0) tilt (~> 1.1, != 1.3.0) sprockets-rails (2.2.4) actionpack (>= 3.0) activesupport (>= 3.0) sprockets (>= 2.8, < 4.0) temple (0.7.5) thor (0.19.1) thread_safe (0.3.4) tilt (1.4.1) tzinfo (1.2.2) thread_safe (~> 0.1) uglifier (2.7.0) execjs (>= 0.3.0) json (>= 1.8.0) web-console (2.0.0) activemodel (~> 4.0) binding_of_caller (>= 0.7.2) railties (~> 4.0) sprockets-rails (>= 2.0, < 4.0) PLATFORMS ruby DEPENDENCIES angularjs-rails bootstrap-sass byebug coffee-rails (~> 4.1.0) jbuilder (~> 2.0) jquery-rails mongoid puma rails (= 4.2.0) sass-rails (~> 5.0) sdoc (~> 0.4.0) slim-rails spring uglifier (>= 1.3.0) web-console (~> 2.0)
Angularが悪いんじゃなくて使い方が間違ってるんだという話
最近いろんな案件や記事でAngular.jsを耳にしますが、結構「あれ使いにくいよね」などという話もちらほら。 実際ぼくが使っていてもなんだか使いにくく感じることがままあります。
多少触ってみたり考えてみたりして、僕なりの結論めいたものが見えてきたので記事にしてみようとおもいます。
サーバーサイドレンダリングとクライアントサイドレンダリング
perl, PHP全盛期
古来(?)、perlやPHPの時代、多くのWebページは手打ちのHTMLで出来ていました。 この中で、フォームなどの機能をちょっとだけ追加したい、などの要請から、HTMLに直接ちょっとだけコードを埋め込めるPHPが一斉を風靡しました。
Rails全盛期
PHPによるWebアプリケーションが盛んになってくると、そのプログラムに重複する部分が多いことや、設計・実装をパターン化することで効率化が図れることがわかってきて、Ruby on RailsなどをはじめとするMVCフレームワークが登場しました。
大事なのは、ここまでずっと「サーバー側でHTMLを生成して、動的な要素はその中に埋め込まれていた」ということです。
Twitterの公開APIとスマートフォン向けアプリの拡大、プラットフォームの多様化
TwitterがAPIを公開し、サードパーティが自由に対応アプリを開発できることが、多様なアプリケーションを生むようになりました。 これとほぼ同時期にスマートフォンが普及し、そういった複数プラットフォームへの対応が要請されるようになりました。
その中では、すべてのWebでやろうという流れも強く、未だにその流れもありますが、レスポンスの悪さなどから好かれない傾向にあるようです。
補足
- そもそもゲームとかだとRPCが当たり前のようにやられてたので、そこから輸入した考えではある
- スマホの台頭以前からデスクトップアプリでは必要なことでしたが、やはりスマホ以後で大きくこの状況が動いたというのはあると思います。
SPAという提案 (Single Page Application)
スマートフォンアプリが発達してきたことで、Webサービスというものの捉え方は変わり、(大抵はJSON+HTTPの)APIこそがWebサービスである、という考え方が出てきました。 また、Webページより先にアプリ側を作ることも増えてきたので、じゃあどうせなら、アプリ側でシッカリ作ったAPIをWebでも使えたら、セキュリティの問題もHTMLよりは考えやすくなるし、良いことづくめじゃないか。 じゃあ、もうページの遷移すらやめてしまって、全ページをJSでレンダリングするという考え方で作ってもいいんじゃないか。 HTML/CSS/JSはクライアントサイドのもので、サーバーとはAPIで通信する。HTML/CSS/JSは静的なサーバーから配信すれば十分高速だろうし、API通信で重い部分はきちんとUIで解消していけばいいじゃん、行ける行ける!
…と、SPAが生まれるまでは、こんな流れなんじゃないでしょうか。
結論「AngularのSPA的アプローチと静的HTML生成アプローチの混在が混乱を招く」
さて、そういわけで結論にすっとばします。
Angularなどを使ったSPA的なアプローチは、バックエンドが全てJSONのAPIで構成されていることを前提にしている。 だから、APIベースで考えずにviewレイヤでHTMLをレンダリングする過去のアプローチと混ぜてはいけない。 SPAで重要なのは、API側とビュー(クライアント)側が疎結合になり、それぞれ独立して開発を進められるようにすること。
わかってる人には当たり前のことなんだと思うんですけど、今のところの自分の解釈をざっと書いてみました。 この辺り、まだまだ流動性の高い部分なのでこれからも変わっていくと思います。コメントもお待ちしておりますので、いろいろ考えを深められたら、と思います。
RailsやMiddleman で自動的に目次を作るにはどうすればいいのか
せっかくなのでブログでも共有しておく。
@AknEp あおかんオススメのmiddleman使って見てるんだけど、ページ内のh2要素一覧から自動で目次作るような機能 or ハックできそうなヒントとかないですかね?ぐぐらびりてぃ低くて泣いてる
— (´・ω・`){;:} rm -rf ~ (@syonbori) 2014, 10月 7
お世話になってる先輩が泣いているのは忍びなかったので適当にサンプルコードをつくった。
考え
リポジトリにも書いたんだけど、以下の様な感じで考えて作った。何かの参考になるかもしれないので公開しておく。
目次の責任範囲はどこにある?
- テンプレートエンジン、ジェネレータ
- そういう考え方もある
- h2の代わりになるタグをヘルパで定義して使う
- Dirty! Dirty! Dirty!
- 再利用性低すぎ!
- レイアウトファイル
- あ、行けそう
ということでレイアウトファイルが目次を作るのはそれなりにアリだと思います。
拡張の仕方
- レイアウトファイルの中の処理をゴリゴリ書く
- レイアウトファイルの中の処理をHelperに切り出す
例:ヘッダへのリンクが貼りたい
- ヘッダにname要素やid要素をつける (どうせセマンティック的には自分でつけるべき)
- パースした方でゴリ押し
ISUCON4 予選に出てきた
去年に引き続いて今年もISUCON4の予選に出ました。
去年は学生だったので @cnosuke , @rkmathi と一緒に出てたのですが、 今年は学生じゃないので @syu_cream , @suma90h と一緒に出ました。チーム名は「SSS」 (僕の本名、彼らのアカウント、の頭文字がすべてSなので。) 僕がタイミング悪く沖縄に出張していて、合流出来ずリモート参戦でご迷惑おかけしちゃいました。
前回はプログラムの方にいろいろとバグがあったのですが、今回はコード自体は普通に動くようにできていたという印象です。 寧ろ、改変したSQLにバグがあったりして3時間ぐらいドブに捨ててしまったのが痛かったです。 8時間って短いですねぇ、やっぱり。
mysqlのCPU負荷が異常に高かったのでインデックスを貼ってみた所で劇的に解決しました。 コードの改変より先にそっちをやれば良かったですね。
16:50時点でのスコアが4426しかなくて、こりゃあお通夜だなーと思っていたら、後半いろいろ頑張ったら結果としては25348ぐらいまで向上しました。 それほどインフラ特化じゃないプログラマーのチームとしては、悪くないんじゃないでしょうか。
主にやったこと
- nginx チューニング
- syu_cream がやってくれた
- 静的ファイルはnginxで返す
- worker_processは1で同時接続数は1024ぐらいにしてた
- gz圧縮の話もあったけど、ベンチマークがローカルで動いていることから逆効果かなと思って止めた
- mysql のパラメータチューニング
- 参考にしたサイト: DSAS開発者の部屋:5分でできる、MySQLのメモリ関係のチューニング!
- mysql へのインデックス追加
- わりと順当に login_log の ip と user_id それぞれにインデックスを追加しただけ
- unicorn のプロセス数と mysql の max_connections のチューニング
- puma への変更
- 最終的にスレッド5つ、プロセス4つに落ち着いた
- TCP(OS)のパラメータチューニング
やってみたかったけどできなかったこと
- MySQLのvarchar(255)になっているカラムの長さを調節
- login_log の login とか、 (24) にすれば良かった気がする
- booleanで良い部分が tinyint(4) になっていた所も似たような話
- ベンチマーク直前のウォームアップ時
- きちんとボトルネック解析
- 結局、せいぜいtopを見る程度で、細かくボトルネックを解析できなくて、場当たり的でした
感想
去年も言ったけど、こういうパフォーマンスチューニングも面白いですねぇ。 勉強になるので、来年も参加したいなーと思っています。
一緒に参加してくれた @syu_cream さん、 @suma90h さん、ありがとうございました!
DTI@VPS 上のRailsからSendGridを使うとタイムアウトする問題の解決策
Railsからのメール送信にSendGridを使う様に変更してたら起きた問題。誰かの役に立つかもしれないので、メモ。
遭遇した現象とか雑多気味なメモ
SendGridの通例通りsmtpの設定をしてみた、けれどうまく送信されないという現象に遭遇。 同じコードをローカルで立ち上げるとちゃんとメールが送られる。なんじゃこりゃ。と。
動作を見る限りでは、タイムアウトの気配なので、おもむろに以下の様に確認した。
$ telnet smtp.gmail.com 465
まずビンゴで、telnetが通っていない事が判明。
試しにufw disable
すると、上記のtelnetが通った。
→ 原因がファイヤーウォールに搾られた
次に iptables -L
してやると、ESTABLISHED,RELATEDが読まれていない事が確認できる。何か変だぞ、と。 他の似たような設定を為ている環境でiptables -Lした結果と全然ちがう。
ここで、試しに以下の様にしてみる。
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
すると、きちんと繋がる。
(しかしここではufw経由で設定出来ないと困るなーと思っていたら、うっかりiptables -F
しちゃってサーバーからSSHがBANされたので、一回VPSの管理コンソールから再起動。)
その他の途中で見てた不穏なエラーメッセージ
検索でだれかが行き着くように、遭遇した不穏なエラーメッセージを書いておく。
problem running ufw-init # とか… iptables: Bad rule (does a matching rule exist in that chain?). # とか…
結論
どうやら OpenVZ環境でufw を使っていると起きるらしい。 (DTIはOpenVZ、らしい)
そういうわけで、以下のサイトの内容の通りにしたら上手く動作してくれました。
Angular.js と Rails の form_for を良い感じに連携する
最近とある案件で Angular.js を使い始めたのですが。
どうにもRailsと相性がそこまで良くないというか、2つの世界をCoCで繋ぐ決定的なgemなどが出てきていないからか、不便さを感じます。
そんな中で、特に不便に感じたのが、form_for がロクに使えないことでした。
$ rails g model post title:string
みたいなモデルを想定してください。
愚直にやると、Angualr.jsで非同期にPOSTする時のformは、こんな感じになってしまいます。
# slim記法の例 div 'ng-controller'=>'PostCtrl' = form_for(@post, html:{ 'ng-submit'=>'submit()' }) do |f| = text_field :title, 'ng-model' => 'post.title' = button :submit end
うーん、何かこう、いけ好かないですよね。 同じ様な事を何回も書いてるし…
ということで、こんなのを作ってみた。
# /app/helpers/angular_form_builder.rb # http://uzuki05.hateblo.jp/entry/2013/04/05/114356 class AngularFormBuilder < ActionView::Helpers::FormBuilder def ng_text_field(method, options = {}) options[:html] ||= {} @template.text_field(@object_name, method, objectify_options(options[:html].reverse_merge!(ng_options(method)))) end # TODO: text_field 以外の互換メソッドも用意しましょう private def ng_options(method) { 'ng-model' => "#{@object_name}.#{method}", } end end
# /app/helpers/application_helper.rb module ApplicationHelper def ng_form_for(*args, &proc) args << {} unless args.last.is_a?(Hash) options = args.last if args.first.is_a?(Symbol) options.merge!(as: args.shift) end options.reverse_merge!( builder: AngularFormBuilder, format: :json, html: { 'ng-submit' => 'submit()' } ) form_for(*args, &proc) end end
これを使うと、フォーム部分は以下の様に書けます。
# slim記法の例 div 'ng-controller'=>'PostCtrl' = ng_form_for(@post) do |f| = ng_text_field :title = button :submit end
あとは、Angular.jsのControllerをこれに準拠して書いていけば、それなりに柔軟さを保ちつつ、RailsのFormBuilderだけで概ね記述できて良いんじゃないかな、と思います。
ちなみに、CSRF対策については以下のStackoverflowでの議論に準拠すると良いと思います。
Angular.js触って2日目ぐらいなので、もっと良い方法あったらおしえてください!