一意性制約はDB側で実現しなきゃ駄目

一意性制約をDB側で実現すべき理由

Railsチュートリアルに、 一意性制約はコード(Active Record)側ではなくてDB側で実装すべきという注意があったのでメモ。

理由は、以下のようなことが起こり得るから。

  1. 登録ボタンが素早く2回クリックされた場合にリクエストが2つ連続で送信される。
  2. リクエスト1は検証にパスするユーザーをメモリ上に作成する。
    リクエスト2も同様にメモリ上に作成する。
    (ここで valid? メソッドにより一意性の検証が行われるが、この時点ではどちらのデータもDBに登録されていないので通過してしまう)
  3. 結果、一意性の検証が行われているにも関わらず、同じメールアドレスを持つ2つのユーザーレコードが作成されてしまう。

対策

DB側で一意性制約を設定する。

class AddIndexToUsersEmail < ActiveRecord::Migration
  def change
    add_index :users, :email, unique: true
  end
end

rubyのmoduleメソッドの呼び出し方法

Rubyの module は慣れ親しんできたVB.NETのModuleとは 大分違うようなので整理しておこうと思います。

moduleのメソッドは関数として使えない

Rubyのmoduleのメソッドは普通に定義しただけじゃ、関数として使えない。

module ModTest
  def sayHello
    puts "こんにちは"
  end
end
# sayHelloをmoduleの外から実行すると・・
ModTest::sayHello()
#=> undefined method `sayHello' for ModTest:Module (NoMethodError)
# 呼び出せない・・

moduleのメソッドを呼ぶ方法

moduleのメソッドを呼ぶには、以下の3つの方法がある。

1. mixinを使う

別にclassを定義して、呼び出したい関数を含むmoduleをincludeする。 これがRubyで最も一般的なやり方らしい。 コードにするとこんな感じ。

class ClsTest
  include ModTest
  # ModTestをmixinします
end
# インスタンスを作ってincludeしたmoduleのメソッドを呼び出す
cls = ClsTest.new
cls.sayHello
#=> こんにちは

2. module_functionを使う

module_functionで関数として使いたいメソッドが指定できる。

module ModTest
  def sayHello
    puts "こんにちは"
  end
  # 外部から関数として使いたいメソッドを指定します。
  module_function :sayHello
end
# sayHelloをmoduleの外から実行すると・・
ModTest::sayHello()
#=> こんにちは

module_functionを実行すると以下の2つの処理が行われる。  ・インスタンスメソッドのprivate化  ・publicクラスメソッドの作成

なので、mixinでmodudleを取り込んだクラスから呼び出す為には、 スコープを public に戻してやる必要がある。

module ModTest
  def sayHello
    puts "こんにちは"
  end
  module_function :sayHello
    # module_functionを使うとインスタンスメソッドがprivate化されてしまうので、
    # mixinでも使う場合は public に戻してやる。
  public :sayHello
end

class ClsTest
  include ModTest
end

cls = ClsTest.new
cls.sayHello
#=> こんにちは

ただ、こういうふうに無理やりスコープを Public に戻すのが 正しいのかわからないので、とりあえずこれは使わないようにする。

3. クラスメソッドとして宣言する

ModuleもClassなので、当然クラスメソッドを定義できます。 だから、Classのクラスメソッドと同じようにこんな感じで定義可能です。

module ModTest
  class << self
    def sayHello
      puts "こんにちは"
    end
  end
end

ModTest::sayHello

簡単ですね。

まとめ

VB.NETにおける Module は関数定義を集めたもので、 ユーティリティ関数をまとめておくような使い方が一般的でした。 しかし、Rubyの module は主にクラス拡張の手段という感じですね。 だから、ここに書いた 2(module_functionを使う方法) や 3(クラスメソッドとして宣言する) 方法はあまり使うべきではないのかもしれませんね。。

社長失格

社長失格という本を読みました。

社長失格

社長失格

概要

本書は、1991年に「HotCafe」事業によりニュービジネス大賞を受賞したベンチャー企業ハイパーネット社の社長・板倉雄一郎氏が、その受賞からわずか6年後の1997年に37億円もの負債を抱えて自己破産するまでの軌跡が、当事者の目線で詳細に描かれているノンフィクション小説です。

Hotcafeとは何か?

