ホーム ブログ ページ 32

mongodbにおいてよく利用する基本的な操作について

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

mongodbにおいてよく利用する基本的な操作について以下に記載致す

DB操作

  1. DBの選択> use <DB名> もしくはMongoのシェル起動前に$ mongo <DB名>
  2. DBの一覧取得> show dbs

コレクション操作

  1. コレクションの一覧取得> show collections
  2. コレクションの作成> db.createCollection(“<コレクション名>”)
  3. インデックス
    3.1. インデックス確認> db.<コレクション名>.getIndexes() 3.2. インデックス追加> db.<コレクション名>.ensureIndex({ <フィールド名>: <値> }) 値)
    • 1: 昇順
    • -1: 降順
  4. データ取得
    4.1. 書式> db.<コレクション名>.find({検索オプション})
  • 結果表示を見やすくなるように調整
    db.<コレクション名>.find().pretty()
  • 制限付加
    db.<コレクション名>.find().limit()
  • 件数
    db.<コレクション名>.find().count()
  • ソート
    db.<コレクション名>.find().sort({<フィールド名>: <値>})
    値)
    • 1: 昇順
    • -1: 降順
  • findの第二引数に表示オプションを指定
    db.<コレクション名>.find({}, {<フィールド名>: <値>})
    値)
    • 0: 非表示(0を指定したもののみ消える)
    • 1: 表示(_idと、1をしていしたもののみ表示)
    • 0と1は混ぜて指定できない
  1. 検索条件 findの第一引数内に指定
  • 文字列 .find({<フィールド名>: “”})
  • 正規表現 .find({<フィールド名>: /aaa/})
  • 比較 .find({<>: {<比較演算子>: <値>})
    • 一致 $eq
    • 不一致 $ne
    • 以下 $lte
    • 以上 $gte
    • 大なり $gt
    • 小なり $lt 例) db.<コレクション名>.find({hoge:{$lt: 3}})

mongoが起動しない場合の対処方法

ホストOSがクラッシュし, 仮想環境の不正終了が発生した場合などに,
仮想環境再起動後、mongoが正常起動しない現象が発生した場合,
以下のコマンドで対処することが可能である.
(発生環境: CentOS 6)

# cd /var/lib/mongo
# rm -f mongod.lock
# mongod --dbpath=/var/log/mongodb --repair
# service mongod start

ActiveRecordのpluckを用いた処理の高速化に関する調査

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

大量のレコードに対してデータ処理を行う場合, ActiveRecordのpluckを使用することが有効な場合が存在する. 本記事では、処理速度向上に関する有効性の確認を行う.

処理内容

テーブル内の全レコードに対して、
現在レコードが所持しているパラメータを利用して、更新をかける処理

  • レコード:50万件
  • パラメータ:25種類

動作比較

1. レコード1件ごとに更新をかける(比較用)

比較用に1件ごとに更新をかける処理を行ってみたところ、
処理に時間がかかり実行が終わらないため、問題外であった

2. find_each

  • find_eachでレコードを取得して、パラメータごとのリストを作成
  • リストのパラメータごとに、update_allで更新をかける

処理の所要時間およそ10分

1SQL自体のログに出力されるSQL実行時間,
発行されるSQLの構文への explain の実行でのインデックスの適用具合自体は問題が無いように見られたが,
ActiveRecordオブジェクト生成にかかるコストが処理速度に影響を与えている可能性が考えられる.

3. pluck

  • pluckで、パラメータごとのリスト作成に必要なカラムの値を取得
  • リストのパラメータごとに、update_allで更新をかける

処理の所要時間およそ30秒

ActiveRecordオブジェクト生成を防ぐことにより,
同一のリスト作成処理において大幅な処理速度向上が見込まれた.

まとめ

上記のことから,
pluckの返却値はArrayでの取得となるため, ActiveRecordのメソッド等は使用できなくなるが,
取得値のみで処理が可能な場合など利用可能な場面においては,
pluckを使用することにより, 処理速度向上を行うことができることを確認することができた.

UnityEditor上で複数のゲームオブジェクトをプレハブ化する方法

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

はじめに

Unityを使っていて、複数のゲームオブジェクトを同時にプレハブ化したい時がありました。Unityではひとつずつしかプレハブ化できないようになっています。それでは不便なのでどうにかできないか調べ、作ってみました。

新しくウィンドウを作る

では、新しくウィンドウを作ってみましょう。

Assetsフォルダの中に、Editorと言う名のフォルダを作りましょう。基本的にエディタ拡張関連のスクリプトはこの中に保存しておきます。

次に、そのEditorフォルダの中に新しくクラスを作りましょう。今回はExampleという名前のクラスを作ります。

注意点として、新しくUnity上でウィンドウを開きたいときは、必ずEditorWindowクラスを継承しなければいけません。

では、Openというメソッドを作り、そこにEditorWindow.GetWindow()と書きましょう。これで新しくウィンドウを作る準備は終わりました。ですが、実際に動かしてみると、どこにも表示させません。
では次に、新しいウィンドウを表示させるために、それを表示させるメニューを作ります。
下記のソースコードのように少し特殊な書き方になります。その下にあるopenメソッドは必ずstaticでなければなりません。
またOnGUIの中にウィンドウ内のレイアウトなどを記述します。
これでウィンドウが開けるようになりました。

public class Example : EditorWindow {
    //メニューに項目追加
    [MenuItem("Example/新しくウィンドウを出します")]
    static void open() {
        EditorWindow.GetWindow<Example> ("Example");
    }

    void OnGUI() {
        EditorGUILayout.LabelField ("ようこそ");
    }
}

実行結果が以下のようになります。

enter image description here

複数プレハブ化

では、複数プレハブ化するためにドラッグアンドドロップできるウィンドウを作りましょう。

UnityがDragAndDropと言うUnityEditor上で行われるドラッグ&ドロップを操作するクラスを用意してくれているのでこれを使います。

先ほど作ったOnGUIメソッドの中にソースコードを書き足していきます。
まず、ドロップするエリアを追加するコードを書きます。
Event.currentで現在のUnityが処理中のEventが取れます。
そのEventがドロップエリア内でドロップしているなら、DragAndDrop.objectReferencesでドラッグしているオブジェクトすべてをプレハブ化する処理になっています。
OnGUIの中に、以下のソースコードを書きます。

private string saveFolderPath = "Assets/Prefab/";

void OnGUI() {
    var dropArea = GUILayoutUtility.GetRect(0.0f, 50.0f, GUILayout.ExpandWidth(true));
    GUI.Box(dropArea, "drop");
    var evt = Event.current;

    switch(evt.type) {
        case EventType.DragPerform:
            if(!dropArea.Contains(evt.mousePosition)) break;
            DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
            DragAndDrop.AcceptDrag();
            break;

        case EventType.DragExited:
            foreach(GameObject go in DragAndDrop.objectReferences) {
                Debug.Log(go);
                DropList.Add(go);
            }

            CreatePrefabs();
            Event.current.Use();
            break;
    }
}

//プレハブ化する関数
void CreatePrefabs() {
    foreach(GameObject go in DropList) {
        if(DropList == null) {
            return;
        }
        string prefab = saveFolderPath + go.name +".prefab";
        if(go.GetComponent<Image>() != null) {
            CreatePrefabImage(prefab, go);
        } else {
            PrefabUtility.CreatePrefab(prefab, go);
        }
    }
    DropList.Clear();
}

まとめ

今回は、複数のオブジェクトをプレハブ化する機能を実装しましたが、このエディタ拡張を使えば、自分の好きなようにカスタマイズすることができるようになります。
そうやって、Unityを自分好みに染めていってください

今回この機能を作るにあたっていくつか参考にさせていただいたサイトのリンクを載せておきます。
【エディタ拡張徹底解説】初級編①:ウィンドウを自作してみよう【Unity】
エディター拡張入門

rails で dbテーブルを truncate する

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

ruby からDBを操作するとき activerecord に頼らずにはいられません。insert, update, delete などは当然のように使っていますが truncate したいときはどうしたらよいでしょう。何故かよく忘れちゃうのでメモ

truncate するメソッドはモデルクラス用には用意されていませんでした。

ですので execute で直接 sql 文を実行します。

ActiveRecord::Base.connection.execute("TRUNCATE TABLE テーブル名;")

クラスメソッドとして登録してしまうときのサンプル

class TransactionTable < ActiveRecord::Base
  class << self
    def truncate
      connection.execute "TRUNCATE TABLE #{table_name};"
    end
  end
end

モデルには記載しないでトランザクションデータだけ削除するスクリプトを作っておくと安全かも

TRANSACTION_TABLES=TransactionTable, NotMasterTable
def clear_transaction
  TRANSACTION_TABLES.each do |transaction_model|
    ActiveRecord.execute "TRUNCATE TABLE #{transaction_model.table_name};"
  end
end

UnityでゲームのUI作りたい! 〜 物並べ編②

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

17新卒エンジニアがUnity関係で学んだことの備忘録を書きます。

はじめに

前回の記事では、Unityでシーンを作成し、キャンバス上に同じ形のボタンをVerticalLayoutGroupというコンポーネント(機能)を用いて自動配置で並べるところまで実装できました。
しかし、VerticalLayoutGroupで並べたボタンが画面外にはみ出してしまっています。

enter image description here

(前回の記事はこちら→UnityでゲームのUI作りたい! 〜 物並べ編①)

今回は、画像のようにはみ出してしまったボタン群を、スクロールしてクリック出来るようにしてみましょう。

準備

スクロールするUIを作るためには、大きく分けて
・スクロール対象となる領域
・対象を表示する領域

の二つが必要になります。

例として新幹線の窓から外の風景を眺める状況を挙げると、外の流れていく風景が「スクロール対象となる領域」にあたり、新幹線の窓が「対象を表示する領域」にあたります。
(この場合、実際に動いてるのはスクロール対象の風景じゃなくて新幹線ですが)

前回の時点で、スクロール対象となる領域の作成とボタンの配置が完了しているため、今回はまず対象を表示する領域を作成します。

enter image description here

さて、唐突ですが水色の部分が表示領域となります。
水色の領域の外にあるボタンは、たとえキャンバス上に存在していてもスクロールするまで見えないようにする必要があります。
その機能を追加する前に、この水色の表示領域の作り方をご紹介します。

前回はCanvas直下にScrollAreaというスクロール領域を作成しましたが、その間に表示領域となるオブジェクトを作成します。(本記事ではViewAreaとします)
親子関係の間に新たにオブジェクトを挟み込むため、まずCanvas直下にCreateでViewAreaを作成し、ScrollAreaをドラッグしてViewAreaの子オブジェクトにします。

enter image description here

ViewAreaを左側に寄せたかったので、PosXを-240にしています。
(前回は-160でしたが、さらに左側に調整しました。)

enter image description here

これで表示領域自体は作成できましたが、表示領域の外側にあるボタンが見えてしまっているので、自分の領域内だけ見えるようにする必要があります。
これを実現するためのコンポーネントが、 Mask です。
厳密には、マスク処理を行うコンポーネントは Mask と RectMask2D の2種類があります。

Mask

Maskコンポーネントを持っている親オブジェクトの子オブジェクトの形を、
親オブジェクトの形に制限する。
子オブジェクトが親オブジェクトからはみ出す場合、はみ出した部分が表示されなくなる。
マスクの形はImageコンポーネントに依存するため、画像次第でどんな形のマスクも作成可能。
(※画像に透過箇所がある場合、アンチエイリアスが効かないため境目が汚くなってしまいます。
綺麗な透過グラデーションを作る場合は、Mask機能を自前で実装する必要があります。)

