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

Rails5 FactoryGirlでコールバックをスキップする方法

Rails4では使えたFoo.skip_callback(:create, :after, :bar)がRails5では使えない。

ArgumentError:
       After create callback :do_something has not been defined

対策として、次のようにFGにおいてメソッドを上書きする:

class User < ActiveRecord::Base
  after_create :run_something
end
FactoryGirl.define do
  factory :user do

    after(:build) do |user|
      class << user
       def run_something
         true
       end
      end
    end

    factory :user_with_run_something do
      after(:build) do |user|
        class << user
          def run_something
            super
          end
        end
      end
    end
  end
end

コールバックメソッドの発火タイミングによって、after(:build)も変更する必要がある

参考:

http://stackoverflow.com/questions/8751175/skip-callbacks-on-factory-girl-and-rspec/22916595#22916595

https://github.com/thoughtbot/factory_girl/issues/931

first_nameカラム、last_nameカラムからフルネーム検索するメソッド

Controller:

class ProfilesController < ApplicationController

  def search
    @profiles = Profile.search_by_full_name(search_params[:name])
  end

  private

  def search_params
    params.require(:search_profile).permit(:name)
  end
end

Model:

class Profile < ApplicationRecord

  def self.search_by_full_name(query)
    query.delete!(' ')
    where("CONCAT_WS('', first_name, last_name) LIKE ?", "%#{query}%")
  end
end

いろいろ応用できそう

Webpack v1からv2へのマイグレーションメモ

自分が使っていたところだけを簡単に。詳しくはhttps://webpack.js.org/guides/migrating

以下、webpack.config.jsの変更点:

resolve.extenstions

空の文字列は必要なくなったので削除する。ちなみにデフォルトでは.js.jsonがresolveされている。

// v1
resolve: {
  extensions: ["", ".js", ".json"],
},
// v2
resolve: {
  extensions: [".js", ".json"],
},

拡張子を指定することで./foojsファイルならばrequire("./foo")が可能になる。

module.loadersmodule.rules

module.loaderシンタックスはまだサポートされているが、module.rulesにかえるほうが望ましい。

// v1
module: {
  loaders: [
    {
      test: /\.css$/,
      loader: [
        "style-loader", 
        "css-loader?modules=true" 
      ]
    }
  ]
}
// v2
module: {
  rules: [
    {
      test: /\.css$/,
      use: [
        {
          "style-loader"
        },
        {
          "css-loader",
          options: {
            module: true
          }
        }
      ]
    }
  ]
}

loaderのチェイン

複数のloaderを!でつなげるのはmodule.loadersオプションでしか使えない。

// v1
module: {
  loaders: [
    {
      test: /\.css$/,
      loader: "style-loader!css-loader"
    }
  ]
}
// v2
module: {
  rules: [
    {
      test: /\.css$/,
      use: [
        "style-loader",
        "css-loader"
      ]
    }
  ]
}

-loaderの省略はできなくなった

loader指定時に、-loaderを省略することはできなくなった。

// ×
module: {
  rules: [
    {
      use: [
        "style",
        "css",
        "less"
      ]
    }
  ]
}
// ○
module: {
  rules: [
    {
      use: [
        "style-loader",
        "css-loader",
        "less-loader"
      ]
    }
  ]
}

json-loaderを指定する必要はなくなった

json-loaderがなくとも、自動的にJSONファイルを読み込む。

// ×
module: {
  rules: [
    {
      test: /\.json/,
      loader: "json-loader"
    }
  ]
}
// ○
module: {
  rules: [
  ]
}

module.preLoadersmodule.postLoadersは削除された

// v1
module: {
  preLoaders: [
    {
      test: /\.js$/,
      loader: "eslint-loader"
    }
  ]
}
// v2
module: {
  rules: [
    {
      test: /\.js$/,
      enforce: "pre",
      loader: "eslint-loader"
    }
  ]
}

UglifyJsPlugin sourceMap

UglifyJsPluginsourceMapオプションはデフォルトでfalseになった。sourceMapが欲しい場合にはtrue設定する必要がある。

devtool: "source-map",
plugins: [
  new UglifyJsPlugin({
    sourceMap: true
  })
]

UglifyJsPlugin warnings

UglifyJsPlugincompress.warningsオプションはデフォルトでfalseになった。warningsが欲しい場合にはtrue設定する必要がある。

devtool: "source-map",
plugins: [
  new UglifyJsPlugin({
    compress: {
      warnings: true
    }
  })
]

UglifyJsPlugin minimize loaders

UglifyJsPluginはloadersをminimizeモードに切り替えなくなった。

loadersのminimizeモードは webpack 3 以降に削除される。

古いloadersとの互換性を保つために、pluginを用いてminimizeモードに切り替えることができる。