ブラウザに広告枠をつけることで無料でネット接続を可能にするシステムです。
当時はISP事業を行っていたアスキーと提携してサービスを提供していたらしく、「アスキーインターネットフリーウェイ」という名前で知られていたようです。

なぜ倒産したのか?

ハイパーネット社は、Hotcafeをアメリカ全土に展開するための事業資金として、銀行から多額の短期融資を受けていました。
しかし、アメリカは愚か、日本でも当初の想定通りに利用者が伸びませんでした。
そんなときに、国から銀行の自己資本比率を上げるように通告が出て、
ハイパーネット社に融資していた各銀行は手のひらを返したように、返済を迫りました。
自己資本比率を上げるためには融資を引き上げてしまうのが一番てっとり早いので) 銀行の融資を当てにして事業拡大と会社の運営を行っていたハイパーネットとしては、
銀行の融資を引き上げられることは死活問題でした。
そして、結局、板倉社長の奔走の甲斐もなく不渡りの手形を出してしまい、一気に倒産へと追い込まれたようです。

本書から学んだこと

ベンチャーは銀行から金を借りるな

銀行にはベンチャーを育てようという意思も、能力も、仕組みも全く欠如しているようです。 (少なくとも1990年台時点では)

急激な事業拡大は大きなリスクを伴う

当たり前のことですが。
「Hotcafe」の日本での成功もおぼつかない状態で、
アメリカでの事業展開を急いだのはいかがなものかと思いました。

英語学習の目的とその方法について

英語学習を再開しようと思うので、 勉強を再開する理由と、学習の戦略などについてまとめてみました。

現在の英語レベル

大学院1年時に就活の役に立てばと思って3ヶ月ぐらいTOEICの勉強をしたことがあります。 それでも、点数的には685点と就職の有利になるような点数は取れませんでした。 勉強方法としては、単語帳2冊の暗記と、TOEICの問題集を試験直前に解いた程度です。

英語を学ぶ理由

僕の個人的な夢・目標は、 「FacebookAirbnbUberなどのような世界を変えるようなWebサービスを開発する」ことです。 そんなサービスを開発できる環境というのは日本よりも海外(特にアメリカ)の方が圧倒的に多いハズ。 だから将来、エンジニアとしてそんな場所で働けるようにビジネスレベルの英語力を身に着けたい というのが理由です。

3年後(2020年)までの目標

3年後までに、TOEIC900点台レベルの英語力を身につける。 ただし、大学時代にしたようなTOEICの点数を上げるための勉強はしません。 サブ目標としては、 1年後(2018年)までに700点台、 2年後(2019年)までに800点台を目指します。

学習の戦略

戦略なんてありません。時間を使うのみ。 とりあえず平日は最低30分、休日は2時間を学習時間に当てたいと思います。 大体毎日1時間はテレビを見てるのでその時間を使えば余裕!のはず・・。 引越し先にはテレビは持っていきません!

具体的な方法

「読み」「書き」「リスニング」「スピーキング」「文法」「単語」を、
どれかひとつを集中してやっていくのではなく、
それぞれをつまみ食いするように勉強していきたいと思います。
このつまみ食い式の勉強法の効果を裏付ける研究結果もあるそうです。

wired.jp

英文法の学習(今年中まで)

一億人の英文法 ――すべての日本人に贈る「話すため」の英文法(東進ブックス) を読みます。 文法の勉強はこの本だけにします。

英語でネットサーフィン(毎日)

はてぶの代わりにHackerNewsを使います。 そして、その中の一日最低1記事は目を通すようにします。 ネットでの情報も出来るだけ英語で行います。

単語や定型句を書き留める

ただし、大量の英文を「読む」ことが目的なので、
分からない単語があっても読み飛ばします。
そして、読み終わった後に、わからなかった単語の意味を調べ、
それをWebliioのアプリを使って書き留めておきます。
そうやって集めた単語集を定期的に読み返します。
また単語の他にも気になった言い回しがあればそれも書き留めて覚えます。

発音

YouTubeでネイティブの子供向けの発音の教育ビデオを見つけたのでそれを毎朝見て、
実際に声に出してみます。フォニックスというやつですね。

www.youtube.com

TEDを毎日聞く(毎日)

TEDの動画をスマホに落として毎日聞きます。 聞くのはなるべく自分が興味が持てるものを、1回だけでもいいし気に入ったら何回でも聞く。

