メンチカツ

ロースカツが好きです

【メモ】Golang/dbrでreplace intoがしたかった。

※2016/12/16 修正しました

Go言語のO/R Mapper、dbrでreplace intoがしたかった。

のですが、dbrではreplace構文はサポートしてないらしい。

それで、delete-insertで対応することにしました。

type (
    //User ユーザー
    User struct {
        ID       int
        Contacts []*Contact
    }
    //Contact ユーザーの連絡先
    Contact struct {
        MailAddress string
    }
)

//replaceUserContacts ユーザーの連絡先を削除して登録する
func (u *UserContacts) replaceUserContacts(sess *dbr.Session) error {
    //削除して
    _, err := sess.DeleteFrom("user_contacts").
        Where("user_id", u.ID).
        Exec()
    if err != nil {
        return err
    }
    //登録
    for _, c := range u.Contacts {
        _, err := sess.InsertInto("user_contacts").
            Columns("user_id", "mail_address").
            Values(u.ID, c.MailAddress).
            Exec()
        if err != nil {
            return err
        }
    }

    return nil
}

よし超シンプルだぜと思って実行したら、なんとぜんぜん登録されない。

確認したら、deleteの返り値errに

dbr: wrong placeholder count

って入ってる。

処理してるところ

github.com

を確認すると、プレースホルダー( where id = ? に当たる部分)と

バインドする値(u.ID)の数が不一致だぞと言っている。なんでや。

なので、

//replaceUserContacts ユーザーの連絡先を削除して登録する
func (u *UserContacts) replaceUserContacts(sess *dbr.Session) error {
    //削除して
    _, err := sess.DeleteBySql(`delete from user_contacts where user_id = ` + strconv.Itoa(u.ID)).
        Exec()
    if err != nil {
        return err
    }
    //登録
    for _, c := range u.Contacts {
        _, err := sess.InsertInto("user_contacts").
            Columns("user_id", "mail_address").
            Values(u.ID, c.MailAddress).
            Exec()
        if err != nil {
            return err
        }
    }

    return nil
}

と、変数バインドしないようにしたところ、エラーなく動作するようになりました。

【メモ】間違えて削除したローカルブランチを復元するときに怒られた

reflogを参照して、間違えて削除したローカルブランチを復元するとき fatal: Not a valid object name と言われて復元できなかったのですが

$ git reflog # feature/hogeを削除する直前のコミット番号(HEAD@{n}というやつ)を控える
$ git branch feature/hoge HEAD@{12}
# => fatal: Not a valid object name: 'HEAD@12'. と出て復活できない

これはコミット番号をダブルクォートで囲んであげればOKです。

$ git branch feature/hoge "HEAD@{12}" # ダブルクォートで囲んでみる

$ git branch
* dev
  feature/hoge #<= 復活できた!
  master

【メモ】dockerに「Error response from daemon: client is newer than server」と言われる

docker氏に、クライアントとサーバーのAPIバージョンが相違しているよ!って怒られた

$ docker version

Client:
 Version:      1.12.0
 API version:  1.24
 Go version:   go1.6.3
 Git commit:   8eab29e
 Built:        Thu Jul 28 21:15:28 2016
 OS/Arch:      darwin/amd64
Error response from daemon: client is newer than server (client API version: 1.24, server API version: 1.23)

ggると docker-machine upgrade default すれば治るよ!とあるけど、改善されない、そんなときは 環境変数 DOCKER_API_VERSION を設定します。

export $DOCKER_API_VERSION=1.23

設定後、再度 docker-machine upgrade default すると、無事にバージョンを

docker version
Client:
 Version:      1.12.0
 API version:  1.23
 Go version:   go1.6.3
 Git commit:   8eab29e
 Built:        Thu Jul 28 21:15:28 2016
 OS/Arch:      darwin/amd64

Server:
 Version:      1.12.1
 API version:  1.24
 Go version:   go1.6.3
 Git commit:   23cf638
 Built:        Thu Aug 18 17:52:38 2016
 OS/Arch:      linux/amd64

合わせられてないやんけ。 でもサーバーのAPIバージョンがあげられたぞ???

そこで、環境変数 DOCKER_API_VERSION を更新してみます。

