2014年10月18日土曜日

cakephp 中間テーブルの命名規則

中間テーブルの命名規則で右往左往したのでメモ

cakephpの中間テーブルの命名規則


複数形をアンダースコアでつなぐ
順番はabc順

「ユーザー」と「趣味」を多対多の関係で表現する場合

interests_usersとなる

modelの命名規則

複数形 + アンダースコア + 単数でつなぐ
順番はabc順

modelは単数なのでモデル名の末尾は単数にする
中間テーブルの一つ目の名称は複数のままにする
interests_user.php

インスタンスの命名規則

アッパーキャメルで複数 + 単数
InterestsUser




2014年10月14日火曜日

cakephp saveAllの仕様

オプションでvalidate onlyとした時、IDの補完はしない

save Allの便利な機能の中に、リレーションを張るとidを保管してくれる機能があります。
しかし、確認画面を挟むなどの理由でバリデーションだけをしたい時に、validatesをonlyとしてしまうと、idの補完は行われません。

なので、そのIDに依存するバリデーション条件が設定されている場合は、必ずエラーに成ってしまうので気をつけないといけません。

User hasone UserInfo

$data = array(
    'User' = array(
        'name' => 'waldo',
        'tel'     => 0123456789,
    ),
    'UserInfo' = array(
        'prefecture' => 'hokkaido',
        'city'           => 'sapporo',
    ),
);
       
$this->User->saveAll($data, $options);

この場合、UserInfo.user_idにinsertしたデータのUser.idが補完されてsaveされます。

$options = array('validates' => 'only');
$this->User->saveAll($data, $options);
とした場合は、上記の補完が適用されないため、user_idの存在の確認や、市外局番と住所の不一致などのバリデーションをuser_id経由で行えなくなります。(user_idが無いというエラーが出ます)

同様のことは
$options = array('validates' => 'first');
とした時にも一度onlyでバリデーションチェックをするので発生しますので注意してください。

解決方法

saveAllを使わない

idを補完したいということならsave後に$this->User->idでinsertしたIDを取得できるので、自前でsaveAll的なメソッドを作ってしまう。
逐一、unsetなどができて自由度が高い。

atomic => false で外部トランザクションをかけて毎回ロールバックする

楽ちんだが、オートインクリメントされていくので、IDが飛び飛びになってしまう

UserInfoバリデーション時にUserのPOST値を見に行く作りにする

UserInfoだけ追加でinsertしたい、updateしたいなどの時に、別途バリデーションを作らないといけない。冗長な作りになってくる



2014年10月13日月曜日

マージしたコミットを戻す git revert -m 1 と git revert -m 2 の違い

マージコミットのrevertで後ろにつける引数について、ネット上を探してもなかなかまとまっているページがなかったので、まとめます。

参考
http://blog.toshimaru.net/git-revert-mainline/

そもそもマージしたコミットの逆差分を作るには?
オプションで -m を指定します。今回はその後ろにつける1,2の引数についてです

git revert -m 1

マージをした側に戻すように差分をつくる
基本的に使うのはこっちが多い

git revert -m 2

マージされた側に戻すように差分をつくる

実際にやってみる

[uenoryouichi@ueno-MacBook-Air:git_study](master)$ git checkout -b merged
[uenoryouichi@ueno-MacBook-Air:git_study](merged)$ vi test.php
[uenoryouichi@ueno-MacBook-Air:git_study](merged)$ git add .
[uenoryouichi@ueno-MacBook-Air:git_study](merged)$ git commit -m 'このブランチをマージする'

[uenoryouichi@ueno-MacBook-Air:git_study](base)$ git checkout master
[uenoryouichi@ueno-MacBook-Air:git_study](master)$ git checkout -b base
[uenoryouichi@ueno-MacBook-Air:git_study](base)$ vi test.php
[uenoryouichi@ueno-MacBook-Air:git_study](base)$ git add .
[uenoryouichi@ueno-MacBook-Air:git_study](base)$ git commit -m 'このブランチでマージコマンドを打つ'
 