RectMask2D

機能そのものはMaskコンポーネントと同じだが、
形が四角形(RectTransform依存)に制限される。
ただし、描画コストが少ないため、パフォーマンスはMaskより良い。

今回の表示領域は四角形なので、無駄の少ない RectMask2D を使用します。

enter image description here

RectMask2Dは、AddComponentするだけで自動的にそのオブジェクトの RectTransform を参照してマスク処理を行ってくれます。

さて、マスク処理を適用し、表示領域内のみボタンが見えるようになりました。

enter image description here

これでスクロール領域を作る準備が出来ました。
この勢いでスクロール機能を追加していきましょう。

スクロールの実装

早速ですが、スクロール機能は ScrollRect というコンポーネントで実現出来ます。
このScrollRectを、スクロールの対象となる領域(=本記事ではScrollArea)にAddします。

enter image description here

設定項目がたくさんありますね。一つ一つ見ていきましょう。

Content
 スクロール対象オブジェクトのRectTransformをアタッチします。
Horizontal 、 Vertical
 スクロールの方向を水平か垂直か決められます。
 両方にチェックを入れると上下左右にスクロール可能になります。
MovementType
 ・Unrestricted
  無制限にスクロール出来ます。
 ・Elastic
  マウス等のドラッグによりスクロール領域の端が表示領域の内側まで
  引っ張られた場合、ドラッグをやめることで表示領域の端と
  スクロール領域の端が一致するように、引っ張られたゴムが
  元に戻るような動作で自動的に戻ります。
 ・Clamped
  スクロールに制限を付け、スクロール領域の端が
  表示領域の内側に来ることがなくなります。
 ・Elasticity
  Elasticを選択した場合のみ設定可能。戻る際の弾力を設定します。
Inertia
 慣性の有無です。慣性がある場合、スクロールをやめても少しだけ
 慣性によってスクロール領域が動きます。
 ・DecelerationRate
  慣性の強さを0〜1の値で設定します。
ScrollSensitivity
 マウスのホイールや指によるドラッグに対する感度を設定します。
Viewport
 表示領域オブジェクトのRectTransformをアタッチします。
 ここでアタッチしたオブジェクトに基づいて、
 MovementTypeのElastic、Clampedが動作します。
HorizontalScrollbar 、 VerticalScrollbar
 スクロールバーがある場合、水平・垂直それぞれここにアタッチします。
OnValueChanged (Vector2)
 スクロールが行われ、位置が変わったときに呼び出されるイベントを設定できます。

これらの設定を、本記事の実装に合わせて行ったものがこちらになります。

enter image description here

スクロール対象領域をScrollAreaに、表示領域をViewAreaにそれぞれ設定し、
垂直方向のみスクロールさせたいのでHorizontalのチェックを外しています。
また、Elasticとの選択は好みの問題な気がしますが、MovementTypeをClampedにすることで見せる必要の無い部分(スクロール領域の外側) を見られないようにしました。

スクロールバー以外の設定が出来たので、とりあえず実行して動作を確認してみましょう。

enter image description here

ボタンが全て同じなのでピンと来ませんが、いい感じにスクロール出来ていますね。
MovementType:Clampedにより、必要以上にスクロールさせてもスクロール領域の端までしかスクロールしないようになっています。

スクロールバーの追加

次は、無くてもいいのですがあった方がスクロール領域っぽさが出るため、スクロールバーを追加します。
スクロールバーを実装するためのコンポーネントはScrollbarです。そのまんまですね。
スクロールバーはScrollbarコンポーネントとImageコンポーネントを自力で組み合わせて作成することも出来ますが、実はUnityのUI機能にそれらが最初から準備されています。

ViewAreaの上で右クリックし、UI -> Scrollbar を選ぶと、ScrollAreaと同じ階層にScrollbarが作成されます。

enter image description here

Scrollbarの子オブジェクトにはSliding Areaがあり、さらにその子にHandleがあります。
どれもその名の通りで、Sliding Areaはスクロールバーの可動領域、Handleはバーの掴む部分です。

enter image description here

Scrollbarコンポーネントにもたくさんの設定事項があります。
案の定、一つ一つ見ていきます。

Interactable
 スクロールバーに対して入力を受け付けるかどうかの設定です。
 Inspectorで設定することはほとんど無いと思いますが、
 ゲーム中の特定の時だけスクロール出来なくさせたい時など、
 スクリプトから設定することで効果を発揮します。
Transition
 スクロールバーの状態に応じて、バーの色や画像などを個別に設定出来ます。
 今回は ColorTint の場合のみ説明します。(状態に応じて色の遷移を行う)
 ・TargetGraphic
  遷移対象となるグラフィックです。デフォルトではHandleが設定されています。
 ・NormalColor 〜 DisabledColor
  それぞれの状態の時の色を設定します。
  上から順に、通常時、ハイライト時、押下時、無効時の色を設定出来ます。
 ・ColorMultiplier
  上記設定の明るさに倍率を設定します。暗い画像を用いる際に使うと効果的です。
 ・FadeDuration
  遷移にかかる時間を設定します。
Navigation
実行中、方向キーによってオブジェクトに対するフォーカスを切り替える際の設定です。
今回は使用しないため無視して構わないと思います。
HandleRect
HandleのRectTransformを設定します。
Direction
スクロールバーの方向を設定します。
垂直方向のスクロールならBottom To Top
水平方向ならLeft To Rightが一般的だと思われます。
Value
Handleの(初期)位置を0〜1の値により設定します。
Size
Handleのサイズを設定します。
NumberOfSteps
Handleの移動の際、段階を設けることが出来ます。
0、1なら滑らかに動き、それ以上の数の場合、数に応じて移動の段階が決定されます。
(例:3に設定した場合、初期位置、真ん中、終点の3箇所にしかHandleが移動しない)
OnValueChanged (Single)
Handleが移動した際に呼び出されるイベントを設定できます。

これらを本記事の目的に合わせて設定してみます。
…とはいえ、特に拘りがあるわけではないので、DirectionをBottom To Topに設定するだけにしておきます。
もちろん、このままではスクロールバーの位置がおかしいので、座標やサイズの調整は行います。

enter image description here

enter image description here

高さをViewAreaと同じ400に設定し、位置を右端に持ってきました。
ここで、少し話が逸れますが、UIを作る際に大事なポイントをご紹介します。


上の画像をよく見ると、今までの画像のRectTransformと違うところがあると思います。
そうです、前回の記事でチラっと触れた、Anchorの設定がされています。
このスクロールバーがどんな画面サイズでもViewAreaの右端に位置するようにするため設定したのです。
Anchorとは、親オブジェクトに対する中央座標のことでした。
つまりこのスクロールバーは、ViewAreaの右端中央を中心座標として座標を設定するようにしてあるのです。PosXもPosYも0になっていますが、中心座標(右端)=自分の座標 にしたいので、このようにしてあります。
ただし、Anchorを設定して座標を両方0にしただけでは、望む結果は得られません。
きっと、以下の画像のようになると思います。

enter image description here

スクロールバーが半分はみ出てしまっていますね。
実は先ほどのRectTransformには、もう一点、手を加えてありました。
それはPivotです。
Pivotは、オブジェクトの座標の起点のようなものだと思ってください。
Pivotは0〜1の値でX、Y座標それぞれに設定でき、デフォルトは0.5です。
Xの場合、0が左、1が右。Yの場合、0が下、1が上になります。
デフォルトのままの場合、Xの起点が0.5、つまり真ん中に設定されているので、スクロールバーのオブジェクトは自身のX座標の起点(=真ん中)と中心座標を合わせようとします。
すると、先ほどの画像のように右側半分がはみ出してしまうのです。
PivotのXを1(=右端)にすることで、右端が起点となるため、オブジェクトは右端と中心座標を合わせることになり、結果として少しもはみ出さずに表示されるのです。

このようにオブジェクトの各座標の起点 Pivotと、オブジェクトの中心座標Anchorの設定を行い、PosX、PosYを限りなく0に近づけることで、画面サイズが変動しても親オブジェクトとの位置関係を保つことが可能になります。


さて、大事な話とはいえ話が逸れてしまいましたが、これで任意の位置にスクロールバーを作成出来ました。
早速、実行してスクロールさせてみましょう。

enter image description here

そりゃ動きませんよね
当然です、ScrollRectの方に、このスクロールバーを設定していないのです。

というわけで、ScrollRectにScrollbarオブジェクトを設定してみます。

enter image description here

今回は垂直方向のスクロールなので、VerticalScrollbarのみ設定します。
すると、Visibilityという項目が出現します。これは、スクロールバーの表示設定です。

Permanent
 どんな時でもスクロールバーを表示します。
AutoHide
 (今回の例で言えば)中身のボタンの数が少ないなど、
 スクロールの必要が無い時にスクロールバーを非表示にします。
AutoHideAndExpandViewPort
 AutoHideの機能に加え、スクロールの必要が無い時に
 表示領域を拡大して表示します。

今回はAutoHideを選びました。
実際のゲームでも、スクロールバーはあるけどスクロールの必要が無いなんてUIはなんだか変な感じがしますよね。(※個人の感想です)

さて、これでようやくスクロールバーが真の力を発揮できます。

enter image description here

うまくいきましたね。
ちなみに、ScrollAreaのAnchorをcenter・top(上端真ん中)、Pivot(Y)を1にして、PosYを0にすることで、ScrollAreaのスクロール初期位置を一番上にしてあります。
(これを設定しないと、スクロールが真ん中から始まると思います)

まとめ

今回も長くなってしまいましたが、無事にスクロール機能を実装することが出来ました。
少しだけ、おさらいをしましょう。

・マスク処理はMaskまたはRectMask2Dコンポーネント
・スクロール領域にはScrollRectコンポーネント
・スクロールバーにはScrollbarコンポーネント
AnchorPivotを適切に設定して表示ずれを防ぎましょう

次回は、少し話題の違った記事を書きたいと思います。

それでは、長々とお付合いいただきありがとうございました。

Ruby/Rails に潜む罠 (find_by編)

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

ActiveRecord::Baseのクラスメソッドの中で最も基本的なメソッドの内の1つである find_by 。Railsを使う案件では頻繁にソースコードの中に現れるだろう。 この至極基本的なメソッドに、実は罠が潜んでいて、稀な条件下では発動する可能性がある。 (条件がレアな為、ほとんど発動しないけれど)

find_by の基本的な使い方

モデル(モデルインスタンスではない)をレシーバにして、引数に条件をハッシュまたはSQL文字列をセット。
返り値はモデルインスタンスとなる。

例1

Artist.find_by(name: 'The Beatles')
# SELECT `artists`.* FROM `artists` WHERE `artists`.`name` = 'The Beatles' LIMIT 1

例2

Artist.find_by("name = 'The Beatles'")
# SELECT `artists`.* FROM `artists` WHERE (name = 'The Beatles') LIMIT 1

罠が発動する条件

モデルに対するテーブルが動的に変化する場合

class Artist < ActiveRecord::Base
  self.table_name = :artists_1 # デフォルトの参照テーブル
end
# 参照テーブルを切り替えるクラス
class TableSwitcher
  def self.exec
    if Artist.table_name == :artists_1
      Artist.table_name = :artists_2
    else
      Artist.table_name = :artists_1
    end
  end
end

