読者です 読者をやめる 読者になる 読者になる

ほろ酔い開発日誌

有意義な技術的Tipsを共有出来たら嬉しいです。Ruby、Railsが好きです。Web開発全般(Rails多め、フロント、サーバー、インフラ)、データ分析、機械学習あたりの記事が中心になる予定です。

大学生がプログラミングをはじめる方法

最近更新がなかったので久々の投稿です。。 Qiita(shizuma) に書いちゃうんですよね。こちらもちゃんと更新したいところです。

さて、今回はいつも書くような技術のお話とはちょっと違うことを書いてみたいと思います。テーマは「大学生がプログラミングをはじめる方法」です。

プログラミングに興味があるけど、はじめの一歩が踏み出せない。そんな方に少しでも役立つと幸いです。

ちなみに、ここでいうプログラミングとはWEB系のプログラミング、nativeアプリ、あとは機械学習等など、僕がやった範囲を想定しながら書いていることを予めお伝えしておきます。

僕自身大学生になってからはじめてプログラミングを勉強し始めました。興味があれば是非これからはじめましょう!

どうやってはじめるか

  1. 独学 (書籍)
  2. 独学 (WEBサービス)
  3. プログラミング教室
  4. 勉強会
  5. インターン・アルバイ

1. 独学 (書籍)

最初に思いついつくのは独学です。

僕は結構、本を使って勉強するのは好きです。ただし、いきなり初学者が本を取り出すと上手くいかない可能性は高いと思います。それは、自分に合う本がどれか分からないからです。もし、身近に詳しい方がいて教えてもらえる環境であれば良いのですが独学の場合は難しいですよね。 プログラミングに慣れてきたらいろんな本を手にとって見て下さい。

2. 独学 (WEBサービス)

最近?では様々なプログラミングを学ぶためのサービスがあります。しかも基本的には無料のものも多いです。一旦ここからはじめて感覚を掴むのは良いと思います。

ドットインストール

http://dotinstall.com/

まずは、3分動画のドットインストールです。僕も一番最初にこの動画を見た覚えがあります。様々な言語がありますし、初心者でも分かりやすい説明で定番ともいえるサイトです。(基本無料)

Progate

prog-8.com

ブラウザ上で実際にコードを書いて学んでいくスタイルの学習サイトです。カリキュラムもどんどん増えてきて勢いがあります。ドットインストールより実践的なイメージです。こちらもおすすめです。(基本無料)

Udemy

www.udemy.com

オンラインの動画学習サイトです。基本お金がかかりますが、カリキュラム立っていて学習しやすかったり、サポートがしっかりしているなどおすすめです。質問したら作者の方から翌日には回答されました。日本ではドットインストールやProgate程使われてない気がしますが(個人の感覚)、自分にあった講座に出会えると思います。

Coursera

www.coursera.org

海外の有名大学の講師が提供してくれる授業です。英語ですが日本語字幕もあります。(全てではないかもしれませんが)理論的なところが多い気がするので一番最初は他のサービスのほうがいいかもしれません。

他にも色々なものがありますが、有名で個人的におすすめな4つのサービスでした。

公式のTutorial

公式のTutorialは各種あります。例えば、Railsチュートリアル等、役立つものがたくさんあります。

railstutorial.jp

ただし、一番最初はやめておいておいたほうがいいかなと思います。ひとつはプログラミング言語を知った上で新しく違う言語をはじめるときはいいかと思います。

プログラミング教室

TECH::CAMP

tech-camp.in

世の中には現在たくさんのプログラミング教室があります。従来の塾のような授業形式のものよりも実践型のものが勢いがあると思います。その中でおすすめはTECH::CAMPです。なぜ、おすすめできるかというと、自分が通った&メンターをしていたから良さを知っているからです。他社のプラグラミング教室には通っていないので比較は出来ないですが、少なくともTECH::CAMPで失敗はないです。カリキュラムの質や質問のしやすさもいいですし、仲間が出来ることも大切です。

お金はかかりますが、独学よりも手っ取り早く学ぶことが出来ると思います。

勉強会

僕自身は、勉強会の情報は今はSNSから入ってきたり、人からの紹介が多いですがはじめのうちは以下のようなサイトを頼るといいでしょう。

dots

eventdots.jp

勉強会の紹介サイトです。dots自体も渋谷にコミュニティスペースがあり、勉強会が開催されています。学生部といったコミュニティもあるので興味があれば是非参加すると良いと思います。学生部に入ると1日いても500円で最高の環境でプログラミング出来ますよ。

conpass、doorkeeper