[uenoryouichi@ueno-MacBook-Air:git_study](base)$ git merge merged
Auto-merging test.php
Merge made by the 'recursive' strategy.
 test.php | 4 ++++
 1 file changed, 4 insertions(+)
 
[uenoryouichi@ueno-MacBook-Air:git_study](base)$ glog
*       Ryoichi Ueno    25605e9  (HEAD, base) Merge branch 'merged' into base
|\
| *     Ryoichi Ueno    5e19ce5  (merged) このブランチをマージする    (<= 2に相当)
* |     Ryoichi Ueno    4e1dfd0  このブランチでマージコマンドを打つ   (<= 1に相当)
|/
*       Ryoichi Ueno    f410859  (master) second
*       Ryoichi Ueno    70e35e5  initial commit
[uenoryouichi@ueno-MacBook-Air:git_study](base)$


git revert -m 1でrevertする

[uenoryouichi@ueno-MacBook-Air:git_study](base)$ git revert -m 1 25605e9
[uenoryouichi@ueno-MacBook-Air:git_study](base)$ glog
*       Ryoichi Ueno    fe81bcd  (HEAD, base) Revert "Merge branch 'merged' into base"
*       Ryoichi Ueno    25605e9  Merge branch 'merged' into base
|\
| *     Ryoichi Ueno    5e19ce5  (merged) このブランチをマージする
* |     Ryoichi Ueno    4e1dfd0  このブランチでマージコマンドを打つ
|/
*       Ryoichi Ueno    f410859  (master) second
*       Ryoichi Ueno    70e35e5  initial commit
[uenoryouichi@ueno-MacBook-Air:git_study](base)$ git diff --stat 4e1dfd0       baseブランチ側とは差分がない
[uenoryouichi@ueno-MacBook-Air:git_study](base)$ git diff --stat 5e19ce5      mergedブランチ側と差分がある
 test.php | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

git revert -m 2でrevertする


[uenoryouichi@ueno-MacBook-Air:git_study](base)$ git revert -m 2 25605e9
[uenoryouichi@ueno-MacBook-Air:git_study](base)$ glog
*       Ryoichi Ueno    1b77f6a  (HEAD, base) Revert "Merge branch 'merged' into base"
*       Ryoichi Ueno    25605e9  Merge branch 'merged' into base
|\
| *     Ryoichi Ueno    5e19ce5  (merged) このブランチをマージする
* |     Ryoichi Ueno    4e1dfd0  このブランチでマージコマンドを打つ
|/
*       Ryoichi Ueno    f410859  (master) second
*       Ryoichi Ueno    70e35e5  initial commit
[uenoryouichi@ueno-MacBook-Air:git_study](base)$ git diff --stat 4e1dfd0   baseブランチ側と差分がある
 test.php | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)
[uenoryouichi@ueno-MacBook-Air:git_study](base)$ git diff --stat 5e19ce5    mergedブランチ側とは差分がない

git reset のオプションについて --soft --hard --mixedの違い

rd : 差分は破棄される(indexとworking treeも戻る)
mixed : add前の状態で保持されている(working treeが保持)
soft : add状態で保持されている(indexも保持)

参考

http://d.hatena.ne.jp/murank/20110327/1301224770


用語の補足

HEAD:コミット状態
index:addした状態
working tree:add前の変更分

[uenoryouichi@ueno-MacBook-Air:git_study](master)$ vi test.php
[uenoryouichi@ueno-MacBook-Air:git_study](master)$ git add test.php
[uenoryouichi@ueno-MacBook-Air:git_study](master)$ vi test.php
[uenoryouichi@ueno-MacBook-Air:git_study](master)$ git status
[uenoryouichi@ueno-MacBook-Air:git_study](master)$ glog
*       Ryoichi Ueno    f410859  (HEAD, master) second                ←HEAD
*       Ryoichi Ueno    70e35e5  initial commit
[uenoryouichi@ueno-MacBook-Air:git_study](master)$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)                                   ←index
 
     modified:   test.php
 
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)
 
     modified:   test.php                                                                    ←working tree