export $DOCKER_API_VERSION=1.24

その後dockerをrestartすると、やっとバージョンが合いました。

Client:
 Version:      1.12.0
 API version:  1.24
 Go version:   go1.6.3
 Git commit:   8eab29e
 Built:        Thu Jul 28 21:15:28 2016
 OS/Arch:      darwin/amd64

Server:
 Version:      1.12.1
 API version:  1.24
 Go version:   go1.6.3
 Git commit:   23cf638
 Built:        Thu Aug 18 17:52:38 2016
 OS/Arch:      linux/amd64

コミットハッシュに変更がないので、どうやら見た目が変わっただけなんですけどね。 ひとまず状況は解決できました。

ggったページ

github.com

【メモ】MyBatisのMapperでオーバーロードをしてはいけない

MyBatisで

public interface UserMapper {

  @Select("SELECT * FROM users")
  List<User> getUsers();

  @Select("SELECT * FROM users WHERE category_id = #{categoryId}")
  List<User> getUsers(@Param("categoryId") Integer categoryId);

}

と定義してビルドする。

と、以下のように怒られる😇

java.lang.IllegalArgumentException: Mapped Statements collection already contains value for jp.co.hoge.core.mapper.UserMapper.getUsers

これは、interface内でメソッド名を一意にすると解決します😙

public interface UserMapper {

  @Select("SELECT * FROM users")
  List<User> getUsers();

  @Select("SELECT * FROM users WHERE category_id = #{categoryId}")
  List<User> getUsersByCategoryId(@Param("categoryId") Integer categoryId);

}

【メモ】webpack.optimize.UglifyJsPluginでbuildしてもコメントが残っちゃうんだよねってとき

Reactアプリでリリースってなったとき、みんなやりたいのがjsファイルのminify。

webpackのドキュメント

list of plugins

に習い、webpack.config.jsで

plugins: [
  new webpack.optimize.UglifyJsPlugin({
    compress: {
        warnings: false
    }
  })
]

を追加するも、ビルドしたソースにはコメントやスペースがもりもり残ってる。。😇

そんなときはjsのloaderにoptionを追加。

module: {
    loaders: [
        {
            test: /\.js$/,
            loader: 'babel',
            query: {
                comments: false,
                compact: true
            },
            exclude: /node_modules/,
            include: __dirname
        }
    ]
}

babel-loaderのqueryに追加できるoption

babeljs.io

無事、いい感じにminifyできました。

【メモ】React,Reduxのリファクタリングはじめの一歩

よくわからないままはじめ、まさに習うより慣れよで身につけつつある Reduxスキル。 最初のほうに作ったソースを見直すと、ある共通点に気がつきました。

無駄なstateが多い!

propsで受け取った値をわざわざコピーしてstateで保持してたりします。 変更される値はイベントハンドラの引数で受け取れるので、捕捉した値を propsのイベントで上位のコンポーネントに伝搬してしまえば、stateを 用意する必要がある箇所をぐっと減らすことができました。

//before:こういうかんじの記述が多かった
handleChange(e) {
    const textValue = e.target.value
    this.setState({
        textValue: textValue
    }, this.props.onChange(textValue))
}

//after:丸投げでスッキリ
handleChange(e) {
    this.props.onChange(e.target.value)
}

変更フォームなど、propsで変更前、stateで変更後の値を保持して 比較したり、リセットボタンを押したら変更前の値に戻すとか、そういう 時以外はstateは最小限がソースが見やすいな、と思いました。

Reactで「Uncaught TypeError: Cannot read property 'props' of null」が出る

render(){
  return <myCompornent onClick={this.handleClick}></myCompornent>
}

ってやって、myCompornent側で

onClick(){
  this.props.onClick()
}

とかやると

Uncaught TypeError: Cannot read property 'props' of null

とエラーしてしまいます。

これは、

<myCompornent onClick={this.handleClick.bind(this)}></myCompornent>

とすることで回避できます。

これはes6の仕様です。es5で書かれたReactチュートリアルを写経すると発生しがちです。

qiita.com

きっちり写経したのにエラーしてしまう。。typoしてんのかな??

とか陥りがちなポイントです(というか陥った)。