facebook-ruby-ads-sdkの読み方

facebook-ads-sdk

facebook-ads-sdkとはfacebook広告に関するAPIマーケティングAPI)を扱うためのSDKである。マーケティングAPIjsonのやり取りで定義されているが、facebook-ads-sdkを用いればより簡単に利用することができる。ただし、APIそのものと違い、自然言語で書かれた解説が少ない。少なくともRubySDKに関しては少なかった。よって本記事ではfacebook-ads-sdkRuby版)のソースコードからその仕様を理解するための方法について説明する。仕様そのものについてはそこまでちゃんと説明しません。

説明書を読む

上の日本語ページにはSDKの使い方はほとんど書いておらず、詳しい説明はGitHubのreadme.mdにある。アクセストークン云々のようなAPIを使うための初期設定についてはここに書いてあることをそのまま実行すれば問題ない。そもそものアクセストークンの取り方についてはこの辺をリンク先含めて丹念に読み込んでください。そもそもアクセストークンとはいったい何なのか、という場合はマーケティングAPIではなく普通のFacebook APIを使う練習などを先にやることをお勧めします。

GitHubのreadmeに話を戻すと、初期設定の下に書いてあるサンプルコードを利用すればある程度の操作は可能である。広告は上から「広告アカウント」「キャンペーン」「広告セット」「広告」の順に木構造になっているが、既に存在するこれらの一つ一つの要素について、名前をとってきたり削除したりといったことはできるようになる。しかし、実用上でマーケティングAPIを使うのであれば、用意したテキストや画像から自動で広告を生成・操作するといったことが主になる。これらについてはreadmeの記述だけでは対応することはできず、しかしこのSDKに関して用意されている自然言語の文書はこのreadmeのみである。

サンプルプログラムを読む

幸いなことに、GitHubのexamplesフォルダに使用例となるいくらかのスクリプトが置いてある。が、残念ながらソースコードの処理に関するコメントはついていない。引数をハッシュで渡すタイプのライブラリ故なんとなく読めるようになってはいるが、正確な内容を理解するためにはGitHubから直接ではなくいったんローカルにクローンしてから読んだ方が良い。「basic.rb」「create_complete_campeign.rb」「dynamic_ads/create_dynamic_ads_flight.rb」の三つを読めば大まかな流れはつかめる。その後に必要であればその他の使いそうなファイルを読むと良い。

しかし、最も詳しく書かれているサンプルが「create_complete_campeign.rb」「dynamic_ads/create_dynamic_ads_flight.rb」の二つであるが、この二つに書かれている内容だけではFacebookの広告ページGUIから操作するような豊富なデザインの広告をすべて利用するための方法がわからないことはすぐに理解できる。そもそもハッシュの引数にとられている文字列は何が利用可能なのかもサンプルに出てきているもの以外はわからない。よって、結局はSDKを実用レベルで利用するにはライブラリの中身を直接読む必要がある、ということになる。

ライブラリの中身を読む

この手の未知の巨大プログラム(といっても今回はそこまで大きなライブラリというわけでもない)を読んでいく場合は、メインとなる処理のメソッド名をgrepやエディタの全文検索でたどりながら中身に立ち入っていく、という流れが一般的である。原始的なテキストエディタしか利用できない環境ではgrepコマンドでたどっていく他ないが、Visual Studio Code や Atom のような、フォルダ内のファイルを含めて全文検索が可能なテキストエディタが利用可能であれば、より効率的に処理をたどることが可能となる。今回は、アプリケーションではなくライブラリのため「メインとなる処理」がやや掴みにくいが、せっかくサンプルプログラムがあるので、「create_complete_campeign.rb」あたりを上から順に読みつつ、そのメソッド名で全文検索して定義を当たる、という流れがよさそうである。

例えば、以下の処理について

  adset = ad_account.adsets.create({
    name: 'Test Ad Set',
    campaign_id: campaign.id,
    bid_amount: 1000,
    billing_event: 'LINK_CLICKS',
    daily_budget: 15000,
    targeting: {
      age_max: 65,
      age_min: 18,
      geo_locations: {
        countries: [
          "HK"
        ]
      },
      publisher_platforms: [
        "facebook",
      ],
      facebook_positions: [
        "feed",
      ],
      instagram_positions: [
        "stream",
      ],
      device_platforms: [
        "mobile",
        "desktop",
      ],
    }
  })