connpass.com

www.doorkeeper.jp

dotsと同じような勉強会のサイトです。僕は能動的にこの2つのサイトで勉強会は探すことは少ないですが、前はまあまあ見てた気がします。

TECH SALON

tech-salon.com

最近勢いがある学生向けの勉強会コミュニティです。イベントが月に20本以上やっているので気になるものがきっとあると思います。仲間も出来ると思うのでかなりおすすめです。僕も機械学習関係は行っています。

インターン・アルバイ

Wantedly

www.wantedly.com

おすすめ度が高いです。ここに載っているものは面白そうなものが多いです。また、今勢いがある会社も多いので、モダンな開発が出来る可能性も高いです。募集自体もどんな技術が使われているか等わかりやすいです。まずはプロフィールを書いて、興味がある会社に話を聞きに行ってみてはいかがでしょうか?スカウトされることもあります。

ニクリーチ

29reach.com

肉を食べたい。そんな軽い気持ちで登録しておくと会社から連絡が来るというなんともお得なサービスです。意外と?連絡がきてアルバイト等に結びついたのでおすすめです。とりあえず登録だけでもどうぞ。

サポーターズ

supporterz.jp

企業から支援金をもらって就活しよう的な就活風味のきいたサービスです。学部3年生とかであればここで会社の人と仲良くなってインターン・アルバイトしてみるといいかもしれません。

goodfind

www.goodfind.jp

こちらも就活風味が強いですが、インターンを探せます。勉強会も探せます。前は使っていたこともありますが、最近はほとんど使っていません。

紹介・その他

知り合いから紹介されると良いですが、はじめはなかなか難しいかもしれません。 ちなみに、僕がはじめてインターンに行った会社はセミナー終わりに直接スピーカーの方に話にいってそこでインターンが決まりました。積極的に社会人の方に話してこういうことがしたいっていうことを伝えるとスキルがなくても「うちでおしえてあげるよ」ってことになる可能性はあります。

継続させるためには

さて、勉強をはじめても続けないと意味がありません。以下のようなことを意識的・積極的にやってみてはいかがでしょうか。

  • 勉強会に定期的に出る
  • 有名人をfollow
  • QiitaやBlogに成果を書く
  • コミュニティに入る
  • サービスを作る
  • インターン・アルバイトに行く

プログラミングをはじめる目的は色々あると思います(作りたいサービスがある、他の人に差をつけるスキルが欲しい、就職に役立つ、一儲けしたい、なんとなく、etc...)。いずれにせよ、今回紹介したことを参考にしてはじめてみることがまず大切かと思います。(勿論、その後の継続も)

Rails サイト内検索機能を作った (AND検索にも対応)

サイトの記事数が増えてきてサイト内検索が欲しくなりました。というわけで検索機能を実装するためのgemのransackで検索機能を実装することにしました。

github.com

今回やろうと思っているのは記事のタイトル検索が出来ればいいなーと思っています。あと検索のときに空白で区切ってAND検索になるようにしたいと思います。

ひとまず、gemを入れます。

gem 'ransack'

それで、今回やりたいことを整理します。

  1. 全ページのヘッダーに検索窓をつける。
  2. /search?q=hoge みたいな感じでqueryを渡す。
  3. 検索ページに検索結果を表示する。

1. 全ページのヘッダーに検索窓をつける。

好きなように検索窓を作ってしまいます。「q」でvalueをgetメソッドで渡すのでその部分は注意してください。(qはqueryとか何でもいんですが)

= form_tag search_index_path, method: 'get' do
  = text_field_tag :q, '', placeholder: "気になるワードを入力"
  = button_tag type: 'submit' do
    %i.fa.fa-search

あと、classとかつけてstyle付ければいいですね。僕はfont-awesomeとか入れるの好きですが何でもいいですね。お好きに。

2. /search?q=hoge みたいな感じでqueryを渡す。

それで、ひとつ注意があって単純にgetメソッドをつける以下みたいな余計なqueryがくっついてきてしまうことです。カッコ悪いですね。。

/search?q=hoge&utf8=✓&commit=submit

というわけで解消します。以下のサイトを参考にします。

www.mk-mode.com

まず、commitなんちゃらのほうを取り除きます。button_tagに name: nil のオプションを渡すだけです。うん、簡単。

= form_tag search_index_path, method: 'get' do
  = text_field_tag :q, '', placeholder: "気になるワードを入力"
  = button_tag type: 'submit', name: nil do
    %i.fa.fa-search

で次にconfig/initializer に以下のファイルを作ればuft8なんちゃらが消えます。