plugins: [
  new webpack.LoaderOptionsPlugin({
    minimize: true
  })
]

DedupePluginは削除された

webpack.optimize.DedupePluginはもう必要ないのでwebpackの設定から削除する。

OccurrenceOrderPluginはデフォルトで設定される

もうわざわざ指定する必要はない。

debug

webpack 1 では、debugオプションはloadersをdebugモードに切り替える。

loadersのdebugモードは webpack 3 以降に削除される。

古いloadersとの互換性を保つために、pluginを用いてdebugモードに切り替える。

plugins: [
  new webpack.LoaderOptionsPlugin({
    debug: true
  })
]

bitcoin保管方法まとめ

自分用にまとめ。随時更新

免責事項: 筆者は、あなたに対して何も保証しません。筆者は、あなたに対して一切責任を負いません。すべての作業は自己責任で行って下さい。

所感

セキュリティ

ペーパーウォレット>物理デバイス>>>デスクトップウォレット>>モバイルウォレット>>>>>>>ウェブウォレット

取引のしやすさ

Webウォレット>>>モバイルウォレット=デスクトップウォレット=物理デバイス>>>>>>>>>>>>>>>>ペーパーウォレット

特徵

ペーパーウォレット

アドレスと秘密鍵を印刷して保管する方法。長期間の保存を目的とする。送金時には、デスクトップ・モバイル・ウェブウォレットなどにインポートする。ソースコードをダウンロードして、オフラインで作成。

bitaddress.org

メリット

  • オフラインで作成した場合、最も安全

デメリット

  • 盗難・火災による紛失の可能性(コピーがない場合は復元できない)
  • 使いにくい

物理デバイ

専用のデバイスに保管する方法。長期保管を目的としている

TREZOR
Ledger Nano S

メリット

  • オフラインで保管するためクラッキングの可能性は低く、物によってはパスワード・取引の承諾などによって厳重にプロテクトをかけることができるため、ペーパーよりセキュリティが高い
  • PCに接続するだけなので取引の利便性が良い

デメリット

  • 紛失盗難の可能性

デスクトップウォレット

デスクトップアプリをインストールしてローカル環境で管理する方法

electrum

メリット

  • 利便性が良い
  • オフラインで管理する場合はセキュリティ面でも優れている

デメリット

  • PCの故障により取り出せなくなる可能性があるので、PCのバックアップに気を使う必要がある
  • ハッキングやウイルス感染により盗まれる可能性があるので、PCのセキュリティには注意する必要がある

バイルウォレット

スマートフォン上で管理する方法

breadwallet - bitcoin wallet - iOS
MYCELIUM - Android

メリット

  • QRコードを利用できる
  • 実店舗の利用に便利

デメリット

ウェブウォレット

ウェブ上のウォレットサービスを利用する方法

coincheck

メリット

  • 使いやすい
  • どのコンピューターからもアクセスできる
  • セキュリティをサービス提供者に一任できる

デメリット

Amazon Dash Buttonをハックする

ウィルキンソン Dash Buttonをハックしたときの備忘録。

Amazon Dash Buttonのセットアップ

まずはAmazon iOS/Androidアプリを使って、Amazon Dash Buttonのセットアップ。商品選択でキャンセルしておくことに注意。

MACアドレスの取得

使用するのはdash-buttonというライブラリ。これをインストールする。

npm i -S dash-button

package.jsonscriptsに手を加える:

{
    "scripts": {
        "scan": "dash-button scan"
    }
}

スキャン実行中に、Amazon Dash Buttonを押すとMACアドレスが取得できる:

sudo npm run scan

> amazon-dash-button@1.0.0 scan /Users/uraway/github/amazon-dash-button
> dash-button scan

Scanning for DHCP requests and ARP probes on en0...
Detected a DHCP request or ARP probe from xx:xx:xx:xx:xx:xx

うまくいかない場合は、インターフェースオプション(--interface/-i)をつけて、他のインターフェースを試してみるといいかもしれない。

Amazon Dash Buttonを入退室ボタンにしてみる

SlackのAPIを使って、Slackに入退室のメッセージを送信するボタンにハックしてみる。

const DashButton = require('dash-button');
const Slack = require('node-slack');

const DASH_BUTTON_MAC_ADDRESS = 'xx:xx:xx:xx:xx:xx';
const HOOK_URL = 'https://hooks.slack.com/services/*****';

let button = new DashButton(DASH_BUTTON_MAC_ADDRESS);
let slack = new Slack(HOOK_URL);

let i = 0;

button.addListener(() => {
  i++;
  console.log(`${i} times working!`);
  if (i % 2 === 0) {
    slack.send({
      text: '入室しました',
      username: 'WILLKINSON'
    });
  } else {
    slack.send({
      text: '退室しました',
      username: 'WILLKINSON'
    });
  }
});