この場合、まずはadsetあたりで全文検索をすることになる。と、いろいろ出てくるが、ad_set.rbなるファイルにAdSetクラスがあることがわかる。createはrubyの命名慣行から推測するに、コンストラクタ的ななにかである可能性が高いので、AdSetクラスの中身を覗くと、様々な列挙型定義の後に、fieldが大量に並んでいるのがわかる。サンプルプログラムのコードと見比べると、name, campaign_id, billing_event, targeting など、呼び出し時のハッシュのキーとして指定されているフィールドが、このフィールド一覧にすべて存在することがわかる。ただし、targetingフィールドのみ呼び出しで入れ子になっているのでこれを確認すると、フィールドの型として'Targeting'とあるのがわかる。よって再びTargetingで全文検索を行うと、やはり「targeting.rb」なるファイルがが見つかり、そこにクラスの定義と大量のfieldが並んでいる。そしてその中には age_max, geo_locations, publisher_platforms といったサンプルプログラムのフィールドが同じように見つかる。

以上から考えるに、クラスとそのフィールドをたどっていくことで、指定したい要素についてはすべて設定可能であろうことが推測される。あとはこのプログラムの構造に従って、createの引数として初期設定をハッシュで与えたり、getでとってきたもののうち対象となるフィールドの値を書き換えたりすれば、望み通りに広告の情報を操作することが可能であるということになる。

まとめ

関連データモデル

関係データモデル

本稿は「SELECTと集合とActiveRecord」の前段階、SQLで操作されるデータベース管理システムを規定している「関係データモデル」の説明である。

関係データモデルとは?

関係データモデルとは「ドメインをもつ値のタプルの集合である関係としてデータをまとめモデル」のこと。以下、各種用語について説明する。

ドメイン

変数の値域。
関係データモデルが計算機上のシステムであれば「文字列」「時刻」などもドメインとなりうる。

タプル

値の並んだもの。
並んだ値の意味付けは関係スキーマによって別途なされる。

関係

タプルの集合のこと。テーブルともいう。

関係スキーマ

関係名に対する属性名の並びのこと。
関係を表で表した時の一番上の行に対応する。

キー

主キーとも呼ぶ。その値を見るだけで何者かがわかるような属性名集合。当然NULLではない。

具体例

下記の関係(テーブル)について具体的に考える。

名前 勘定科目 耐用年数 取得価格 減価償却累計額 簿価
バイク 車両運搬具 3 300000 100000 200000
事務所 建物 50 10000000 8000000 2000000
株式会社awsedrftgyhujikolp のれん 20 800000000 200000000 600000000

この関係の関係スキーマは(名前,勘定科目,耐用年数,取得原価,減価償却累計額,簿価)であり、(バイク,車両運搬具,3,300000,100000,200000)がタプルの一例となる。
なお、関係スキーマやタプルは横ベクトルであるが、縦ベクトルの(勘定科目,車両運搬具,建物,のれん)などはそのままカラムと呼ばれ、関係スキーマに対応するこの例では「勘定科目」がカラム名と呼ばれる

テーブルの操作

テーブル、すなわち関係の操作は関係演算によって行う。関係演算とは集合演算である。
関係演算には以下の五種類が存在する

  1. 射影 projection
    • 一部のカラム(テーブルを行列と見た時の縦ベクトル)だけを取り出す
  2. 選択 selection
    • 一部のタプル(テーブルを行列と見た時の横ベクトル)だけを取り出す
  3. 和 union
    • 二つのテーブル、すなわち関係を合わせる。
    • テーブル=関係はタプルの集合であるため、二つのテーブルの要素であるタプルすべてを要素に持つ新たな集合を定義する、と言い換えられる
    • 同一の関係スキーマを持つテーブル同士でなければ和の演算は行えない
  4. 直積
    • 二つのテーブルの要素に対しすべての組み合わせの新しいテーブルを作る
      • タプル数nの関係とタプル数mの関係の直積によってタプル数n×mの関係が作られる
  5. 結合
    • 直積を行った後に選択を行う
    • 直感的には、同じキーを持つテーブル同士を一つのテーブルにまとめる。足りないところはNULLになる。

SQLDML(Data Management Language) 

SQLは、関係データモデルの関係演算を集合を意識せずに行えるように設計したプログラミング言語である。関係演算はSQLDMLに対応する。
関係演算との対応は下記の通り

  • SELECT [カラム名]
    • 出力するカラムを規定
    • 射影
  • FROM [テーブル名]
    • 入力するテーブルを規定
    • 直積
  • WHERE
    • 出力に含まれるタプルの条件
    • 選択
      和および結合は直積と選択によって定義可能。

参考文献

where系ActiveRecord備忘録

