3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

[Ruby] ad_manager_apiでIN句を利用する

Last updated at Posted at 2025-12-07

以前の記事では様々な条件を利用して、ad_manager_api gemを利用してオーダーを取得するようにしました。
今回は前回触れたwhereの応用として、IN句を使う方法を考えます。
まずはサンプルとして、INを使わないwhere文を使ったorderの取得プログラムです。

# frozen_string_literal: true

require 'dotenv'
require 'ad_manager_api'

Dotenv.load

ad_manager = AdManagerApi::Api.new(
  {
    authentication: {
      method: 'OAUTH2_SERVICE_ACCOUNT',
      application_name: 'Ruby Ad Manager Sample',
      oauth2_issuer: ENV['GOOGLE_AD_MANAGER_CLIENT_EMAIL'],
      network_code: ENV['GOOGLE_AD_MANAGER_NETWORK_CODE'],
      oauth2_key: OpenSSL::PKey::RSA.new(
        ENV['GOOGLE_AD_MANAGER_PRIVATE_KEY'].gsub('\\n', "\n")
      )
    }
  }
)

order_service = ad_manager.service(:OrderService, :v202508)
statement = ad_manager.new_statement_builder do |sb|
  sb.where = "name = :name_1"
  sb.with_bind_variable("name_1", "テスト")
end.to_statement
response = order_service.get_orders_by_statement(statement)
p response[:results]

今回は上記のプログラムを拡張していきます。
以下のプログラムは動きませんがイメージ的にはこういう感じ。

names = ['テスト1','テスト2']
statement = ad_manager.new_statement_builder do |sb|
  sb.where = "name IN (:names)"
  sb.with_bind_variable("names", names)
end.to_statement

with_bind_variableを使わない場合

まずはwith_bind_variableを使わない方法を考えます。
一個は全てwhereに全部ベタ書きする方法。

names = ['テスト1','テスト2']
statement = ad_manager.new_statement_builder do |sb|
  sb.where = "name IN ('#{names.join("', '")}')"
end.to_statement

p statement
# {query: "WHERE name IN ('テスト1', 'テスト2') LIMIT 500 OFFSET 0", values: []}

INの中身を配列から生成し、whereの中に直接入れています。
以下のような方法でも同様な結果にもなります。

names = ['テスト1','テスト2']
statement = ad_manager.new_statement_builder do |sb|
  sb.where = "name IN ('%s')" % names.join("', '")
end.to_statement

p statement
# {query: "WHERE name IN ('テスト1', 'テスト2') LIMIT 500 OFFSET 0", values: []}

ただ、SQLインジェクションを考えるなら用意されているwith_bind_variableを使いたいです。

with_bind_variableを使う方法

with_bind_variableを使うためには配列に使うのではなく、配列の中身の要素それぞれにwith_bind_variableを使うようにします。

in_str = names.each_with_index.map { |_, index| ":name_#{index}" }.join(', ')

statement = gam_client.new_statement_builder do |sb|
  sb.where = "name IN (#{in_str})"
  names.each_with_index do |name, index|
    sb.with_bind_variable("name_#{index}", name)
  end
end.to_statement

p statement
# {query: "WHERE name IN (:name_0, :name_1) LIMIT 500 OFFSET 0", values: [{key: "name_0", value: {xsi_type: "TextValue", value: "テスト1"}}, {key: "name_1", value: {xsi_type: "TextValue", value: "テスト2"}}]}

配列を分解して、IN句に渡すためのパラメータを動的に生成します。
これによって、IN句を使いつつ各変数をwith_bind_variableを使うことでSQLインジェクションを予防できます。

まとめ

ad_manager_api gemで安全にIN句を使う方法をこの記事では考えました。
ad_manager_api gemはあまり知見が転がっていないので参考になれば幸いです。

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?