module ActionView
  module Helpers
    module FormTagHelper
      def utf8_enforcer_tag
        "".html_safe
      end
    end
  end
end

これでオーケー!

3. 検索ページに検索結果を表示する。

  def index(q, page=1)
    @q = q
    query_arr = q.split(/[[:blank:]]+/)
    @search = Article.ransack(title_cont_all: query_arr)
    @articles = @search.result.published.newest.page(page)
  end

以下で詳しく解説します。

query_arr = q.split(/[[:blank:]]+/)

qは受け取ったqueryですが、空白で切り分けて配列にします。splitの引数に入れたやつで区切ってくれます。はじめ普通に /\s/ のようにすれば空白区切り出来るかと思ったのですが全角に対応出来ないみたいだったので探してみたらこんな感じでいけました。

 Article.ransack(title_cont_all: query_arr)

Articleというテーブルに ransack というメソッドをgemの力をかりて実行します。 title_cont_all というオプションで値にqueryの配列を与えるとそれら全てを含む記事を引っ張ってくれます。 title_cont_allの部分なのですが(検索するcolumn名)_cont_allの意味で、今回はtitleカラムを使いましたが適宜変更可能です。

それで後は好きに加工して表示させちゃってください! ( 上記サンプルコードは、action_argsとかkaminariといったgemを使ったことがコードに反映されてます。)

これで完成です!

正直まあこの程度の検索ならgem使わなくても...とか思ったりもしたのですが、and検索とかあとひらがなでもカタカナでも取得してくれたりとか簡単に出来るので入れてみると便利だなとか思いました!

Rails使うときほとんど正規化考えないよね

正規化とはRDBにおいてデータを適切に管理するための手順です。

正規化

まずはさらっと正規化を考えます。 正規化は以下の手順で行っていきます。

  • 第一正規化
  • 第二正規化
  • 第三正規化
  • ボイスコッド正規化
  • 第四正規化
  • 第五正規化

第一正規化

  • 同一の内容の行が複数存在することはない
  • 候補キーが存在する

候補キー

特定の行を識別することの出来る項目を候補キーといいます。「候補」というのは主キーとなる候補という意味合い。主キーは候補キーの条件+「null値を持たない」という条件がつきます。

第一正規化は普通にすれば普通に出来るはずです笑 表で考えた時にひとつのセルに3つ項目入っているとか変なことをしなければ大体できてると思います。

第二正規化

  • キーに対する部分関数従属がない

キーの一部が決まることで一意に決まる非キー属性がないというと分かりやすいかと思います。 キーは複数あることがあります。以下の様な項目を持つテーブルを考えるときitem_idとorder_idがキーであるとします。

  • item_id
  • order_id
  • name
  • price

このときitem_idが決まれば name、priceは一意に決まっていまいます。これはもうひとつのキーであるorder_idとは関係なく決まります。item_idとorder_idの2つが決まってはじめて他の項目が決まることを完全関数従属といい、例のようにキーの一部で他の項目が決まってしまうことを部分関数従属であるといいます。

第二正規化ではこの部分関数従属を別テーブルに分解して部分関数従属をなくします。

第三正規化

  • 非キー属性の関数従属をなくす

Booksテーブルがあったとしてtitleをキーとします。

  • title
  • writer_name
  • writer_birth_day

writer_nameが決まればwriter_birth_dayが一意に決まります。これが非キー属性での関数従属です。 なのでこの部分を別テーブルに分けることが第三正規化となります。

ボイスコッド正規化

ボイスコッド正規化以下は簡潔に。 ボイスコッド正規化までくると、主キー同士の関数従属も排除します。

第四正規化

第四正規化と第五正規化は非キー属性をもたないキー属性のみのテーブルにのみ適用します。

多値従属性を考える必要があります。 対称性のある多値従属性を分解します。

第五正規化

対称性のない場合の多値従属性も考えます。

第四正規化と第五正規化は以下がわかりやすいので参照下さい。 http://www.atmarkit.co.jp/ait/articles/0605/11/news124_4.html

Railsの正規化

Railsはテーブルを設計するときに、「id」というキーが単独のprimary keyとなります。第一正規化はまあ普通にやれば出来ているとして、キーが単独なので第二正規化、ボイスコッド正規化、第四正規化、第五正規化は考える必要がなくなり、第三正規化だけ考えればよさそうです。 「id」を使うようになった背景や詳しい理由は気になるところなので参照記事や書籍を是非ご紹介頂きたいです。

Imagemagickをupdateしたらrmagickに怒られたから直した