where系ActiveRecord備忘録

 where系のActiveRecordメソッドとその引数。これさえあればとりあえず何とかなる。そもそもwhereさえあらばなんとでもなるともいう。
 ActiveRecordに対応するSQLで言えば

データベースの操作とは,「取得(選択)」,「挿入」,「更新」,「削除」の4つが基本であり,これらを表すSQLの命令は,それぞれSELECT,INSERT,UPDATE,DELETEとなります。
忙しいあなたのためのSQL入門 第2回(1)

のうち取得(選択)のところにあたる。ただしfind_by_sqlとかのSQL直書き系のメソッドは対象外。

where

 条件指定複数検索用。
 ハッシュか文字列で受け取った引数を条件として検索をする。結果は集合として配列で来る。

# ハッシュ系
records = RecordObject.where(id: 10)
records = RecordObject.where({id: 10, name: "国民年金基金"})
# ※{}で囲まれていようとなかろうとハッシュはハッシュ。
records = RecordObject.where(myhome: 1..3)

# 文字列系
records = RecordObject.where("age > ?", 100)
# ※正確には要素数2の配列を与えているのだが、まあ直感的にはprintfみたいなものなので文字列ということで。下も同様。
records = RecordObject.where("income > :serious_income_bottom AND income < :serious_income_top", {serious_incom_bottom: 100, serious_income_top: 100000000})

結果は配列で来る(上例ではrecordsが配列になる)ので単体のレコードをあらわすオブジェクトにアクセスしたい場合は添え字で指定するかeachなどをやる必要がある。

find

 id指定単体検索用。
 整数で受け取った引数を条件として検索をする。結果は単体オブジェクトとしてくる。条件に二つ以上適合する場合は最初に見つけたやつが来る。

record = RecordObject.find(59)

whereで書くと

record = RecordObject.where(id: 59)[0]
record = RecordObject.where("id = ?", 59)[0]

という感じ。

find_by

 id以外の要素指定単体検索用。
 何を検索するかをハッシュで指定する。idで検索したい場合は入力文字数の無駄なのでfindを使った方が良い。

record = RecordObject.find_by(name: "国民健康保険")

whereでは

record = RecordObject.where(name: "国民健康保険")[0]

となる。

all

 配列で全部。

records = RecordObject.all
records = RecordObject.where(nil)

first

 単体で最初(idが最小)のやつ。

record = RecordObject.first
record = RecordObject.where(nil).sorted_by{ |e| e.id }[0]

last

 単体で最後(idが最大)のやつ。

record = RecordObject.first
record = RecordObject.where(nil).sorted_by{ |e| e.id }[-1]

take

 単体で任意のやつ。具体的には、記録されているものの一番上のやつ。

record = RecordObject.take
record = RecordObject.where(nil)[0]

not

 whereの後ろにつけて、条件を論理反転。

records = RecordObject.where.not("id < 74")
records = RecordObject.where("id >= 74")

参考文献

React Nativeでボタンを押している間動作する処理

はじめに

押している間なにかしらのアクションを発火させたい時があると思う

それは、ボタンを2秒押下で下書き保存や4秒押下で記事公開にする等をインタラクションを交えつつ処理をするようなケースである

私のケースだと、チャットシステム構築の際にいいねボタンの横にいいね数を表示しているのだが、実際にいいね数のテキストを押している間モーダルでいいねしたユーザを表示することはできないか考えたことがある

このようにユーザからのフィードバックを用いて処理するReact Nativeのコンポーネントは他のケースだと押下すると透過するTouchableOpacityや押下した際にハイライトを変えるTouchableHighlight、押下時にボタンがバウンスするTouchableBounceがある
今回は上記以外のケースである表題に関してオリジナルのフィードバックを返すボタンを構築する

セットアップ

import React, { Component } from 'react'
import {
  View,
  Text,
  StyleSheet,
  TouchableWithoutFeedback,
  TouchableHighlight
  } from 'react-native'

コンポーネントとスタイル設定

