LoginSignup
1
3

More than 3 years have passed since last update.

RailsからWordPressにAPI経由で投稿する

Last updated at Posted at 2019-09-01

まとまっている最近の記事がないのでメモ。

やること

  • Railsから、WordPressにREST API経由で投稿する
  • APIの認証には、Application Passwordsプラグインを利用する(インストール・パスワード発行済とします)
  • Application Passwordsで発行したユーザ名、パスワードは、Railsのcredentials.ymlで管理する

環境

  • Ruby 2.6.0
  • Rails 5.2.2
  • WordPress 5.2.1
  • Application Passwords 0.1.0

記事内で利用する設定値

項目 設定値
WordPressのサイトURL https://example.com
WordPress ユーザ名 wp-user
wp-user用のAPIパスワード aaaa bbbb cccc dddd eeee ffff
API投稿時の公開状態 draft(下書き)

credentialsの設定

$ EDITOR="vi" bin/rails credentials:edit
credentials.yml.enc
wp_api_username = 'wp-user'
wp_api_password = 'aaaa bbbb cccc dddd eeee ffff'

保存しておく。

投稿クラス作成

今回は、ServiceクラスとしてWordPressへの投稿機能を作成します。
※Serviceクラス自体邪道とも言われているので、場所はそれぞれの環境下で最適な場所を選んでください。
※あるモデルのデータを投稿するのであれば、そのモデル内でもいいと思います。

/services/wp_api_post_service.rb
# frozen_string_literal: true

require 'net/http'
require 'open-uri'

Class WpApiPostService
  API_URL = 'https://example.com/wp-json/wp/v2/posts'

  def initialize(title, body, categories, tags)
    @title = title
    @body = body
    @categories = categories
    @tags = tags
  end

  def api_post
    uri = URI.parse(API_URL)

    http = Net::HTTP.new(uri.host, uri.port)
    http.use_ssl = true
    http.verify_mode = OpenSSL::SSL::VERIFY_NONE

    req = Net::HTTP::Post.new(uri.path)
    req.content_type = "application/json"
    req.set_form_data(article_setting)
    req.basic_auth(Rails.application.credentials.wp_api_username, Rails.application.credentials.wp_api_password)

    response = http.request(req)

    if response.code == '201'
      Rails.logger.info('Successfully posted WP API')
    else
      Rails.logger.warn(['---Failed to WP API Post---', response.code, response.message, response.body].join("\n"))
    end
  end

  private

  def article_setting
    {
      title: @title,
      content: @body,
      status: 'draft',
      categories: @categories,
      tags: @tags
    }
  end
end

APIのURLは、WordPressのURLにwp-json/wp/v2/postsをくっつけた値です。
記事のタイトル、本文、カテゴリ、タグを引数として渡せば、API投稿がされます。

投稿例
WpApiPostService.new('テストタイトル', '<h2>テスト本文</h2>', '1, 222, 333', '2, 20').api_post

正常に投稿がされれば、response.codeで201が返ってきます。

カテゴリとタグ

カテゴリとタグは、IDを指定します。また、複数選択する場合、配列ではなく、カンマ区切りのIDの文字列を渡します。投稿例の第3引数と第4引数が例となっています。
(Pythonから投稿する例では配列だったんですけど、Rubyでは配列の最初の要素のみ適用されるだけでちゃんと動きませんでした。)

作ってるときに遭遇したエラー

401 Unauthorized

ベーシック認証時のIDとPASSの構成に間違えがありませんか?
注意点は、このAPIにおけるユーザ名がWordPressのユーザ名のことを指すという点です。
1とか2とかのWordPressのUserIDでも、Application Passwords作成時の名前のことでもないです。

400 Bad Request

api_postメソッド内、uri/http/req の属性値の設定が間違っていたため、正常に動作しなかった模様。開発上は、squidのプロキシ経由で接続しているので、squidのzero size replyが表示される状態でした。

502 Bad Gateway

cloudfrontなどを使って、管理側にSSL接続するときに、 http.use_ssl = true が抜けていると、オリジンサーバに接続できずに502が返ってくるようです。

参考サイト

1
3
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
1
3