imagemagick脆弱性が見つかってわちゃわちゃしてますね。

ImageMagick の脆弱性 (CVE-2016-3714) に関する注意喚起

rubyでいうとrmagickとか普通に使うので古いimagemagickに依存してたらよくないですね。というわけでimagemagickをupdateしてみた。 そしたらなんかエラー >< (rails s でサーバー立ち上げるとき)

This installation of RMagick was configured with ImageMagick 6.9.0 but ImageMagick 6.9.4-1 is in use. (RuntimeError)

あれ、rmagick対応出来てないのかな?とか一瞬思ったのですが、なんか 6.9.0 にconfiguredされちゃってるらしいのでインストールし直してみた。

$ gem uninstall rmagick
$ gem install rmagick

そしたら直った!!(reinstallとか出来たっけ?) imagemagickのバージョン変わったらrmagickはインストールし直す必要があるんですね。

Pythonの環境構築 Anaconda 蛇をアナコンダに強化した

これまでpythonをそこまでたくさん使わなかったのでそんな気にしなかったですけど、そろそろちゃんと使うようになったのでちゃんとpythonを使いやすくしとこうと思います。

なかなか良さ気な記事があったのでこれを参考にしました。

qiita.com

anacondaは、pythonのパッケージをまるっとまとめてインストールしてくれる便利なやつみたいです。というわけでanacondaをインストールします。

ただ、今後2系と3系を都合によって分けなきゃいけないので2系のanacondaと3系のanacondaどっちも管理したかったのです。

それで、この記事にあるようにpyenvを入れてその中で複数のanacondaを管理すればオーケーでした。 pyenvはRubyでいうrbenvとかRVMですね。そのなかで簡単にバージョンを切り替えられます。

$ brew install pyenv
$ echo 'export PATH="$HOME/.pyenv/bin:$PATH"' >> ~/.bash_profile
$ echo 'eval "$(pyenv init -)"' >> ~/.bash_profile

$ exec $SHELL -l

僕の場合、元々普通にpythonのパスを通した時のコードが .bash_profile に残っていたのでそいつはコメントアウトしておきました。

$ pyenv install -l

これでインストール出来るバージョンを見て、新しそうなやつ入れます。

$ pyenv install anaconda-2.4.0
$ pyenv install anaconda3-2.4.0
$ pyenv global anaconda3-2.4.0 #とりあえず使うバージョンを設定
$ python --version
  system
  anaconda-2.4.0
* anaconda3-2.4.0 (set by /Users/seishin/.pyenv/version)

二匹のアナコンダがいれば大丈夫です。

あとは好きなときに違うアナコンダを出してあげればいいです。

$ pyenv global anaconda-2.4.0

なんかrbenvと同じ感覚なので抵抗ないです。 globalだけじゃなくてlocalもいけるらしいです。

こちらの記事でアナコンダの使い方みたいなの載ってたので参考になるかもしれません。(まだやってない)

qiita.com

以上、pythonの環境構築でした。 ひとまず、ipython notebookで動き出すとします。

$ ipython notebook

GooglebotのUA変更の影響を受けた1%に見事に含まれたお話

事の発端は、自分のサイトを検索にかけたときにURLの下に「このサイトはスマートフォン対応されていません」のような文言があることに気づいたことです。

このサイトではPCとスマホはViewを切り分けているのでばっちり対応していたので「えっ?」って感じでした。

サイトがスマートフォン対応されていることがSEOに関係することは公式のページを見ても分かるので対応する必要がありました。

Google ウェブマスター向け公式ブログ: 検索ユーザーがモバイル フレンドリー ページを見つけやすくするために

そもそもなんでこんなことになったかというと、2016年3月18日に勧告されているGooglebotのUA変更をもろに受けた結果です。

Google ウェブマスター向け公式ブログ: Googlebot のスマートフォン用ユーザー エージェントの更新について

これまでのGooglebotのスマートフォンUAは「iPhone」でしたが、それが「Android」に変更されました。

ただし、Googleによるとサイトの99%は影響を受けないと言われています。もし、影響を受けるのであればそれは「クローキング」の一形態であるとまで言われています。

Google の評価によると、今回のユーザー エージェントの変更は 99% のサイトで影響がない見込みです。サイトが影響を受ける場合に最も多い理由として考えられるのは、そのサイトが Googlebot の特定のユーザー エージェント文字列を期待している場合です。Googlebot に対するユーザー エージェント スニッフィングは推奨されておらず、クローキングの一形態と見なされます。Googlebot は他のブラウザと同様に扱ってください。