この条件は、Railsの規約には沿っていない。つまりRailsの規約に全て沿っていれば、本記事の内容は気にする必要はない。
大半の案件はRailsの規約には沿うだろうが、大量データ更新の為、2つのテーブルを、TRUNCATE+INSERTしながら交互に参照を切り替えていく方針を取っている場合、この問題に直面する事になる。

罠が発動する条件下でfind_byを使うとどうなるか

Artist.table_name # => artists_1
Artist.find_by(name: 'The Beatles')
# SELECT `artists_1`.* FROM `artists_1` WHERE `artists_1`.`name` = 'The Beatles' LIMIT 1

TableSwitcher.exec # 参照テーブル切り替え

Artist.table_name # => artists_2
Artist.find_by(name: 'The Beatles')
# SELECT `artists_1`.* FROM `artists_1` WHERE `artists_1`.`name` = 'The Beatles' LIMIT 1

参照テーブルは切り替わっているはずなのに発行されるSQL中の参照しているテーブル名が切り替わっていない!
これでは、(テーブルを切り替えて)データを新しても、実際は参照するデータが古いままになってしまう可能性がある。

原因

デフォルトのfind_byメソッドは発行したSQLをキャッシュする。(ActiveRecord::StatementCache)
よって、参照テーブルを切り替えた後でも、切替前のキャッシュが残って、切替前のテーブルが参照されてしまう。

対処方法

罠が発動する条件に該当するモデルでは、デフォルトのfind_byが使用されないよう、クラス内でオーバーライドし、where+firstに書き換える。
whereメソッドはキャッシュされないので、この対処が可能となる。

class Artist < ActiveRecord::Base
  self.table_name = :artists_1 # デフォルトの参照テーブル

  class << self
    def find_by(*args)
      where(*args).first
    rescue
      super # 例外処理はスーパークラスに任せる
    end
  end
end

注意点

rubocop を導入している場合は、「where+first は find_by と書き直せ」という警告が出る。
意図的にwherefirstに分けている訳なので、該当部分だけ以下のようにrubocopチェックの対象外とする必要がある。

def find_by(*args)
  # rubocop:disable Rails/FindBy
  where(*args).first
rescue
  super
end

【Rails】gem ‘global’の使い方【global】

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

環境ごとに値を設定する場合よくgem ‘config’が使われますが、個人的にgem ‘global’の方が使いやすいと思うので紹介します。

gem ‘config’との違い

gem ‘config’との大きな違いは.ymlファイルの持ち方です。

gem ‘config’

config/settings.yml
config/settings/development.yml
config/settings/production.yml
config/settings/test.yml

config/settings.yml

web_domain: localhost
api_domain: api.local

config/settings/production.yml

web_domain: web.com
api_domain: api.com

gem ‘config’は環境ごとに.ymlを持つのに対し、gem ‘global’は機能ごとや値の種類ごとにファイルを持つ形になります。

gem ‘global’

config/global/domains.yml

default:
  web: localhost
  api: api.local

development:
  web: localhost
  api: api.local

production:
  web: web.com
  api: api.com

test:
  web: test.com
  api: api.test.com

導入方法

1.Gemfileにgem ‘global’の追記

gem 'global'

2.config/initializers/global.rbの作成

Global.configure do |config|
  config.environment = Rails.env.to_s
  config.config_directory = Rails.root.join('config/global').to_s
end

使い方

基本

> Rails.env
=> "development"

> Global.domains
=> { "api" => "api.local", "web" => "localhost" }

> Global.domains.api
=>"api.local"
> Rails.env
=> "production"

> Global.domains
=> { "api" => "api.com", "web" => "web.com" }

> Global.domains.api
=>"api.com"

名前空間付き

config/global/name_space/domains.yml

> Global.name_space.domains
=> { "api" => "api.com", "web" => "web.com" }

> Global.name_space.domains.api
=> "api.com"

ネストを入れる

config/global/domains.yml

default:
  nest:
    web: localhost
    api: api.local

development:
  nest:
    web: localhost
    api: api.local

production:
  nest:
    web: web.com
    api: api.com

test:
  nest:
    web: test.com
    api: api.test.com
> Global.domains.nest
=> { "api" => "api.com", "web" => "web.com" }

> Global.domains.nest.api
=> "api.com"

ERB

config/global/domains.yml

default:
  web: localhost<%= 1 + 2 %>
  api: api.local
> Global.domains.web
=> "localhost3"

リロード

> Global.reload!

他にもjavascriptで使えたりするのでぜひ使ってみてください。

キーフレームアニメーション、絵コンテ制作

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

はじめに

この記事はspritestudioを使用する前提で書いております。
他のソフトには対応できない部分もありますのでご了承ください。

こんにちは、2Dモーションを勉強中のなすちゃです。
今回も自身の復習用にまとめていきます。

絵コンテとは

アニメーションとしてものを動かすことに関して必要になってくるのが絵コンテになります。
映像物を作る前にイラストなどで1つのカットを説明するものになります。

いきなり物体を動かすのではなく「こんな動きにしたい」「ここのシーンは尺を長くする」など設計図を組み立てていきます。
漫画のネームみたいなものですね。

自身で製作したものをわかりやすくまとめるものとして大切ですが、仕事として通す際には様々な人とチームとして製作します。食い違いや説明不足にならないようにする役割でもあります。

案出し

コンテを作る前に、このモーションはどの場面をイメージしているのかおおまかなプロットを考えるとやりやすいです。

たとえば、キャラの走るモーションを考えてみます。
走るといっても場面により演出が変わっていき様々なパターンが生まれます

・どんな場面で走っているのか
・喜怒哀楽が含まれるのか
・キャラの個性

など、基礎にある世界観・キャラクターの設定をもとに感情が含まれる動きを考えます。
今回は女の子のキャラクターを使用していきます。

・道を走るなど移動する場面をイメージ
・軽やかに走り、余裕のある表情
・長いスカートを身につけているのでフワッと揺れるように

ざっと思いついたネタを出していき、そこから組み合わせていくのも面白いと思います。

いざ、コンテを製作します。

キャラクターはキーフレームを打てるよう手足・頭部・胴体など各パーツに分かれたテクスチャを使用していますが、相手に伝われば手描きのスケッチでも棒人間などでも構いません。
各製作現場に沿ったスタイルで行いましょう。

プロットに沿ってキャラクターを動かしていきますが、
実際にコマ切をしていると当初のイメージに追加したい要素やここはこうした方が可愛くなるのでは…!というアイディアも出てきます。

enter image description here

この場合も、より個性が表現出来るように表情差分の追加をしました。
瞬きや笑う要素一つ加えるだけでも見栄えが変わっていきます。

ループで走っているように見せたいため、始まりと終わりに同じポーズを入れ後半に走りながらふと笑う要素を組みました。

こういったコンテから考えていくとモーションが制作しやすくなります。
自分がどういう動きをさせたいか、楽しんで案をだしていくことが大切だと思います。

簡単デザイン。ThemeRollerを使う

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

Webページに欠かせないボタン、フォーム、セレクトメニュー…。 デフォルトのものを使うと味気ないけれど、サイトの雰囲気にあったものを0から作るのはなかなか難しい… そんなときの強い味方。そんな「ThemeRoller」について紹介します。

http://jqueryui.com/themeroller/

上記URLにアクセスすると、アコーディオンメニューやボタン、チェックボックスなどのサンプルが並んでいます。

enter image description here
▲ボタンやオートコンプリートは、実際に押したり入力したり出来ます。

左にあるツールバーで、フォントや色合いを調節できます。
調節したものは右のサンプルで即確認でき、分かりやすいです。

enter image description here
▲背景のテクスチャなども設定可能。

基本的には、デフォルトのデザインをこのツールバーで調整し、
理想のデザインに持っていくのですが、
「デフォルトのデザインが理想と離れ過ぎていて調整が面倒…」という場合もあります。

そんなときはツールバーの「Gallery」タブをクリック。
ThemeRollerにあらかじめ用意されたテーマがずらりと表示されます。
それぞれのテーマの横にある「Edit」をクリックすると、そこから調整が出来ます。
自分の理想イメージに近いテーマから、調整していきましょう。

enter image description here
▲現時点で25種類のテーマが用意されています。もちろんこれをそのまま使うのもアリ。

調整が出来たら、「Download theme」をクリック。
作ったスタイルシートをまるまるダウンロードできます。
ダウンロードしたスタイルシートをWEBページで読み込むようにすれば完成です。


ThemeRollerではGUIで各フォームやボタン等のスタイル調整が簡単に出来ます。
ただし、ボタン間のマージンや、枠線の太さなどはサポートされていないので、
細かい部分は自分でCSSを改修する必要がありますが、
大まかにデザインをするのには便利だと思います。

【git】コミットログ散らかした!ログを編集する方法

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

コミットログの編集の仕方を簡単にまとめてみました。

はじめに

最近東京に馴染んできた(気がする)Be82Mです。
自分が業務上よくcommit漏れしてしまったり、ちょっと実装してはコミット、とちまちまコミットしてログを散らかしがちなのでpush前にコミットをまとめたりするのですが、どうだったっけ?と調べたり時間がなくて結局そのままpushしてしまったり…ということが何度もあったので、今回備忘録としてコミットの改ざんの仕方を自分なりにまとめることにしました。
 

手順

今回コミット漏れした場合を例にします。

とりあえずコミット漏れしたファイルをaddして再度コミットします。

h82w-no-MacBook-Pro:file Be82M$ git commit -m "コミット漏れ"
[branch_name f40110a] コミット漏れ
 1 file changed, 2 insertions(+)

ログを確認すると当然ですがコミットログに修正したのが残っています。

h82w-no-MacBook-Pro:file Be82M$ git log
commit igtismsmehyoowutrilmoevmeodvreihveorttafbaesaiton
Author: Be82M <be82m@doruby.com>
Date:   Mon Jul 24 18:19:48 2017 +0900

   コミット漏れ

commit deaomcwmhniadgnoecwcennsaedtamnenfarweie
Author: Be82M <be82m@doruby.com>
Date:   Mon Jul 24 12:29:35 2017 +0900

    A機能実装完了
 

ここで改竄コマンドgit rebaseが登場です。

$ git rebase -i branch_name~number

branch_name: コミットを消したいブランチの名前
number: コミットログの表示数

これを実行するとテキストが開きます(稀にテキストエディタ等で開くことがあるそうですが、大概vimで開きます)

  1 pick d83743a B機能実装
  2 pick d99647d A機能実装
  3 pick f40110a コミット漏れ

消したいコミットである3行目のpickをfもしくはfixupに書き換えます。
※このオプションについては後述しています。

  1 pick d83743a B機能実装
  2 pick d99647d A機能実装
  3 fixup f40110a コミット漏れ

変更を保存して閉じます。
もう一度ログを確認して見ます。

h82w-no-MacBook-Pro:file Be82M$ git log
commit deaomcwmhniadgnoecwcennsaedtamnenfarweie
Author: Be82M <be82m@doruby.com>
Date:   Mon Jul 24 12:29:35 2017 +0900

    A機能実装完了
 

これでログをまとめることができました。
 

オプション

git rebaseしたときに開くvimの下部にも書いてありますが、毎回英語は読みたくないのでまとめておきます。

  • p, pick

 コミットを使用する
 そのままコミットを残す場合はこのコマンドのままにしておく。

  • r, reword

 コミットメッセージを編集してこのコミットを使用する

  • e, edit

 コミットをなかったことにする(またpickに戻せばコミットは戻ってくる)

  • s, squash

 コミットを前のコミットと融合する

  • f, fixup

 コミットを前のコミットと融合するが、コミットメッセージを破棄する

  • x, exec

 後に書かれたコマンドを実行する