class OriginalBtn extends Component{
  constructor(props) {
    super(props)
    this.state = {
      modalVisible: false,
      userLists: ['miyabi', 'micky', 'hogehoge'],
      reactionNum: 3
    }
  }
  render() {
		return (
    <View style={styles.container}>
      <Modal
        animationType="fade"
        transparent={true}
        visible={this.state.modalVisible}
        style={styles.modal}
      >
        <View style={{
          marginTop: 40,
          flex: 1,
          flexDirection: 'column',
          alignItems: 'center'
          }}>
          <View style={{
            height: 100,
            width: 300,
            padding: 10,
            backgroundColor: 'rgba(0, 0, 0, 0.5)',
            }}>
            <Text style={{color: 'white'}}>{this.state.userLists.join('\n')}</Text>
          </View>
        </View>
      </Modal>
      <View style={[styles.contentscontainer]}>
        <View
        style={[styles.reactionContainer]}
        >
          <TouchableWithoutFeedback 
            onPressIn={this.PressIn} 
            onPressOut={this.PressOut}
                >
              <View>
              <Text
                style={styles.reactionNumText}
              >
              {this.state.reactionNum}
              </Text>
              </View>
          </TouchableWithoutFeedback>
        </View>
      </View>
    </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 12,
    flexDirection: 'row',
    alignItems: 'center',
    backgroundColor: 'transparent',
    borderWidth: 0.5,
    borderColor: 'rgba(255, 255, 255, 0.1)'
  },
  contentscontainer: {
    flex: 0.1
  },
  text: {
    color: 'white',
    marginLeft: 12,
    marginRight: 10,
    paddingRight: 20,
    fontSize: 15,
    width: 250,
  },
  reactionContainer: {
    flexDirection: 'row',// widthで吹き出しサイズやで
    marginTop: 5
  },
  reactionNumContainer: {
    width: 250,
  },
  reactionNumText: {
    color: 'white',
    fontSize: 12,
    fontWeight: '100',
    paddingTop: 6.9,
    paddingLeft: 5,
  },
  modal: {
    height: 100
  }
})

アクション作成

PressIn = () => {
    console.log('pushing')
    this.setState({modalVisible: true})
  }
PressOut = () => {
    console.log('push out!')
    this.setState({modalVisible: false})
  }

最後に

以上のサンプルコードを参考にユーザのフィードバックをもとに多様なインタラクションを表現してみて下さい

最終コード

import React, { Component } from 'react'
import {
  View,
  Text,
  StyleSheet,
  TouchableWithoutFeedback,
  TouchableHighlight
  } from 'react-native'

class OriginalBtn extends Component{
  constructor(props) {
    super(props)
    this.state = {
      modalVisible: false,
      userLists: ['miyabi', 'micky', 'hogehoge'],
      reactionNum: 3
    }
  }
  PressIn = () => {
    console.log('pushing')
    this.setState({modalVisible: true})
  }
  PressOut = () => {
    console.log('push out!')
    this.setState({modalVisible: false})
  }
  render() {
    return (
    <View style={styles.container}>
      <Modal
        animationType="fade"
        transparent={true}
        visible={this.state.modalVisible}
        style={styles.modal}
      >
        <View style={{
          marginTop: 40,
          flex: 1,
          flexDirection: 'column',
          alignItems: 'center'
          }}>
          <View style={{
            height: 100,
            width: 300,
            padding: 10,
            backgroundColor: 'rgba(0, 0, 0, 0.5)',
            }}>
            <Text style={{color: 'white'}}>{this.state.userLists.join('\n')}</Text>
          </View>
        </View>
      </Modal>
      <View style={[styles.contentscontainer]}>
        <View
        style={[styles.reactionContainer]}
        >
          <TouchableWithoutFeedback 
            onPressIn={this.PressIn} 
            onPressOut={this.PressOut}
          >
              <View>
              <Text
                style={styles.reactionNumText}
              >
              {this.state.reactionNum}
              </Text>
              </View>
          </TouchableWithoutFeedback>
        </View>
      </View>
    </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 12,
    flexDirection: 'row',
    alignItems: 'center',
    backgroundColor: 'transparent',
    borderWidth: 0.5,
    borderColor: 'rgba(255, 255, 255, 0.1)'
  },
  contentscontainer: {
    flex: 0.1
  },
  text: {
    color: 'white',
    marginLeft: 12,
    marginRight: 10,
    paddingRight: 20,
    fontSize: 15,
    width: 250,
  },
  reactionContainer: {
    flexDirection: 'row',
    marginTop: 5
  },
  reactionNumContainer: {
    width: 250,
  },
  reactionNumText: {
    color: 'white',
    fontSize: 12,
    fontWeight: '100',
    paddingTop: 6.9,
    paddingLeft: 5,
  },
  modal: {
    height: 100
  }
})

SELECTと集合とActiveRecord

SELECTと集合とActiveRecord

SQLとは集合演算である」しか知らなかった状態からもう少し計算機上の処理というところにまで踏み込んで学習をしたのでその橋渡し的な部分についてまとめます。同様の知識状態の方は末尾の参考文献に上から順に触れると良いでしょう。「穀物の英語」は別にいいです。
本記事は学習のまとめとしての位置づけが強く、内容の正確性は保証できません。誤り等ございましたらコメントにてご指摘いただけると幸いです。