http://d.hatena.ne.jp/murank/20110327/1301224770 より引用


この状態でそれぞれどのような動きになるか試してみましょう
git reset --soft HEAD
git reset --soft HEAD^
git reset HEAD
git reset HEAD^
git reset --hard HEAD
git reset --hard HEAD^

git resetとgit revertの基本

コードを過去に戻すgit resetとgit revertの違いについて解説します。

ソースを切り戻す時、resetなのか?revertなのか?gitに慣れていないメンバーが多いこともあり、しっかり理解することで安心して切り戻しなどの作業をみんなができるようになると良いなと感じたことから記事にさせていただきました。

はじめに

コードの中にこちらのaliesが使われていますので記載します。

alias glog='git log --graph --all --format="%x09%C(cyan bold)%an%Creset%x09%C(yellow)%h%Creset %C(magenta)%d%Creset %s"'


resetとrevert

利用シーン
過去に戻る。
コミットした差分を修正したい

resetの基本

「指定したコミット位置までHEADの位置を戻す」

revertの基本

「指定したコミットの逆差分を作成する」

よくある切り戻しのシーン

バグが有るコードをリリースしてしまった。orz
リリース前のコードに戻したい!!

どちらが正しいでしょう?
git resetを使って、前回リリースした位置まで戻す!
git revertを使って逆差分で上書きする!


正解はもちろん「git revertする」です。

revertによる切り戻し手順

revert -m 1 <commit hash>でマージコミットの逆差分を作ります(-m と 1 については下方で解説します。)
 ※切り戻し自体はgithubのwebUIによる操作もできるようになりました(下方に記載)

[uenoryouichi@ueno-MacBook-Air:git_study](base)$ git revert -m 1 25605e9
[uenoryouichi@ueno-MacBook-Air:git_study](base)$ glog
*       Ryoichi Ueno    fe81bcd  (HEAD, base) Revert "Merge branch 'merged' into base"
*       Ryoichi Ueno    25605e9  Merge branch 'merged' into base
|\
| *     Ryoichi Ueno    5e19ce5  (merged) このブランチをマージする
* |     Ryoichi Ueno    4e1dfd0  このブランチでマージコマンドを打つ
|/
*       Ryoichi Ueno    f410859  (master) second
*       Ryoichi Ueno    70e35e5  initial commit

reset使っちゃいけない理由

gitの概念として歴史を改変してはいけない。
誰かが誤ったコミットの歴史を間違って保有している可能性がある。→デグレのリスクが生じる。
存在しないコミットから分岐したブランチが作られる可能性がある。→PRを送れないorデグレのリスク

例)
master_resetで7d71e00 をリリースしました。前回リリースは cdf4505
修正するためにresetで戻した場合(ダメなパターンです)
[uenoryouichi@ueno-MacBook-Air:git_study](recover_reset)$ git reset --hard cdf4505
HEAD is now at cdf4505 hogehogehogehoge
[uenoryouichi@ueno-MacBook-Air:git_study](recover_reset)$ glog
*       Ryoichi Ueno    7d71e00  (master_reset) miss!!!!!
*       Ryoichi Ueno    cdf4505  (HEAD, recover_reset) hogehogehogehoge
*       Ryoichi Ueno    b3bd9c4  hogehogehoge
*       Ryoichi Ueno    44515ea  hogehoge
*       Ryoichi Ueno    1b4f700  hoge
[uenoryouichi@ueno-MacBook-Air:git_study](recover_reset)$ git push -f origin master

おさらい

resetの基本
「指定したコミット位置までHEADの位置を戻す」
revertの基本
「指定したコミットの逆差分を作成する」