絶対いらない保証もないので実際にやったことはないのですが、行自体を消すとその行に該当するコミットそのものが完全に消えてしまうようです。
間違って消してしまわないように気をつけましょう…!
 

最後に

業務上欠かせないgitですが、理解しきれておらずgitについて書いてある参考書やサイトを渡り歩いてる段階です。
まだまだ打ったことないコマンドもたくさんあり、そういった実際に体感していないものは全然身になっていないのでコマンド打つたびに怯える日々です。
状況に応じていろんなコマンドを少しずつ使ってマスターしたいと思います。

肥大化するAIと対峙する時に覚えておきたいこと

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

戦略的に切り崩していかなければ、立ち向かえない可能性もあります。

はじめに

みなさん、お久しぶりです。
新卒エンジニアのくろすです。

さて、残念ながらこの記事には最近話題のAIの話はほとんどありません。

言い訳

いや本当はMNISTのDataSetから手書き数字認識をやってみたって話を書こうと思ってたんです。今月半ばまでは。
弊社はrubyistが多いので、rubyでNNを書いて簡単に説明してみたってやるつもりだったんです。
昔MATLABで書いたプログラムがどっかにあるから、ピャーって書いちゃおうって。

9割遊びだからお家で作業を進めてるんですよ。
rubyでMNISTのデータセット取ってきて、バイナリデータだからそれを画像ファイルに変換してですね。
そして、こう、アニメがですね、アニメを見てるとですね……

rubyでNN作るやつはそのうち記事にはします。

そもそもAIとは

AI流行ってますよね。
映画でも機械学習がーって話があったり、ギークがリア充にボコボコにされたり、出身大学が悪の巣窟扱いされたり。

じゃあそもそもAIってなんですかって話です。
Artificial Intelligence
コンピュータ上で知能を実現しようとする試みやそれに関連する技術がそう呼ばれているよう思います。
人工知能学会の人工知能って何?には以下のように書かれています。

「人工知能」とは何だと思うでしょうか?まるで人間のようにふるまう機械を想像するのではないでしょうか?これは正しいとも,間違っているともいえます.なぜなら,人工知能の研究には二つの立場があるからです.一つは,人間の知能そのものをもつ機械を作ろうとする立場,もう一つは,人間が知能を使ってすることを機械にさせようとする立場です(注1).そして,実際の研究のほとんどは後者の立場にたっています.ですので,人工知能の研究といっても,人間のような機械を作っているわけではありません.

学習や推論をするゲームのAIだと囲碁や将棋が有名ですよね。
ニューラルネットワークなどの手法で学習を行なっているようです。

ゲームのAIって???

学習や推論等を行わないゲームのAIの場合は、なんらかの単語をトリガーに会話を返す人工無脳と似たような存在です。
条件分岐に従った行動しか取れない、要するにただ設定されているだけの戦略と言い換えてもいいかもしれません。

かなり適当ですがこんな感じです。

class AI

  def initialize(code)
    @code = code
  end

  def select_action(code)
    send("select_action_#{code}")
  end

  # ここからAI
  def select_action_1
    # 1の倍数のターンだけアホになる
  end

  def select_action_2
    # 2の倍数のターンだけアホになる
  end
  alias :select_action_4 :select_action_2 
  # code:4のAIはやっぱり2の倍数の時もアホになった方がいい感じ

  def select_action_3
    # 3の倍数のターンだけアホになる
  end
end

sendメソッドで動的にメソッドを呼び出すことで大量のcase文が並ぶことは避けられていますが、このクラス自身が全ての戦略を知っているということは様々な問題に繋がります。
AIが増えるにつれ条件分岐が増え、空は堕ち、大地は割れ、海が涸れます。
こんなところで死ぬわけにはいかないので大問題です。

生存戦略

さて、この肥大化する戦略群と向き合うとしましょう。
うまいこと戦略を切り分けてあげないと、とてもじゃないけど生き残れる気がしません。
取替え可能な戦略をうまいこと使いたいなぁ……
戦略を切り替えたいなぁ……
そうStrategy Patternの出番です。

module AIManager
  @codes_to_ai = {}

  def self.set_code_to_ai(klass, codes)
    codes.each do |code|
      @codes_to_ai.merge!({code => klass})
    end
  end

  class NotIntelligence < StandardError; end

  def self.get_ai(code)
    # ai = AIManager.get_ai(code).new(code)のように呼ばれた時の大域脱出で使う
    raise NotIntelligence unless @codes_to_ai.keys.include?(code)
    @codes_to_ai[code]
  end

  module StrategyInterface
    OVERRIDE_PROHIBITION = [:initialize].freeze

    def self.included(klass)
      klass.define_singleton_method(:method_added) do |symbol|
        if OVERRIDE_PROHIBITON.include?(symbol)
          raise "Do not override : #{symbol}" 
        end
      end
      AIManager.set_code_to_ai(klass, klass::CODES)
    end

    def initialize(code)
      @code = code
    end

    def select_action
      raise "Called abstract method : select_action"
    end
  end
end

このようなInterfaceを作り、AIManager.get_ai(code)を介して各AIクラスにアクセスすることで、codeさえわかれば欲しいAIを引っ張り出すことが可能です。
StrategyInterface 内で定義されているincludedというのはモジュールがincludeされた時にrubyが呼び出すメソッドで、引数にはclassが自動的に入ります。
Interfaceにせずにabstractなクラスを作っても良いのですが、同じことをやろうとしても、クラスが継承された時に呼ばれるinheritedメソッドは

class Hoge < SuperClass

のような一文を解釈した時に呼ばれてしまうためうまくcodeを管理者に渡せません。

module AIManager
  class AlwaysAho
    CODES = [1].freeze
    include StrategyInterface
    def select_action
      # 1の倍数のターンにアホになる
    end
  end

  class UsuallyAho
    CODES = [2, 4].freeze
    include StrategyInterface
    def select_action
      # 2の倍数のターンにアホになる
    end
  end

  class SometimesAho
    CODES = [3].freeze
    include StrategyInterface
    def select_action
      # 3の倍数のターンにアホになる
    end
  end
end

アホになる頻度でAIのクラスの名前を変更することに成功しました。
実際に使う側からはこのAIクラスが本当にAIかはどうでもよく、select_actionが呼べてたまにアホになれば、それはAIだというふうに捉えていきます。
アヒルのように歩きアヒルのように鳴くものはアヒルに違いない。ということです。

終わりに

アホになれないcodeを割り振られた子たちはNotIntelligenceエラーを返されるという、なんとも分かりにくい説明コードを書いてしまいました。
こんな書き方はしてますがrubyでのStrategyパターンではconcreat strategyはlambda式を使った方が良さそうな気がします。

話はちょっと変わりますが、醜いアホの子が実は人工知能だったら面白くないですか???
暇と余裕とゆとりがあれば、そのうち機械学習をアホの子に突っ込んでみたいなぁって思いました。

立ち絵を魅力的に描く①【ポーズと表情でキャラクターを伝える】

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

はじめに

nocoです。暑い日々が続いており、液晶ペンタブレットの発熱が気になる今日この頃です。

今年の春に入社してから1ヶ月間ほどキャラクターの立ち絵制作の業務に携わらせていただきました。私自身立ち絵への理解が浅く、短い期間の中でもたくさんの発見がありました。

立ち絵は、その性質上ゲームの中で長時間目にする重要なグラフィックです。
そんな立ち絵を魅力的に描くためのポイントを共有したいと思います。

立ち絵とは

enter image description here
弊社・株式会社アピリッツ運営のMMORPG「かくりよの門」の会話シーン

立ち絵とは、その名の通りキャラクターの立ち姿を描いたイラストのことです。
主にノベルゲームやアドベンチャーゲームの会話シーン(ストーリーパートなど)に用いられます。
会話シーンという性質上、複数のキャラクターが並ぶことが多いため「動」ではなく「静」の印象を受けるポーズで描かれることがほとんどです。

多くの場合、キャラクターごとにそれぞれ表情の差分を用意します。
異なる表情をシーンの状況に合わせて表示することで止め絵ながら会話を華やかに演出することができます。
また、必要に応じて表情の他にもポーズ差分や衣装差分が用意されることもあります。

立ち絵はキャラクターの外見を伝えることは勿論ですが、「誰がどういった表情で話しているか」を視覚的に伝えることができます。
小説でいうところの地の文が必要なくなり、会話のテンポも良くなりますね。

キャラクターを作ろう

立ち絵の描き方についてお話する前に、前提となるキャラクターデザインのことを簡単にお話させていただきます。
ゲーム制作の現場では依頼としてこういったキャラクターを作ってくれ!と指定がある場合がほとんどですが、自分で1からキャラクターを作ることもあります。

最初に、描きたいキャラクターの設定を文字で書き出してみましょう。

【外見】性別・年齢・髪型・服装 など
【内面】性格・信念・声・話し方・過去 など


筆を動かしているうちに良いアイデアが浮かぶことも多いので、最初から完璧な設定を作り込む必要はありません。設定を元にイメージスケッチを描き、デザインが固まったら立ち絵の制作に入ります。

外見はもちろんですが、内面をしっかりと作り込んでおくことでキャラクターが活き活きとしてくるように感じられます。
キャラクターの内面の情報をどこまで視覚的に伝えられるかがデザイナーの腕の見せ所です。
設定の段階からキャラクターの要素を立ち絵の中にどう盛り込んでいくかイメージしておくと良いですね。

キャラクターデザインについて詳しく知りたい方は、本やWeb上に専門的な講座や記事があるためそちらをご覧ください。
次項より、立ち絵を魅力的に描くポイントについて解説していきます。

立ち方で人柄を表現する

立ち絵において、キャラクターの立ち方はとても重要です。

まず、ベースとなる素体を用意します。6頭身の何の変哲もない少女です。
enter image description here
この素体を、4つの性格をイメージしてそれぞれポーズを取らせました。
enter image description here
体型は同じでも、ポーズを変えるだけでまるで別人のようになります。
このように、立ち方ひとつでキャラクターの人柄を表現することができます。

棒立ちではキャラクターの魅力が十分に伝わらず、人形のように生気のない印象を受けます。
意図してそういった表現をしたいのでなければ、どこか一か所でも動きをつけてあげましょう。
片手や片足を動かすだけでもキャラクターが活き活きとしてきます。

例にあげたような「元気」「内気」という括りの中でもさまざまな種類があります。
キャラクターのイメージを膨らませ、それに合った最適なポーズを決めてあげましょう。

表情でさらに魅力的に

前述したように、立ち絵にはベースの表情に加え基本的な喜怒哀楽の表情が用意されます。
目の伏せ方や眉の位置、口の開け方など、パーツを一部描き変えて表情を作っていきます。
手間は掛かりますが、差分の種類が多いほどキャラクターの個性を繊細に伝えることができます。

先ほどの「元気」ポーズを元に1人のキャラクターを描き起こしました。
enter image description here

このキャラクターに喜怒哀楽の表情を付けてみます。

enter image description here

元気な子というポーズからの情報に加え、差分によって表情がコロコロと変わる感情豊かなキャラクターということが伝わるかと思います。
立ち方に加え、表情でさらにそのキャラクターの人柄を掘り下げることができます。
特に、外見と内面にギャップのあるキャラクターはその魅力をアピールするチャンスです。