select文

SQLにおける基本であるselect文は全体集合における集合Aと集合Bの直積として表される。

  • SELECT [集合A] FROM [全体集合] WHERE [集合B]
  • SELECT [カラム名] FROM [テーブル名] WHERE [条件]
-- 21世紀以降の三大穀物の生産高を取得
SELECT rice, wheat, maize FROM Grain WHERE year > 2000 ;

集合Aは列(カラム/column)に対する操作、集合Bは行(ロー/row)に対する操作であり、文字通りそれぞれ直交している。集合演算としては任意のテーブルΩという全体集合から集合Aと集合Bの両方に属するものを取り出してくることを意味する。

ここではテーブルを全体集合としてとらえた。直感的にはDBMSで管理されているデータすべてが全体集合とするほうが自然だが、SELECT文での操作対象としての全体集合は指定されたテーブルである。FROM節でDBMSから部分集合を切り出してきて、それをSELECT文における全体集合として再定義していると考えると良いかもしれない。今までx∊ℝで考えてきたが、この命題ではx∊ℤについて考える、というのと構造的には同じ。ところでFROM節なんていう用語はあるのでしょうか。


DBMS

データ・ファイルとデータ管理プログラムのセットのことを「データベース管理システム(DBMS=Data Base Management System)」と呼びます。そうです! 現在では,DBMSのことをデータベースと呼ぶのです。マイクロソフト社のSQL Serverや,オラクル社のOracleなどは,市販DBMSの代表です。身近なところでは,Microsoft Officeファミリの一製品であるAccessDBMSです。
忙しいあなたのためのSQL入門 第1回(1)

とのことです。たぶんMySQLSQLiteDBMSでしょう。
DBMSで管理されているデータ」というのは雑な言い方をすれば「すべてのテーブル」ということです。


select文でとってきたデータはビューという仮の集合に送られる。Acessではビューに対してそのまま次のSQL文(クエリ)を発行することができる。MySQLSQLiteでは何もしないとビューは標準出力となり文字通り見ることしかできずその場でメモリから消滅するので明示的にビューを作成する必要がある。

ActiveRecord

SQLの記法は英文としては自然だが集合Aや集合Bよりも大きな全体集合がそれらにはさまれる形になっている。

それに対し、ActiveRecord、すなわちRuby on Railsでの記法はテーブル名をクラス名と対応させることによって、その集合に対する集合演算であるということがより視覚的にとらえやすくなっている。SELECT文を英文として見て日本語訳した場合もこの順番が自然になるため日本語話者的にもうれしい。

  • [クラス名].where([条件])
# 21世紀以降の生産高を取得
g21 = Grain.where("year > 2000")

カラム名を意味する集合Aの指定が抜け落ちており、対象とするテーブル=集合とその中における条件という構成になってる。Rubyのコードなので集合演算の結果はビューではなくクラスの実体(オブジェクト)として渡される。集合Aに対応するカラム名については受け取った実体のメンバ変数としてアクセスできる。ちなみにgrainは不可算名詞です。

補足

SQLは大文字と小文字の区別はないとのこと。HTMLと同じですね。今回はテーブル名やカラム名と区別がつきやすいように大文字にしています。

参考文献

Sequelizeでsqlのexistsを再現


Sequelizeとは 

sqlite3、Mysql、Postgresへ簡単にアクセスするためのライブラリである
実際に使う場合はsequelizeを使ってみたを参照

実現方法

Sequelizeでexistsを記述する場合、queryに直接記述するかexistsと同等の処理を記述する二つのやり方がある

今回はqueryに直接記述するのではなくexistsと同等の処理を記述する取っつきやすいやり方を紹介する

以下のユーザモデルがあったとしてレコードが存在するかどうか表現できればいい

const User = sequelize.define('user', {
  firstName: {
    type: Sequelize.STRING
  },
  lastName: {
    type: Sequelize.STRING
  }
})

existsはsequelizeに用意されていないのでfindOne若しくはcountを用いる

findOneの場合

Follow.findOne({
  where: { id: id }
    }).then(data => {
      if (!!data) {
        return true
      } else {
        return false
      }
    })

countの場合

User.count({ 
  where: { id: id } 
  }).then(count => {
    if (count != 0) {
      return true
    }
    return false
  });

以上です
sequelizeでexistsを記述する方法が見つからなかったので自分で書いてみました
誰かの役に立てれば幸いです
もっといい書き方が教えてもらえると嬉しいです

参考

sequelizeを使ってみた