【Rails】技術面接対策の記事の質問を多少深ぼる記事⑦
はじめに
こんにちは!大ちゃんの駆け出し技術ブログです。
この記事は前回の記事の続きものです。
(前回の記事)
本記事ではQ37 ~ Q42を深掘りします。
Q37: Railsのどういうところがキライですか?
回答:
私の場合は、機械学習系のライブラリ開発が乏しかったり存在しなかったりする点。
これについては正直回答ができないのでスキップします。。。RailsやRubyだけでなく他の言語も比較しないと嫌いところは答えられないと思うので。2年後あたりにはわかるのかもしれないです。
同様のトピックである下記記事はざっと読みましたが「へーそうなんだー」ぐらいの感想でしたね、、。
Q38: ご贔屓のRuby gemを教えて下さい
回答:
Rails開発者なら誰もがご存知のDeviseが好きです。認証のような複雑なものを2分でセットアップできるからです。
まず漢字が読めませんでした、、、、。ご贔屓(ごひいき)だそうです。要はお気に入りのgemはなんですかと言う質問ですね。
回答例はDeviseですが、自分はあまりDeviseは好きではないですね、、、。ブラックボックス過ぎて何が実際に行われているのがわからず、ログイン機能のカスタム性も優れていません。ポートフォリオではガッツリDeviseを使っていますが、Slackログインを実装するために仕方なく使っています。
個人的に1番好きなgemはbulletですかね。
GitHub - flyerhzm/bullet: help to kill N+1 queries and unused eager loading
こちらのgemはN + 1問題を検知してくれるgemです。以下のようにLogにN + 1問題が発生していた記録を残し、さらにはその解決方法まで提案してくれます。
[INFO] N+1 Query in /posts Post => [:comments] Add to your finder: :include => [:comments] # 解決方法 [INFO] N+1 Query method call stack /home/flyerhzm/Downloads/test_bullet/app/views/posts/index.html.erb:14:in `_render_template__600522146_80203160_0' /home/flyerhzm/Downloads/test_bullet/app/views/posts/index.html.erb:11:in `each' /home/flyerhzm/Downloads/test_bullet/app/views/posts/index.html.erb:11:in `_render_template__600522146_80203160_0' /home/flyerhzm/Downloads/test_bullet/app/controllers/posts_controller.rb:7:in `index'
自分はポートフォリオでテーブル数が20個で未経験にしてはかなり複雑なDB設計をしていました。
そのためActive Recordをたくさん使用していたのですが、N + 1問題がどこで起きてもおかしくないと思っていました。しかし、bulletを使用することでどこでN + 1問題が起きているかわかるので、N + 1問題の解決を容易に行うことができました!このgemがなかったらN + 1問題の修正地獄に追われていたことでしょう、、、、。
Q39: springについて説明してください
回答:
springはアプリケーションプリローダーであり、アプリケーションをバックグラウンドで実行し続けることでマイグレーションやrakeタスクを実行するときにアプリケーションの起動が不要になります。
springはRailsにデフォルトで入っているgemです。rails newしたらGemfileに既に記述されます。
group :development, :test do gem 'spring' gem 'spring-watcher-listen', '~> 2.0.0' gem 'spring-commands-rspec' end
一応公式のgemを見てみます。
Spring is a Rails application preloader. It speeds up development by keeping your application running in the background so you don't need to boot it every time you run a test, rake task or migration.
[訳] Springは、Railsアプリケーションプリローダーです。アプリケーションをバックグラウンドで動作させておくことで、テストやrakeタスク、マイグレーションを実行するたびにアプリケーションを起動する必要がなく、開発をスピードアップしてくれます。
ほとんど回答例と同じような説明をしていますね。
前もってロードしておく(preload)とあるように実行するたびに再起動するのではなく常に起動しておくことで、処理が呼び出された際に実行するスピードを早めてくれるということです。
例えば、あるテストファイルを実行するとします。
起動時にはspringは走っていません。
$ bin/spring status Spring is not running.
テストファイルを実行します。
$ time bin/rake test test/controllers/posts_controller_test.rb Running via Spring preloader in process 2734 Run options: # Running tests: ....... Finished tests in 0.127245s, 55.0121 tests/s, 78.5887 assertions/s. 7 tests, 10 assertions, 0 failures, 0 errors, 0 skips real 0m2.165s user 0m0.281s sys 0m0.066s
springが起動します。
$ bin/spring status
Spring is running:
再度実行すると既にバックグラウンド側で起動している状態ですのでテストが早くなります。
$ time bin/rake test test/controllers/posts_controller_test.rb Running via Spring preloader in process 8352 Run options: # Running tests: ....... Finished tests in 0.176896s, 39.5714 tests/s, 56.5305 assertions/s. # 早くなっている 7 tests, 10 assertions, 0 failures, 0 errors, 0 skips real 0m0.610s user 0m0.276s sys 0m0.059s
Q40: アセットパイプラインについて説明してください
回答:
ブラウザで使われるJavaScriptやCSSを用意するフレームワークです。
ちょっと回答例が説明不足な気がしますね、、。
Railsのディレクトリ構造では画像、javascript、css、htmlの各ファイルは以下のように分割して配置されています。
画像 -> app/assets/images javascript -> app/assets/javascripts css(scss) -> app/assets/stylesheets html -> app/views
しかし、Railsではこれらのファイルを集約し一つのファイルにまとめる仕組みがあり、それがアセットパイプラインです。
もう少し詳しく説明します。よくある共通レイアウトのapplication.html.erbを見てみます。
<!DOCTYPE html> <html> <head> <title>Hoge</title> <meta name="viewport" content="width=device-width,initial-scale=1"> <%= csrf_meta_tags %> <%= csp_meta_tag %> <%= stylesheet_link_tag 'application' %> <%= javascript_include_tag 'application' %> </head> <body> <%= yield %> </body> </html>
javascript、cssのファイルをレイアウトに適用する記述は以下の2つです。
<%= stylesheet_link_tag 'application' %> <%= javascript_include_tag 'application' %>
stylesheet_link_tag
はapp/assets/stylesheets/application.scssをレイアウトに適用するように指定しています。javascript_include_tag
も同様にapp/assets/javascripts/application.jsをレイアウトに適用するように指定しています。各ファイルのデフォルトの記述は以下のようになります。
// application.scss * * This is a manifest file that'll be compiled into application.css, which will include all the files * listed below. * * Any CSS and SCSS file within this directory, lib/assets/stylesheets, or any plugin's * vendor/assets/stylesheets directory can be referenced here using a relative path. * * You're free to add application-wide styles to this file and they'll appear at the bottom of the * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS * files in this directory. Styles in this file should be added after the last require_* statement. * It is generally better to create a new file per style scope. * *= require_self *= require_tree
//= require rails-ujs //= require turbolinks //= require_tree .
ここで重要な記述は各ファイル共通して存在するrequire_tree
です。これにより同一ディレクトリにあるファイルを集約してファイル内に読み込みます。例えば、application.scssの同一ディレクトリにmain.scssやhogehoge.scssがあればそれらをapplication.scss内に読み込みます。結果require_tree
で個々のファイルを集約させたものが全体のレイアウトであるapplication.html.erbに適用されます。これが基本的なアセットパイプラインの仕組みです。
上述したscssとjsとは似ていませんが、画像ファイルの読み込みもアセットパイプラインの仕組みの中の一つです。以下のようにimage_tag
を記述します。
<%= image_tag "hoge.png" %>
上記のように記述するとapp/assets/imagesディレクトリのhoge.pngにアクセスできます。
Q41: Railsで認証を管理するときには何を使っていましたか
回答:
Deviseです。
回答例と同じようにDeviseですね、、、。理由としてはポートフォリオではどうしてもDeviseとOmniauthの組み合わせを使用しないと安全なSlack ログインを実装することができなかったので、、。
# Gemfile gem 'devise', github: 'heartcombo/devise', branch: 'ca-omniauth-2' gem 'ginjo-omniauth-slack', require:'omniauth-slack'
他の認証gemにsorceryがありますが、sorceryにもslackログインの機能があるようです。
しかし、こちらのファイルは2016年の12月より更新がされていないためか何度試してもエラーになりました。おそらくSlackの方で認証の方法が大きく変わっているためだと思われます。sorceryの方がカスタマイズ性が優れていて好きなので可能であればsorceryを使いたかったですね、、。
Q42: splat演算子について説明してください
回答:
splat演算子は、メソッドに渡される引数の数を事前に決めておきたくない場合に使われます。Rubyにはsplat演算子とdouble splat演算子**の2種類があります。 splat演算子は想像どおり以下のように動作します。
def do_sth(*input) input.each {|x| puts x } end do_sth(3,4,5) # => 3 # => 4 # => 5
def do_sth(**input) input.each {|k,v| puts v } end do_sth('a':3, 'b':4, 'c':5) # => 3 # => 4 # => 5
これはよく(*args)
とかでお目にかかるものでしょう。メソッドの引数の数を指定しない時に使われます。
def hoge(*args) args.each { |arg| p arg } end hoge("A", "B") => "A", "B"
eachで展開できるため予想できますが、渡された引数は配列となっています。
def hoge(*args) p args end hoge("A", "B") => ["A", "B"]
double splat演算子は見たことがありませんが使うタイミングが気になりますね。キーバリューを引数に取るので少し扱いが難しそうです。
def hoge(**args) args.each {|key, value| p value } end hoge fuga: "A", foo: "B" => "A", "B"
double splatでは引数の塊がハッシュとなります。
def hoge(**args) p args end hoge fuga: "A", foo: "B" => { fuga: "A", foo: "B" }
終わりに
今回はここまで!!!!
次回はQ43からです!
残りあと2回のブログで終わりそうです!