Duo3.0で単語を覚える(毎日)

Duo3.0を2日で1巡するペースで毎日読み返したいと思います。 この単語帳を眺める勉強法はGoogleの日本支社長だった村上さんなどが自著などで紹介されていました。 村上さんの場合は1万語の単語帳を毎日眺められていたそうですが、とりあえず僕はDuoでやってみたいと思います。

会話はオンライン英会話サービスを使う

会話はDMM英会話などのオンライン英会話サービスを使いたいと思います。 ただ、十分な単語力、文法力、リスニング力が見についていない状態でやっても効果が薄いと思うので、 始めるのは4ヶ月後ぐらいを目安にします。

Web系ベンチャーに転職します

9月中旬からWeb系企業への転職活動を勧めていたのですが、 昨日先方から内定の通知が来ました。

とりあえず、備忘録として転職に至った経緯、今後やりたいこととかを 書き留めておこうとおもいます。

年齢とか

27歳。男性。

現職の仕事内容

医療系のシステムベンダーで介護関係のシステムを担当、 言語はVB.NETで、Windowsのネイティブアプリを作ってました。

転職先での仕事内容

Ruby on RailsのWebエンジニア

100万人以上のユーザーがいるWebサービスの開発に携わることになります。。 プレッシャー半端ない。

転職理由

ずっとWebエンジニアになりたかった

大学のときもWeb系に進みたいと思っていたのですが、実力不足でその時は 今の会社に就職しました。でも、ずっとWebエンジニアになりたいという気持ちは 消えず、個人的にRailsやSwiftを自習していました。

危機感

今の会社の方針として、言語はVB.NETしか使うことができませんでした。 VB.NET自体はC#の方言みたいなもんで十分先進的な言語だけれど、 世間的には余り使われていない部類の言語だと思います。 また、フレームワークも自社独自のものを使っていました。 この環境で5年、10年と働いていけば、確実にエンジニアとしての市場価値は 低くなっていくだろうな・・と感じていました。 社内の体制変更、入社から3年たったことなど、抜け出すなら今しかないと考え 転職を決意しました。

未経験なのになぜ採用されたか

自作アプリを面接に持っていた

個人的に勉強のためにRuby on Railsで簡単なSNSサイトを、 Swiftで中古本の価格を検索できるアプリを作っていました。 面接でこれを見てもらったのがすごく効果があったと思います。 一次面接で圧迫的だった面接官の態度(内定もらったところとは別の会社)が、 アプリを見せた時にガラッと変わるのはすごく印象的でした。 多分、自作アプリを面接で見せるだけで2倍ぐらいは通過率が上がるんじゃないかな。

入社までに勉強しておくこと

Ruby

抜けている知識を埋めておくために、 Ruby技術認定試験のSilver(できればGold)を取得しておきたいと思います。

Ruby on Rails

Railsチュートリアルを読み返します。 あと、実際にWebサービスを一つ作っておこうと思います。

mongoDB

とりあえずどんなものか触っておこうと思います。

AWS

Railsで作ったWebサービスをデプロイしてみたいと思います。

Git、GitHub

GitHubFlowで開発をしていると聞いているので。。 恥ずかしながらPullRequstを送ったことがないのでそのへんも勉強しておこう。

SOFT SKILLS ソフトウェア開発者の人生マニュアル

SOFT SKILLS ソフトウェア開発者の人生マニュアル

SOFT SKILLS ソフトウェア開発者の人生マニュアル

を読んだので重要だと思ったところをメモ。

第一部 キャリアを築こう

専門性はとても大事(p.33)

特定のフレームワークやプラットフォームについて深く掘り下げることによってより高い時給を要求できる。 また、専門分野は時代の流れによって変えていくことが大切。

あなたの習慣を見直そう。自らの1日を観察して、出来る限り多くの習慣を見つけよう。良いものと悪いものに分けてリストアップしよう。次に、いい習慣を考えてそれを身につけるプランを立てよう(p.56)

プロとアマの違いについて、プロになるために習慣の見直しが重要だということ。

第二部 自分を売り込め!

私がソフトウェア開発者に特に勧めたいもっとも効果的なものは、ブログである。ブログはインターネット上のホームベースにすべきだと思う。(p.107)

エンジニアが自分をマーケティングするにはブログをやると良いよという話。実は僕もこれを読んで始めた。