それで今回のサイトがどのようにViewを切り替えているかというと以下のgemの下記メソッドで切り分けています。

request.from_iphone?         # true if it comes from iphone
request.from_ipad?           # true if it comes from ipad
request.from_android?        # true if it comes from android mobile
request.from_android_tablet? # true if it comes from android tablet
request.from_windows_phone?  # true if it comes from windows phone

github.com

ただし、これだとうまくGooglebotに対応してくれないので、以下のようにGooglebot用にメソッドを用意していました。クローキングをしたい訳では全くないのですが個別に対応することになってしまっています。

  def google_mobile_bot?
    request.browser == 'Googlebot' && /iPhone/ === request.user_agent
  end

これを見ると分かるように「iPhone」から「Android」に変わってしまうとこのメソッドはGooglebotのスマートフォンのアクセスに対してfalseを出してしまいます。 対応として「iPhone」、「Android」どちらともいけるようにメソッドを作りました。

  def google_mobile_bot_android?
    request.browser == 'Googlebot' && /Android/ === request.user_agent
  end

  def google_mobile_bot_iphone?
    request.browser == 'Googlebot' && /iPhone/ === request.user_agent
  end

このようにすると無事に以下のフレンドリーテストをクリアしました!

モバイル フレンドリー テスト

今回はGooglebotのUA変更の影響を知らないうちに受けていましたが、ひとまず対応出来たのでよかったです。 気づいていなかったら、スマートフォンの検索順位落とされていたと思うと恐ろしいですね。。

2016年5月12日から、モバイルフレンドリーであることがgoogleの検索順位により大きく影響を受けるようにアップデートされたので未対応の場合は早急に対応が必要ですね。

meshrepublic.com

ELBとEC2-2台で冗長構造を作ってみた Nginxのconfを紹介

前回capistranoで2台のproductionサーバーにdeployした続きの記事です。

seishin55.hatenablog.com

メモ書き程度に書いておきます。 とりあえず、ELBを用意しました。ELBでEC2の2台を繋げてあげて出来るかなと思ったのですが挙動が変でした。(heathチェックを/healthにしてました) (Nginx + Unicorn + Rails)

それで結論からいうと、最終的には以下のようなconfになりました。

/etc/nginx/conf.d/horoyoi.conf

# log directory
  error_log  /var/www/rails/horoyoi/current/log/nginx.error.log;
  access_log /var/www/rails/horoyoi/current/log/nginx.access.log;
  # max body size
  client_max_body_size 2G;
  server_names_hash_bucket_size  128;
  upstream app_server {
    # for UNIX domain socket setups
    server unix:/var/www/rails/horoyoi/current/tmp/sockets/.unicorn.sock fail_timeout=0;
  }
  server {
    listen 80;
    server_name horoyoi.com 52.222.23.22 sakamichi-app-elb-20323346271.ap-northeast-1.elb.amazonaws.com 10.0.*;
    # nginx so increasing this is generally safe...
    keepalive_timeout 5;
    # path for static files
    root /var/www/rails/horoyoi/current/public;
    # page cache loading
    try_files $uri/index.html $uri.html $uri @app;
    location @app {
      # HTTP headers
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Host $http_host;
      proxy_redirect off;
      proxy_pass http://app_server;
    }
    location = /health {
      # HTTP headers
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Host $http_host;
      proxy_redirect off;
      proxy_pass http://app_server;
      access_log off;
    }
    # Rails error pages
    error_page 500 502 503 504 /500.html;
    location = /500.html {
      root /var/www/rails/horoyoi/current/public;
    }
  }

/healthのところはヘルスチェック用ですが、もうちょっと綺麗に書けると思うので良い書き方教えて下さい笑

それで今回ハマったのは

server_name horoyoi.com 52.222.23.22 sakamichi-app-elb-20323346271.ap-northeast-1.elb.amazonaws.com 10.0.*;

server_nameです。はじめは 10.0.*という記述はなかったのですが、つけるとうまくいきました。

うまくいかなくて以下のようにしてlogを見てたら、10.0. ... というローカルIPからのアクセスがあってよくなさそうな感じだったのでserver_nameに 10.0. * とか入れてあげるとうまく動きました。

sudo tail -f /var/log/nginx/access.log

healthチェックは下記の記事が参考になりました。(unicornが落ちたら表示してほしくなかったので) http://blog.tnantoka.com/posts/75

僕はcontrollerで

def health
  head :ok
end

みたいにしてstatus 200を返しています。 さらった書いてしまったので、もっと丁寧に時間があるとき書こうかなとか思ったり。