スクリプト実行中にAmazon Dash Buttonを押すと…

ウィルキンソン Dash Button

ウィルキンソン Dash Button

Gem::Ext::BuildError: ERROR: Failed to build gem native extension.

nokogiriがインストールできない

Gem::Ext::BuildError: ERROR: Failed to build gem native extension.
An error occurred while installing nokogiri (1.6.8.1), and Bundler cannot continue.
Make sure that `gem install nokogiri -v '1.6.8.1'` succeeds before bundling.

xcodeのコマンドラインツールをインストールすれば解決した:

gem uninstall nokogiri
xcode-select --install
gem install nokogiri

依然xcode関係を整理したからかな?

参考: https://github.com/bundler/bundler/issues/3372

2000名以上の日本人英語学習者のデータからあなたに必要な学習時間を計算してくれるWebアプリ、作りました

エンジニアインターン生として働いているサウスピークにて、新たにWebアプリを作成しました。公開できるものとしては初のアプリですね。

どんなものか

英語学習時間シミュレーター

目標の英語力と現在の英語力から必要な英語時間を算出するWebアプリです。

使い方としては、まず、目標の英語力を選択します。

アルゴリズム的な話をすると、選択肢の英語力はTOEICの点数に換算されます。

現在の英語力の選択肢(下図)もすべてTOEICの点数に換算されます。

で、この2つの情報とサウスピークの卒業生のデータを照らし合わせ、到達に必要な英語学習時間を導き出します。

アプリ内では「一日あたり2時間の勉強で〇〇日の計算になります」と言ってはいますが、"お金を出して留学するほどやる気があり""フィリピン人からのレッスンを受け""英語学習のスペシャリストが作成したカリキュラムに沿って勉強する"サウスピークの生徒のデータから作成しているので、一般的な英語学習者のデータから作成したものと比較すれば、短く見積もられているはずです。なので英語学習の道しるべ程度にどうぞ。

使用したもの

フロントにはReact、サーバーフレームワークはExpressのJSオンリーの構成になっています。

グラフの生成にはRechartを使用。使いやすくて好きなライブラリです。

悩んだところ

SNSのシェアがうまく行かず、やたらと時間を食いました。

当初はreact-helmetで、フロント側で結果の画像毎に動的にOpen Graph用にmetaタグを埋め込んでいました。

<Helmet
  meta={[
    {"property": "og:title", "content": "英語学習時間シュミレーター"},
    {"property": "og:type", "content": "website"},
    {"property": "og:image", "content": imageId},
    {"property": "og:url", "content": "http://simulator.souspeak.com/"}
  ]}
/>

が、駄目。FacebookやTwitterのスクレイパーは正しく読み込んでくれませんでした。

ググってみると、全く同様のことで悩んでいる方がいらしたので、その方の解決法を参考にサーバーサイドで対処しています。ありがとうございます。

気づいたこと

データ活用のアルゴリズムについては一人であーでもないこーでもないと悩みながら作っていたんですが、最初はコードがやたら汚くなってしまっていました。そこらへんもレビューしてもらいながら改善していって、デザインをすごくきれいにしてもらって、作り始めてから1ヶ月少しで公開となりました。

コードが汚いまま公開して、公開日に重大なバグ発見、公開取りやめってのは考えうる中で最悪のシナリオですが、当初はコードをきれいにする必要性を理解してもらえず、早く公開しろ、とせっつかれ、納期に迫られるエンジニアの気持ちが少しわかりました。上司がエンジニアではない場合、デモ見せの時点でコードをきれいにして、バグを見つけやすく保守しやすくしておく方がいいのかも。

もう一つ気づいたこと、というか前から思っていたんですが、プログラマーには基礎的な数学の教養が必要です。

プログラマーは、与えられたデータからほしい結果を得るための計算問題を考えて、それをコードに落とし込むことで、アプリケーションの核であるアルゴリズムを作ります。そのために、最低限の数学の教養、高3までの数学の知識ぐらいは必要ではないかと思いました。

だとするとプログラマーは文系が不利かって言うとそうでもなく、大学で数学やコンピューターサイエンスを修めるような人には人工知能やインターネットの高速化のアルゴリズムなんかを研究してもらって、文系は世界中の数学好きが発表するアルゴリズム(人工知能フレームワークとか高速化されたインフラとか)を、コントリビューションまではいかなくとも、英語と最低限の数学の知識でがんがん吸収して使えるようにして、アプリとして利用できるようにすれば、住み分けができるんじゃないかと。

まあ、プログラマー1年目の意見なので、数年後には真逆のことを言っているかもしれませんが。

最後に

さて、あと数日でプログラミングを学び始めて、2年目に入ります。アプリのアイデアがいくつかあるので、2年目はそれを実現していきます。