一口に喜びと言ってもさまざまな種類があります。
大きく口を開けてニカッと笑ったり、目を細めて優しく微笑んだり…これだけでも与える印象が大きく変わります。
キャラクターたちが皆同じ顔をして笑うなんてことはありませんよね。

立ち方と同様に、キャラクターのイメージを膨らませて魅力的な表情を引き出してあげましょう。

まとめ

今回は立ち絵の根幹となるポーズと表情を描くポイントについて書かせていただきました。
ポーズや表情だけでもキャラクターの個性を引き出せているのなら、衣装や装飾を描き込んでいくことでさらに魅力が増していきます。
ベースをしっかり作り込んでおくことで描画もスムーズに進めることができます。

立ち絵を描くときには、頭の中で動き出すくらいキャラクターのことをたくさんイメージしてあげるのが大切です。
また、日頃から既存のアニメやゲームのキャラクターの魅力や特徴がどこに表れているのか考えて観察してみると良いかもしれません。

次回も立ち絵についてのお話を続けて書きたいと思います。

Googleデータポータルの計算フィールドが役立つ!REGEXP_MATCH関数編

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

Googleデータポータルの計算フィールドでは正規表現を使った記述が可能です。一致条件の正規表現に使えるのがREGEXP_MATCH関数。特定のルールに一致するデータをフィルタリングすることができ、CASE関数などと組み合わせると実用の幅が広がります。REGEXP_MATCH関数の使い方について、実例を踏まえてご紹介いたします。

この記事でまとめられていること

こんにちは。株式会社アピリッツでアナリストをしているssekiです。
以前、Googleデータポータルの計算フィールドでCASE関数の使い方について記事を書きました。
CASE関数は置換・統合を行う際にとても役立つということで実例を踏まえてご紹介しました。
CASE関数があるからマイレポートの代わりにデータポータルを使ってみよう、という方も多いのではないでしょうか。
ただし、アナリティクスとデータポータルでは仕様や記述方法が違う部分も多々あり、難しく感じることもあるでしょう。

今回紹介するREGEXP_MATCH関数はCASE関数と一緒に使って、データの抽出条件を正規表現で記述することができる関数です。
REGEXP_MATCH関数が使えるようになると、Googleアナリティクスの「計算指標」の代わりに計算フィールド上で正規表現が使えるようになります。

※計算指標は1ビューあたり5個までしか作成できませんが、計算フィールドは無制限に作れます。そのため、多数の計算指標を作成したいとの悩みを抱えているならば、Googleデータポータルの計算フィールドがおすすめです。

今回は、Googleデータポータルの計算フィールドで正規表現を使う方法、第一弾として一致条件ができる「REGEXP_MATCH関数」についてご紹介します。

正規表現とは

まず簡単に正規表現についておさらいしておきましょう。
正規表現とは、「いろんな文字列を一つの文字列で表現するための記述方法」です。
例えば、こんな例を考えてみましょう。
以下のようなページURLがあるとします。

20170701.php
20170702.php
20170703.php
...
20170731.php

ブログなどでは、このように投稿日をページURLにしている例がよく見られますね。
このうち、2017年7月1日~2017年7月7日までの1週間に書いたブログ記事のPV数を計測したいとします。
まず、Googleアナリティクスの正規表現にしたがって対象のブログ記事を抽出するよう記述してみます。

(20170701|20170702|20170703|20170704|20170705|20170706|20170707)\.php

ここでは、3つの正規表現記号が使われています。
()と|と\ですね。それぞれ丸カッコとパイプとバックスラッシュと呼びます。
まず、丸カッコは「他の正規表現をグループ化」する記号です。丸カッコで囲われている正規表現はカッコ内でしか効果を発揮しません。
次に、パイプは「OR条件」を意味します。
最後に、バックスラッシュは「次の正規表現記号を打ち消し」、普通の文字として解釈します。
実は、「.」(ドット)も正規表現記号として使うことができるため、その効果を打ち消すために使っています。
つまり、先ほどの正規表現を日本語に直すと、

「20170701か20170702か20170703か20170704か20170705か20170706か20170707」と「.php」がついている文字列

となります。
でも、この書き方だと選択する数が増えたとき大変です。今回1週間分を例にしましたが、1か月分だと最大31個も入れなきゃいけないですよね。
この他にもいろいろな正規表現記号があり、今回の例をもっと楽に書くこともできます。
例えば、こんな感じに。

2017070[1-7]\.php

新たな正規表現記号として[]と-を使いました。読み方は角カッコとハイフンです。
まず、角カッコは「囲まれた文字が任意の順序で文字列に含まれる場合」を表す記号です。
そして、ハイフンは「角カッコ内の文字範囲」を表します。
この二つは合わせて使うことが多く、先の[1-7]は「1から7までの範囲の数字を含む」を表すようになります。
先ほどの正規表現を日本語に直すと、

「2017070」の次に「1から7までの範囲の数字を含み」、その後「.php」がついている文字列

となるので、今回の条件では最初の例と同じ文字列と一致することがわかりますね。

説明が長くなりましたが、Googleアナリティクスではこのような正規表現記号を使うことができ、データから必要な分だけを抽出することを助けています。
その他の正規表現を知りたい人は公式のヘルプページを見てみてください。

計算フィールドでの正規表現の使い方

さて、ここまでGoogleアナリティクス上での正規表現記法についてご紹介いたしました。
実はGoogleデータポータルの表やグラフで用いるフィルタ機能では、アナリティクスと同じ正規表現をそのまま使います。
ただし、計算フィールドだけは特殊で、アナリティクスの正規表現をさらに高機能にしたもの(使える正規表現記号が多くなったもの)を用いることができます。
その方法の一つが今回紹介するREGEXP_MATCH関数です。
REGEXP_MATCH関数は「Google RE2」という正規表現を使ってフィールドの式と一致するものを抽出する関数です。
先ほどと同じ例を考えてみましょう。

20170701.php
20170702.php
20170703.php
...
20170731.php

このうち、2017年7月1日~2017年7月7日までの1週間に書いたブログ記事を抽出するには次のように記述します。

CASE WHEN REGEXP_MATCH(ページ,"2017070[1-7]\.php") THEN "2017年7月1日~2017年7月7日" END

REGEXP_MATCH関数ですが、CASE関数との相性がとてもよい関数です。
ちなみに、CASE関数は置換するのに使った関数でしたね。詳しくは「Googleデータポータルの計算フィールドが役立つ!CASE関数編」の記事を参照していただければと思います。

REGEXP_MATCHはカッコ内に2つの変数をとります。
REGEXP_MATCH(X,Y)と置くと、Xに当たるのが「抽出元となるディメンションあるいは指標」です。
そして、Yが「一致条件の条件式」に相当します。
この例ではXに「ページ」、Yに「先ほどの正規表現」を設定することで、THENの後に記述された「2017年7月1日~2017年7月7日」という文字列に条件に一致したページ群がまとめられます。

あとは、お好きな表やスコアカードでページビュー数を指標にセットしていただければ、2017年7月1日~2017年7月7日までの1週間に書いたブログ記事のPV数を計測することができますね。

Googleデータポータルでアナリティクスのデータ管理が可能に!

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

Googleデータポータルに新機能が追加され、アナリティクスデータを閲覧レポート上で切り替えることが可能になりました。データポータルの閲覧権限だけで複数のアナリティクスデータを使えるので、情報共有のリスクが減る機能といえます。今回はデータ管理機能の使い方についてご紹介いたします。

この記事でまとめられていること

こんにちは。株式会社アピリッツでアナリストをしているssekiです。
最近Googleデータポータルを使う機会が多くなり、作成したレポートを共有することが多くなりました。
データポータルは共有が簡単な反面、編集権限を与えていると知らぬ間に誰かに書き換えられていて困ることもしばしば・・・。
そんな不満を持っている最中、Googleが7月14日に神アップデートしてくれました!
enter image description here

「データ管理・・・?」

これを見つけた時の僕の気持ちです。
とりあえずググったのですが、日本語ページが何ひとつとして見つからなかったのでGoogleヘルプページ(英語版)を参考に使い方を理解しました。
今回は、データソースのGoogleアナリティクスビューをレポート上で変更できるデータ管理の機能について、使い方を交えてまとめてみました。

Googleデータポータルのデータ管理とは

Googleデータポータルの共有権限には2種類あります。

  1. 編集者権限:リンクURLを知っていればレポートを閲覧・編集どちらも可能
  2. 閲覧者権限:リンクURLを知っていればレポートを閲覧可能だが、編集は不可

1つのデータソースだけを定点観測する分には閲覧者権限のみでも問題ないのですが、複数のデータソースを見たり適宜フィルタリングをかけたり編集したい場合には編集者権限が必要でした。

しかしながら、複数人が勝手にレポート内容を変えると管理が煩雑になり、結構面倒くさくなります。
それを防ぐために、これまではデータソースごとに同じテンプレートのレポートを複数作成することで対応していました。(これも管理が面倒ではあるけど)

そんな状況で、データ管理が役立ちます。
データ管理はざっくりいうと「閲覧者権限でもレポートで使われているデータソースを(アナリティクスに限り)変更できる機能」になります。

データ管理の使い方

データ管理の使い方は極めて簡単です。まず、普通にレポートを作成しておきます。
とりあえずGoogle Merchandise Storeのデータを使って、メディア別のセッション数を表にしてみました。
enter image description here
次に、データ管理をクリックした状態で長方形を書きます。
enter image description here
「ビューを選択」が出ましたね。この状態で閲覧画面に戻りましょう。
するとこのように表示されます。
enter image description here
「ビューを選択」をクリックすると自身が持っているアナリティクスの閲覧権限一覧が表示されます。
変更したいビューにカーソルを合わせてクリックすることで、レポート内の全データを変更することができます。
enter image description here
新卒コミュニティサイトのデータを使って表のデータを入れ替えてみるとこんな感じです。
enter image description here
現在表示しているアナリティクスビューの名前が表示され、表のデータが変更されました。
ほぼワンタッチで変更できるので、データポータルに慣れていなくても簡単に使えます。

データ管理を使う際の注意点

簡単に使えて有用なデータ管理ですが、いくつか問題点もあるため記載しておきます。

1つ目に、アナリティクスデータだけしか対応していないことです。
もし、Search ConsoleやAdwordsなどの他のデータソースを切り替えたいと思っている場合、現段階ではデータ管理の機能を使用することはできません。

2つ目に、アナリティクスビューの閲覧権限を持っていなければいけないことです。
データポータルのレポートにデータソースとして使われている場合はそのまま見ることができますが、データ管理として変更する場合には閲覧者自身が該当のアナリティクスビューの閲覧権限を持っている必要があります。

1つのレポート内で複数のデータ管理をする方法

上記では、データ管理によってレポート内の全データを総入れ替えする方法についてご紹介しました。
実際のレポート内で使うには場面が限られますが、1つのレポート内で異なるデータ管理を2つまで切り替える方法を見つけたのでご紹介いたします。

先ほど作ったレポートを利用して説明します。
まず、表とデータ管理をそれぞれコピーします。(わかりやすいように並べました。)
enter image description here
レポート上にある表やグラフなどすべての要素には、レベルというものが存在します。
データ管理で変更しているデータは同じレベルのものを変更しているため、レベルを変更することで異なるデータ管理の効果を受けることができます。