第3部 学ぶことを学ぼう

第33章 教える:学びたいなら教えよう

私がいつも勧めているのは、ブログの解説である。ブログは、あまりプレッシャーを感じずに自分が学んでいることを他人に教えられるすばらしい場だ。(p.185)

第4部 生産性を高めよう

第38章 ポモドーロ・テクニック

著者が実践してきた生産性向上法の紹介。

その日にする仕事の予定を立てて、25分で鳴るタイマーをセットしてから、最初のタスクに取り掛かる。一度に一つのタスクだけを処理し、25分間はそれだけに集中する。・・・25分立ったら5分で鳴るようにタイマーをセットして休憩を取る。これを1ポモドーロとする。4ポモドーロごとにそれよりも長い休憩(通常は15分)を取る。(p.210)

ポモドーロ・テクニックの本当の力は作業量を見積もり、トラッキングするためのツールとして使った時に現れる。1日に実行したポモドーロの数を数え、1日にどれくらい一生懸命仕事をしたか、自分のほんとうの能力はどれだけかを精確に測れるようになる。(p.212)

集中法としての要素もあるけど、タスクの見積もりの精度を向上させるテクニックでもあるよ。

第39章 以前よりも安定して多くの仕事が出来るワケ

著者が実践している「クォータシステム」という生産性向上策の紹介。

あなたが繰り返し行なっているタスクを取り出して、特定の期間内にそのタスクを何回こなすつもりかをクォータとして設定する。期間は、毎月、毎週、毎日のいずれかでもかまわないが、明確に決めて奥。大きなプロジェクトに取り組むときには、それを小さな頒布できるタスクに分割する方法が必要になる。(p.219)

タスクの実行周期を決めるということ。

クォータシステムのルール
・反復可能なタスクを選ぶ。
・タスクを実行しなければならない期間を決める。
・その期間にタスクを何回実行しなければならないかを決める
・コミットする。クォータを必ず達成するように厳格にコミットする。
・調整する。クォータが高すぎたり低すぎたりする場合、期間中にはクォータをいじらない。

これを読んで僕も、「1週間にブログを1記事以上書く」、「1週間に1つCodeIQまたはPaizaの問題を解く」というクォータを設定した。 でも、最近はコミットできない週もあってかなり弛んでたなぁ・・。

第43章 時間を浪費するメカニズム

はっきり言おう。テレビを見るのを止めよう。(p.237)

小飼弾も言ってたなぁ。

弾言 成功する人生とバランスシートの使い方

第5部 お金に強くなろう

第50章 給与交渉の方法

会社があなたのことを知っていて、面接さえせずに直接ポストを提示してくるのが最良の形であることは言うまでもないだろう。その場合、給与交渉はほとんどあなたの言い値だ。(p.282)

第二部の話につながってくる。マーケティングは大切だ。交渉テーブルに付く前に大方の勝負がついている。

数字を先に言ったほうが負け

特に重要なのは、先に数字を言った方が確実に不利になることだ。どのような交渉でも、自分の条件は後から言うようにしたい。(p.282)

例として、予算が8万ドル〜10万ドルのポストに応募した際に、自分から数字を行ったせいで年俸を2万5千ドルも割引いて雇用されてしまった男の話が載っていた。

その他

後半は不動産投資と筋トレの話。。

 

nokogoriの使い方メモ(XPathを使った場合)

Nokogiriのサンプルをメモ。

Youtubeで「Ruby on Rails」と検索して、結果の動画のタイトルの一覧を表示する。

require 'open-uri'
require 'nokogiri'

# Youtubeで「ruby on rails」で検索した結果の動画のタイトルの一覧を取得する。

# youtubeでruby on railsを検索
doc = Nokogiri::HTML(open('https://www.youtube.com/results?q=ruby+on+rails&sp=CAI%253D'))

# 動画のノードの一覧を取得
# ドキュメント全体を検索する場合は「//をつける」
nodes = doc.xpath("//div[@class='yt-lockup-dismissable yt-uix-tile']")

nodes.each do |node|
  # このノード以下のすべての子要素に対して検索を行う場合は「.//」をつける
  title_node = node.xpath(".//h3[@class='yt-lockup-title ']")
  # 子要素のみを検索対象とする場合は何もつけない
  title = title_node.xpath("a")
  puts title.text
end