デフォルトでは、「ページレベル」に設定されているので、左側の表とデータ管理を「レポートレベル」に変えてみましょう。
表にカーソルを合わせて右クリックすると図のように表示されるので、「レポートレベルに変更」をクリックすると変更できます。
enter image description here
ちなみに、もう一度同じことをすると「ページレベルに変更」と文言が変わって、「ページレベル」に変更できます。
左側の表と「ビューを選択」をページレベルに変更した後、閲覧画面に戻ります。
左側の「ビューを選択」のみを変更してみます。すると、左側の表だけが変更されました。
enter image description here
右側についてもアナリティクスビューを変更することで、右側の表だけが変更されます。
このように、レベルを変更することでデータ管理を複数設置することも可能です。

まとめ:データ管理はどんなときにおすすめか

データ管理は閲覧者権限でもアナリティクスデータのビューを変更することができる機能でした。
アナリティクスビューごとにデータポータルレポートを作成するとなると作成も管理も面倒ですが、ひとつのレポート上で切り替える分にはワンタッチなのでお手軽です。
今回はチーム内での共有に視点を置いて説明しましたが、その他にも例えば次のようなことに使えるかなと思います。

  1. テンプレートとなるデータポータルレポートをコンサルに作成してもらい、他のアナリティクスビューでも使いまわす
  2. 報告や会議にデータポータルレポートを使う場合、質問に答える際に他のビューで見た場合の結果をすぐに表示できる

これまでの流れからすると、Googleアナリティクスのマイレポートにあるソリューションギャラリーのように、いろんな人がデータポータルレポートのテンプレートを作成して公開するようになるのかもしれないな、と思います。
今後のアップデートに期待ですね!

JMeterでCSRFトークンを取得する方法

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

WEBサイトの負荷テストに便利なツール JMeter で、CSRFトークンを取得する方法をご紹介します。

CSRFトークン

CSRF対策として、入力フォームにhiddenでトークンを埋め込んでいるサイトは多いと思います。
最近ではフレームワーク側でデフォルトでこの機能が付いている場合もありますね。
このような場合、JMeterでPOST系のテストするためには、どうにかしてこのトークンを取得しなければなりません。

正規表現抽出

まず、CSRFトークンが表示されている画面のサンプラーを追加します。
そしてサイドバー上のそのサンプラーを右クリック
 →追加→後処理→正規表現抽出

表示された、正規表現抽出画面で以下のように設定します。

Apply to:● Main sample only
Field to check:● Body
参照名:csrf_token ※後ほど参照する時のキーとなります
正規表現:<input name="token" value="(.*?)" type="hidden" /> ※例です。各サイトに合わせてください
テンプレート:$1$

Parametersに追加

正規表現で取得したトークンをフォームをPOSTするサンプラーのParametersにセットします。

名前:_csrf
値:${csrf_token}

以上です。

寝だめや夜更かしは太りやすい?

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

はじめに

週末の朝は目覚まし時計を設定しないで、お昼頃まで寝たいという人が多いと思いますが、
起床時間や睡眠時間が毎日バラバラだと代謝機能の問題が起こりやすく、太りやすい体質になると言われています。

夜更かしによる体の影響

休日の夜遅くまで起きている人や、毎日の睡眠時間が一定ではない人は、インスリン抵抗性を発症したりBMI値が高くなったりするなど、代謝機能に問題が起きやすいとのことです。

また、規則的な睡眠を取らない生活を長く続けていると、心疾患や糖尿病などの長期的な病気が起こりやすくなるとのこと。

平日と休日で違った睡眠パターンを取っている人は、体内時計が狂った結果、代謝のサイクルが他の体のサイクルとはズレてしまうそうです。

さらに、平日と休日の睡眠時間の差が開けば開くほど、代謝機能の病気を発症しやすいようです。

睡眠時間の差が開くと血液中の脂肪量が増えて、インスリン抵抗性にかかりやすくなったり、
ウエスト周りが太くなったり、血圧が上がったり、善玉コレステロール値が下がったりといった健康被害が起こってしまいます。

まとめ

健康のため適度な運動も重要ですが、睡眠の質に気を掛けるのも健康の為には重要になると思われます。

CLIPSTUDIOvsPhotoshopここはこうなる仕様の違い①

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

イラスト作成ツールのCLIPSTUDIOPAINTとPhotoshopの各ツールの仕様を比較してみました。

 皆さんイラスト制作の際ソフトは何を使っていますか?私はセルシスのCLIP STUDIO PAINT PROとAdobeのPhotoshopCC2017を業務によく使います。片や漫画作成に特化したソフト、片や写真加工に特化したソフトと呼ばれるこの二つ。実は結構似たようなツールやコマンドシステムが揃っています。しかし似てはいても異なるソフト。同じコマンドやツールでも此方のソフトはこの仕様だが其方のソフトはこの仕様である、といった違いが存在します。今回はそんなそれぞれのソフトの仕様の違いについて載せていきます。

比較するのはこの二つ。

  • セルシス CLIP STUDIO PAINT PRO(クリスタ)
  • Adobe PhotoshopCC2017(フォトショップ)

どちらもコマンド変更していないデフォルト状態のものです。
今回はクリスタ→フォトショップという流れで比較していきます。この比較は主に自分がイラスト制作中に使っている部分での気づきなので掘り返せば他にも色々あると思いますがご容赦ください。それではいってみましょう。

レイヤー削除コマンド

 クリスタではレイヤーを選択した状態でBackSpaceキーを押すとレイヤーに描かれた内容が全て消えます。しかしフォトショップでは同じコマンドを使用すると指定したレイヤーごとデータが削除されます。ここで気をつけたいのがクリスタ気分で削除するとレイヤーごと削除されたことに気づかず他のレイヤーに描き込んでしまう場合です。レイヤー数が多くなってくると特に見逃しやすくなるので要注意。逆にフォトショ感覚でクリスタに削除コマンド→新規レイヤー作成をし続けるといつの間にか何も描かれていないレイヤーが大量に…なんてことにもなりかねないので気を付けていきたい所です。

フォルダー作成ボタン

 レイヤー管理欄の上部分にあるフォルダー作成ボタンがありますよね。ワンクリックで簡単に新規フォルダーが作成できるボタンです。クリスタの場合は「そのボタンをクリックして新規フォルダーを作成」してからまとめたいレイヤーを詰め込むのですが、フォトショップの場合はなんと「まとめたいレイヤーを複数選択した状態でフォルダー作成ボタンをクリック」するだけで選択したレイヤーが入っている状態のフォルダーが作成されます。まとめたいときにすぐさま選択してボタンを押すだけでまとめられるので感覚的にまとめやすいです。ちなみにクリスタでも「フォルダーを作成してレイヤーを挿入する」というコマンドは存在する為コマンド設定すればフォトショと同じ感覚でフォルダーにまとめられます。

クリッピングマスク

 個人的にマスク機能よりもお世話になっているのがクリッピングマスク機能。これをかければ下のレイヤーからはみ出ないように絵や効果がかけられます。そんな便利な機能、クリスタではフォルダーにクリッピング機能を付属できるのです。つまりかけたい効果や絵のレイヤーを全てフォルダーにまとめた状態でクリッピングが可能!クリッピング内容がまとめられることでかなりレイヤー欄が見易くなります。クリッピング内容を一つのレイヤーに結合する必要がないので細かな修正もしやすいです。
 一方のフォトショップはフォルダーにクリッピング機能は付けられません。レイヤーにしか機能がつけられないためマスク機能との併用がおすすめです。
enter image description here

ベクター線・シェイプツール

enter image description here
 描いた後でも支点(パス)を選択して線の微調整ができるだけでなく、拡大縮小してもぼやけることのない綺麗な画像が作り出せるベクター線。フォトショップではシェイプツールが近いものだと思います。それぞれ特徴があるので気づいた点を箇条書きにしてみました。

  • クリスタベクター線
    ・ベクターレイヤーを使えば描写内容が全てベクター線になる
    ・好きなペンツールを使いフリーハンドで線を描くことができる
     (勿論パスが備わるため太さや作成した線の位置調整も変更可能)
    ・ベクター線に特化した消しゴム設定が備わっている
    ・面状態での図形作成はできない(境界線のみで作成される)
  • フォトショップシェイプツール
    ・シェイプツールで描くと同時に新しくシェイプレイヤーが作成される
    ・星や五角形などの多角形やハートや音符などの複雑な形の図形データもデフォルトで数多く備わっている
    ・シェイプツールで囲った部分で面の作成や、境界線を線にする設定も可能。面や線を伴わない軌跡のみのパスも作れる
    ・滑らかな曲線を作りやすい。ただしフリーハンドの線は描けない

 どちらかというとクリスタは図形・フリーハンドの線の調整に強く、フォトショップは滑らかな曲線や面のある図形の作成に強いと感じました。特に滑らかな線で描け、面で構成できるフォトショップのシェイプツールはUIのシンプルな形のボタン制作やイラストにもよく活躍します。描く作品によってどちらのソフトも使っていきたいですね。

変形ツール

 縦横の伸縮や拡大縮小、左右反転だけでなく支点からの自由変形までできる変形ツールはデジタルならではの心強いツールです。この便利なツールも勿論どちらのソフトにも備わっています。クリスタの変形ツールで注目すべきところはレイヤー結合することなく複数レイヤーを選択した状態で選択範囲内の変形が行えるところ!選択範囲が適用された状態で移動が行えるので、各レイヤーに移動して個々にずらすことなく変形させたい部分だけをひとまとめに変形できます。モーションパーツの作成に便利ですね。
 一方フォトショップでは複数選択した場合、選択範囲関係なく、選択したレイヤー全体に変形がかかります。しかしフォトショップのすごいところはフォトショップにしかない変形ツール、遠近ワープとパペットワープです。遠近ワープはまるで移動して視点を変えたかのように建物の遠近感を変える3Dのような変形ツールです。パペットツールは好きなところにピンをおき、あとはそこを中心に人形のように動かしたり伸ばしたりできるツールです。さすが写真加工に特化しているだけあって変形部分のまわりの画像も違和感のないように処理してくれること。統合した状態でもスムーズに調整できます。
enter image description here

戻るコマンド

 作業中はデジタルならではのひとつ前の状態に戻すコマンドを良く使います。上欄の編集からでも使用できますが、Ctrl+z,Ctrl+shift+zのコマンドで簡単に戻ることができます。クリスタだとこのコマンドをひたすら押せばどんどん前の状態へ戻っていきますが、コマンド設定をいじっていないフォトショップだとコマンドが多少異なります。Ctrl+zの場合、「一つ前に戻る、戻した内容を元に戻す(一つ後に進む)」となります。戻したりやり直したりいったりきたりが一つのコマンドで行えます。では逆にずっと戻していく場合は?こちらはCtrl+z+altでクリスタと同じようにどんどん一つ前へ戻っていけます。ちなみにあまりにも内容を戻す必要がある場合はヒストリー画面で直接戻したい段階に飛んだほうが早いかと思われます。コマンドはカスタマイズできるのでどちらかの設定に合わせたほうがより混乱せずスムーズに作業が行えるでしょう。

 いかがでしょうか。まだまだ違いがあるので次回も続けて仕様の違いについてお話いたします。それでは。

Googleデータスタジオでアナリティクスのデータ管理が可能に!

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

Googleデータポータルに新機能が追加され、アナリティクスデータを閲覧レポート上で切り替えることが可能になりました。データポータルの閲覧権限だけで複数のアナリティクスデータを使えるので、情報共有のリスクが減る機能といえます。今回はデータ管理機能の使い方についてご紹介いたします。

この記事でまとめられていること

こんにちは。株式会社アピリッツでアナリストをしているssekiです。
最近Googleデータポータルを使う機会が多くなり、作成したレポートを共有することが多くなりました。
データポータルは共有が簡単な反面、編集権限を与えていると知らぬ間に誰かに書き換えられていて困ることもしばしば・・・。
そんな不満を持っている最中、Googleが7月14日に神アップデートしてくれました!
enter image description here

「データ管理・・・?」

これを見つけた時の僕の気持ちです。
とりあえずググったのですが、日本語ページが何ひとつとして見つからなかったのでGoogleヘルプページ(英語版)を参考に使い方を理解しました。
今回は、データソースのGoogleアナリティクスビューをレポート上で変更できるデータ管理の機能について、使い方を交えてまとめてみました。

Googleデータポータルのデータ管理とは

Googleデータポータルの共有権限には2種類あります。

  1. 編集者権限:リンクURLを知っていればレポートを閲覧・編集どちらも可能
  2. 閲覧者権限:リンクURLを知っていればレポートを閲覧可能だが、編集は不可

1つのデータソースだけを定点観測する分には閲覧者権限のみでも問題ないのですが、複数のデータソースを見たり適宜フィルタリングをかけたり編集したい場合には編集者権限が必要でした。

しかしながら、複数人が勝手にレポート内容を変えると管理が煩雑になり、結構面倒くさくなります。
それを防ぐために、これまではデータソースごとに同じテンプレートのレポートを複数作成することで対応していました。(これも管理が面倒ではあるけど)

そんな状況で、データ管理が役立ちます。
データ管理はざっくりいうと「閲覧者権限でもレポートで使われているデータソースを(アナリティクスに限り)変更できる機能」になります。

データ管理の使い方

データ管理の使い方は極めて簡単です。まず、普通にレポートを作成しておきます。
とりあえずGoogle Merchandise Storeのデータを使って、メディア別のセッション数を表にしてみました。
enter image description here
次に、データ管理をクリックした状態で長方形を書きます。
enter image description here
「ビューを選択」が出ましたね。この状態で閲覧画面に戻りましょう。
するとこのように表示されます。
enter image description here
「ビューを選択」をクリックすると自身が持っているアナリティクスの閲覧権限一覧が表示されます。
変更したいビューにカーソルを合わせてクリックすることで、レポート内の全データを変更することができます。
enter image description here
新卒コミュニティサイトのデータを使って表のデータを入れ替えてみるとこんな感じです。
enter image description here
現在表示しているアナリティクスビューの名前が表示され、表のデータが変更されました。
ほぼワンタッチで変更できるので、データポータルに慣れていなくても簡単に使えます。

データ管理を使う際の注意点

簡単に使えて有用なデータ管理ですが、いくつか問題点もあるため記載しておきます。

1つ目に、アナリティクスデータだけしか対応していないことです。
もし、Search ConsoleやAdwordsなどの他のデータソースを切り替えたいと思っている場合、現段階ではデータ管理の機能を使用することはできません。

2つ目に、アナリティクスビューの閲覧権限を持っていなければいけないことです。
データポータルのレポートにデータソースとして使われている場合はそのまま見ることができますが、データ管理として変更する場合には閲覧者自身が該当のアナリティクスビューの閲覧権限を持っている必要があります。

1つのレポート内で複数のデータ管理をする方法

上記では、データ管理によってレポート内の全データを総入れ替えする方法についてご紹介しました。
実際のレポート内で使うには場面が限られますが、1つのレポート内で異なるデータ管理を2つまで切り替える方法を見つけたのでご紹介いたします。

先ほど作ったレポートを利用して説明します。
まず、表とデータ管理をそれぞれコピーします。(わかりやすいように並べました。)
enter image description here
レポート上にある表やグラフなどすべての要素には、レベルというものが存在します。
データ管理で変更しているデータは同じレベルのものを変更しているため、レベルを変更することで異なるデータ管理の効果を受けることができます。

デフォルトでは、「ページレベル」に設定されているので、左側の表とデータ管理を「レポートレベル」に変えてみましょう。
表にカーソルを合わせて右クリックすると図のように表示されるので、「レポートレベルに変更」をクリックすると変更できます。
enter image description here
ちなみに、もう一度同じことをすると「ページレベルに変更」と文言が変わって、「ページレベル」に変更できます。
左側の表と「ビューを選択」をページレベルに変更した後、閲覧画面に戻ります。
左側の「ビューを選択」のみを変更してみます。すると、左側の表だけが変更されました。
enter image description here
右側についてもアナリティクスビューを変更することで、右側の表だけが変更されます。
このように、レベルを変更することでデータ管理を複数設置することも可能です。

まとめ:データ管理はどんなときにおすすめか

データ管理は閲覧者権限でもアナリティクスデータのビューを変更することができる機能でした。
アナリティクスビューごとにデータポータルレポートを作成するとなると作成も管理も面倒ですが、ひとつのレポート上で切り替える分にはワンタッチなのでお手軽です。
今回はチーム内での共有に視点を置いて説明しましたが、その他にも例えば次のようなことに使えるかなと思います。

  1. テンプレートとなるデータポータルレポートをコンサルに作成してもらい、他のアナリティクスビューでも使いまわす
  2. 報告や会議にデータポータルレポートを使う場合、質問に答える際に他のビューで見た場合の結果をすぐに表示できる

これまでの流れからすると、Googleアナリティクスのマイレポートにあるソリューションギャラリーのように、いろんな人がデータポータルレポートのテンプレートを作成して公開するようになるのかもしれないな、と思います。
今後のアップデートに期待ですね!

【Rails】wheneverで出力されるコマンドで環境変数を使用する場合【whenever】

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

wheneverで環境変数を使いたくなった時に方法を模索していたのでメモ。

環境変数を使用したい場合、通常は下記のように記述するかと思います。
※例:バッチを動かした後にあるディレクトリをrsyncで同期をとる
schedule.rb:

every 1.day, at: '0:00 am' do
  command("cd :path && :environment_variable=:environment bin/rake batch:batch_name && rsync -a -e \"ssh -p $PORT\" /path/aaa/ user_name@$IP:/path/aaa/ ")
end

この記述だとcronに出力は下記になります。
出力結果:

0 0 * * * bash -l -c 'cd /home/user_name/app && RAILS_ENV=production bin/rake batch:batch_name && rsync -a -e \"ssh -p $PORT\" /path/aaa/ user_name@$IP:/path/aaa/'

これで問題ないのでは?と思いますがコマンドが「”」で囲まれているため環境変数が展開されません。
環境変数を展開するにはコマンド「””」で囲む必要があります。

コマンドを「””」で囲むためにwheneverにjob_templateの設定が必要になります。job_templateではコマンドの形を設定できます。

set :job_template, "bash -l -c \":job\""

上記を設定すればコマンドの出力が「””」で囲まれます。
schedule.rb:

set :job_template, "bash -l -c \":job\""

every 1.day, at: '0:00 am' do
  command("cd :path && :environment_variable=:environment bin/rake batch:batch_name && rsync -a -e \"ssh -p $PORT\" /path/aaa/ user_name@$IP:/path/aaa/ ")
end

出力結果:

0 0 * * * bash -l -c "cd /home/user_name/app && RAILS_ENV=production bin/rake batch:batch_name && rsync -a -e \"ssh -p $PORT\" /path/aaa/ user_name@$IP:/path/aaa/"

これで環境変数が展開され想定通りのコマンドになるかと思います。

BTCでマーチンゲール!

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

最近は仮想通貨が相場的にも世間的にもたいへん盛り上がってまして、きたる8/1のイベントに向けて世間はざわざわしております。
ぼくも昔は相場を張ってた時期がありまして、その時のなんやかんやで今回はギャンブル必勝法と名高いマーチンゲールがBTCで検証してみたいと思います。
マーチンゲールの説明についてはベッティングシステムとかマーチンゲールでググっていただくとして、今回はマーチンゲールの幾つかのバリエーションを検証していきます。
ちなみに、今回コードは掲載しないです。

検証するマーチンゲールのバリエーション

  • ノーマルマーチン
  • グランマーチン
  • ダランベール
  • バーレー

共通のルール

資産 1000000
取引対象: BTC/JPY
検証期間: 2014-09-17 検証終了日: 2016-08-01
スプレッド及び手数料などの取引コストは0と考える
レバレッジはかけない

戦略

買いポジションを取る。
前日比がプラスなら勝ち
前日比イコールなら引き分け
前日比マイナスなら負けとする
共通して、引き分けの場合は賭け枚数を現在のまま引き継ぐ(増額なし)
賭け金が資産を上回る場合も賭け枚数を現在のまま引き継ぐ(増額なし)

とまあこんな感じで、基本は買いのナンピンマーチン戦略となってます。
レバレッジをどうするかは結構迷って、ハイレバを可にすると破産が見られる楽しい検証になるんですが、不健全なのと証拠金関係が面倒なのでなしにしました。

ノーマルマーチン

ルールは至って簡単で、負けたら(BTC/JPY)が下げたら倍プッシュするだけ。

資産: 1427096.0 利益: 427096.0 利益率: 29.9276292555

グランマーチン

マーチンが負けた場合n * 2のベットなのに対し、負けた場合にn * 2 + 1をベットする。

資産: 1680161.0 利益: 680161.0 利益率: 40.4818942947

リスク取った分だけリターンが上がりました。

ダランベール

ノーマルマーチンが負けた時に倍プッシュするのに大して、1単位だけ増やし、勝った場合に1だけ減らす。1単位のときに勝った場合は、引き続き1単位。

資産: 1413083.0 利益: 413083.0 利益率: 29.2327485364

リスクを取らない分リターンも下がりました。

バーレー

ノーマルマーチンの逆。
勝ったら倍プッシュを繰り返します。
ノーマルマーチンの鏡対象の結果になるんですが、今回はすぐにかつかつまでベット額が増えていったので結果はノーマルマーチンとやや異なります。

資産: 764141.0 利益: -235859.0 利益率: -30.8659004032

考察とか

簡単に検証できるのはこんなところです。
調べればもっと色々出てくるんですが、実装するのが面倒なので簡単な4つで検証してみました。
バーレー以外はだいたい利益出てるんですが、まあ当然なんですよね。
だって上がってる銘柄買ってりゃ賭け方がどうであれ基本儲かりますから。
ちなみにこの期間、上昇率は終値ベースで30.28%となってるので、ただ買って持ってる以上に儲かるのってグランマーチンだけなんですよね。
今回の検証は結構雑な感じで、最大DDとか資産曲線とかシャープレシオみたいなアレコレを一切考慮に入れてません。
個人的にはベッティングシステム単体でどうにかするのはイケてないと思ってるんですが、もっと色々やるといい感じの手法になるかもしれませんね。
最後にお決まりのアレを。

免責事項

当ブログの内容に関し、いかなる保証をするものではありません。 万一、内容についての誤りおよび内容に基づいて被った損害についても一切責任を負いかねます。

DB水平分散を使用した状態でマイグレーションファイルを纏めた過程。

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

drecom/activerecord-turntableを使用した状態でマイグレーションファイルを纏めた過程。

 こんにちは。甘いものを食べたくて食べたくて、けれど竹下通りというシャレオツな場所は怖くて避けていて、震えているHelloWorld??です。

問題

 drecom/activerecord-turntable…DB水平分散を使用した状態では、既存の方法でマイグレーションを纏める事が出来なかった。けれど、色々な理由で纏めたかった。

過程1. gemを入れてみる

 まず、マイグレーションを纏めると言ったらこれだよね、という事でsquasherを入れてみました。
 そうしたら、お決まりのmysql2関連のエラーが出てしまって(対象となったRailsアプリではmysqlを使っています)。

Specified 'mysql2' for database adapter, but the gem is not loaded. Add `gem 'mysql2'` to your Gemfile (and ensure its version is at the minimum required by ActiveRecord). (Gem::LoadError)

 この問題は、大抵の場合mysql2のバージョンに問題があるみたいですが(勿論mysql2は入れてます)、新しく入れたgemの為に現状のgemのバージョンを変えるとかは極力したくないですし。
 という事で却下しました。

 次に、他にマイグレーションファイルを纏めるgemは無いかと調べてみると、自分が調べた限りではありませんでした。以下のようなものは見つかりましたが、マイグレーションを纏めるというものではないですし、マイグレーションが使えなくなるのも困りますし……。

  1. Ridgepole 既存のマイグレーションを使用せずにDBを管理するgem。
  2. Convergence http://labs.timedia.co.jp/2014/10/railsdb.html Ridgepoleを参考にして一から作り上げた、Ridgepoleの改良版。

過程2. 詰まったから聞いてみた

 そんな感じで、これ無理じゃないかなーと思いながら先輩に聞いてみたら、マイグレーション実行時に吐き出されるstructure.sql使えない? と言われて、これはもしかしたら、と光明が見えてきました。
 ただ、問題が新しく出てきて。
 題名の通り、このアプリでは、activerecord-turntableを使用しています。即ち、クラスタとかを指定して、DB水平分散をしてユーザーデータやらそれに紐づくデータやらを管理している訳です。
 要するに、SQLを直接実行するにせよ、複数のDBを指定してSQLを実行しなければいけない。
 これは、activerecord-turntableを調べなきゃいかんな……。という訳で、頑張りました。1~2時間位。
 以下が、DB水平分散をしてマイグレーションをかけている実際のコードです。
/lib/activerecord-turntable-feature-rails4_1/lib/active_record/turntable/migration.rb

  def migrate_with_turntable(direction)
    config = ActiveRecord::Base.configurations
    @@current_shard = nil
    shards = (self.class.target_shards||=[]).flatten.uniq.compact
    if self.class.target_shards.blank?
      return migrate_without_turntable(direction)
    end
    shards_conf = shards.map do |shard|
      config[Rails.env||"development"]["shards"][shard]
    end
    seqs = config[Rails.env||"development"]["seq"]
    shards_conf += seqs.values
    shards_conf << config[Rails.env||"development"]
    shards_conf.each_with_index do |conf, idx|
      @@current_shard = (shards[idx] || seqs.keys[idx - shards.size] || "master")
      ActiveRecord::Base.establish_connection(conf)
      if !ActiveRecord::Base.connection.table_exists?(ActiveRecord::Migrator.schema_migrations_table_name())
        ActiveRecord::Base.connection.initialize_schema_migrations_table
      end
      migrate_without_turntable(direction)
    end
  end

 このメソッドについて簡単に言えば、水平分散するように指定されているマイグレーションに対して、その水平分散するDBそれぞれにマイグレーションを掛ける処理をしています。
 そして、水平分散をするDBを指定するコードが、

ActiveRecord::Base.establish_connection(conf)

 confの中身は、以下のようなdatabase.ymlに書かれている設定ファイルを拾ってきているハッシュです(ローカル環境なら大体こんな感じかな)。

{adapter:    "mysql2",
 encoding:   "utf8",
 reconnect:  false,
 pool:       5,
 username:   "root",
 password:   "I_WANT_TO_EAT_SWEETS!!",
 host:       "127.0.0.1",
 port:       3306,
 database:   ""}

 ここまで分かれば、後は色々頑張っていくだけです。

実装過程

  1. SQLファイル作成

まず、纏めたい部分までのマイグレーションを1から実行します。ここでは2017年1月1日までのマイグレーション、バージョンは20170101000000としておきましょうか。

bundle exec rake db:migrate:reset version=20170101000000

 そうすると、それまでのSQLの実行結果がdbディレクトリ以下に吐き出されます。
 activerecord-turntableを使用していたならば、turntable.ymlで設定した分だけ複数吐き出されるはずですので、水平分散DBで種別に一つずつrenameして取っておきましょう。全部は必要ありません。例としては、
structure_AAA_seq.sql これと
structure_AAA1.sql これと
structure_AAA2.sql
structure_BBB_seq.sql これと
structure_BBB1.sql これと
structure_BBB2.sql
structure.yml    これを
以下にrename。
old_structure_AAA_seq.sql
old_structure_AAA.sql
old_structure_BBB_seq.sql
old_structure_BBB.sql
old_structure.sql
といった感じです。

 そして、ここからこのSQLファイルに対してひと手間必要になってきます。
 これをこのままSQL文として実行しても、SQLは動きません。また、消しておかなければいけないSQL文も存在します。

 まず、正規表現を使って、取っておいた全てのファイルからrubyのコメントアウト文を削除します。これがあるとSQLが走りません。
 Visual Studio Codeなら、簡単に行けます。
1. 正規表現を使ったファイル内検索で引っ掛ける。
 以下で行ける(macだとバックスラッシュはキーボードの設定弄らないと出てこないので要注意)。

/*.*\*/;

2.”全ての出現箇所を変更”で削除。
後、お好みでSQLのコメント文も削除しましょう。VisualStudioCodeの正規表現は以下で。

--.*

 それから、全てのSQLを登録する、structure.sqlからのみ、SQLを削除する手間が必要になります。
 それは、schema_migrations関連に対してです。このSQLを実行するマイグレーションを後々作成するのですが、schema_migrations関連のSQLを残したままだと、このマイグレーションの実行履歴が、schema_migrationsに入らず、マイグレーション実行してないよ、と怒られてしまいます。
 まあ、他の水平分散するDBにもschema_migrationsのテーブルが入るのですが、rails側で参照しているのは、このstructure.sqlで作成されるところのDBだけなのでここだけ削除しておけば大丈夫でしょう。
 それともう一つ、最後の方に羅列されている、INSERT INTO schema_migrations (version) VALUES (……)も削除します。古いバージョンのマイグレーション情報はもう、必要ありません。

2.マイグレーションファイル削除、作成。
 まず、もう要らないマイグレーションファイルを一気に削除します。今回は20170101000000以前のマイグレーションファイルです。
 そして、次にマイグレーションファイルを直接作成します。
 20170101000000_init_database.rbと言った感じに、年月をその時に指定して作成します。
 最後にその中で、detabase.ymlの内容からでもハッシュを作成し、DBを作成し、sqlを直接実行するcreateメソッドを作成してから、もう一仕事面倒な事を片付けてから、完了となります。
 ローカル環境に限るなら、自分は以下になりました。

class InitDatabase < ActiveRecord::Migration
  def change
    environment = {}
    databases = {AAA: [], AAA_seq: [], BBB: [], BBB_seq: [], :master => []}
    if Rails.env.development?
#取り敢えずdatabase.ymlからじゃなくて手打ちで。
      environment = {adapter:   "mysql2",
                     encoding:  "utf8",
                     reconnect: false,
                     pool:      5,
                     username:  "root",
                     password:  "I_WANT_TO_EAT_SWEETS!",
                     host:      "127.0.0.1",
                     port:      3306,
                     database:  ""}
#データベース名をそれぞれ入れていく。こっちも取り敢えず手打ちで。
      databases[:AAA] = ["AAA1_development",
                          "AAA2_development"]
      databases[:AAA_seq] = ["AAA_development_seq"]
      databases[:BBB] = ["BBB1_development",
                          "BBB2_development"]
      databases[:BBB_seq] = ["BBB_development_seq"]
      databases[:master] = ["development"]
    elsif Rails.env.test?
...
    elsif Rails.env.XXX?
...
    end
#ファイルを読みだしてから、SQL単位で分割する。SQLファイルの保存場所は任意で。この場合はdbディレクトリ以下。
    databases[:AAA].each do |database|
      file = File.read(Rails.root.to_s + "/db/old_structure_AAA.sql")
      sqls = file2sqls(file)
      environment[:database] = database
      shard_sql_execute(environment, sqls)
    end
    databases[:AAA_seq].each do |database|
      file = File.read(Rails.root.to_s + "/db/old_structure_AAA.sql")
      sqls = file2sqls(file)
      environment[:database] = database
      shard_sql_execute(environment, sqls)
      ActiveRecord::Base.connection("INSERT INTO *_id_seq(id) values(0);")
      ActiveRecord::Base.connection("INSERT INTO *_id_seq(id) values(0);")
      ...
      ...
      ActiveRecord::Base.connection("INSERT INTO *_id_seq(id) values(0);")
    end
    databases[:BBB].each do |database|
      ...
    end
    databases[:BBB_seq].each do |database|
      ...
    end
    databases[:master].each do |database|
      ...
    end
  end
end

#ファイルをSQL単位で分割するメソッド。コメントアウト文などを消しても、ファイルをそのままActiveRecord::Base.connection.executeに代入したら動かなかった。原因はまだ不明。
def file2sqls(file)
  sqls = file.split(";")
  sqls.delete_if{|sql| sql.blank?}
  sqls.each do |sql|
    sql.gsub!(/\n/,"")
    sql << ";"
  end
  sqls
end
#接続を設定してSQL実行する。
def shard_sql_execute(env, sqls)
  ActiveRecord::Base.establish_connection(env)
  sqls.each do |sql|
    ActiveRecord::Base.connection.execute(sql)
#sqlの中に"create table *_id_seq"の文字列が入っていたら...の時に初期値入れる事をやる?
  end   
end

 面倒な事、というのは上のコードでの、

ActiveRecord::Base.connection("INSERT INTO *_id_seq(id) values(0)")

に関してです。
 activerecord_turntableに依るDB水平分散によるID管理はまた別のseqDBなるものによって管理されています。普通にマイグレーションを実行すれば、そのseqDBのAAAやらBBB、それらに紐付いているデータのIDを管理する*_id_seqテーブルに初期値である0のレコードが入るのですが、こうしてSQL直接実行だとレコードが入りません。なので、手動で入れてあげる必要があります。……元々のマイグレーションファイルの中で”create_sequence_for”で紐付けているデータ分だけ。

 多いと、何かしら簡略化のコードが必要でしょう。
 しかし、それを頑張れば、完了です。
 これで後はまたマイグレーションを問題なく実行出来たら、アプリを動かして、中身などを確認してみましょう。
 それから、多過ぎるマイグレーションを纏める、という意味でこれを自分は行ったのですが、思わぬ良い副作用がありました。
 マイグレーションをして吐き出されるstructure*.sqlには、最終的に実行されるSQLが入っています。即ち、過去のマイグレーションでadd_columnやらrename_columnやら、そんなテーブルに対する変更処理などが全くありません。
 なので、纏めたこの特殊なマイグレーションは、纏めていない大量のマイグレーションファイルをそのまま実行するよりとても速くなります。

まとめ

 acitiverecord-turntableを使用した状態でマイグレーションを纏めたい、でもsquasher使えないときには、
1. 纏めたいところまでマイグレーション実行。
2. 吐き出されたSQLファイルをrenameして保存、コメント文などを削除、schema_migrations関連のSQL文も削除。
3.纏めたいところまでのマイグレーションファイル削除。新たにその地点でマイグレーションを作成し、直接環境指定してからSQLを実行、seqDBにレコードを挿入するコードを書く。
 で、出来る。
(これって邪道……?)

追記: executeとかでSQLを直接投げたものはログファイルに入らない模様。

最近人気な記事