This week, I wanted to programatically create posts on my Wordpress site, Maxims. Unfortunately, all of the example code I found online for controlling Wordpress was using PHP, and I hate PHP. I wanted to control Wordpress with Ruby using XML-RPC.

It turns out that connecting to Wordpress using Ruby is pretty simple. Every Wordpress instal comes with an XML-RPC API. You can connect to your Wordpress' XML-RPC endpoint using Ruby's standard library XML-RPC client. Once connected, you can call any XML-RPC method in Wordpress.

To learn how to use Ruby with Wordpress XML-RPC, read and run the following code. You'll need to substitute your site's real URL, username, and password. I demonstrate a few of the common Wordpress methods, like wp.getPosts and wp.newPost. However, you can use any Wordpress XML-RPC method. Just look up the documentation for the method you want to use. Then pass in the parameters, in the order they appear on the Wordpress website, to the call() function like this: call("method_name", "parameters", "go", "here"). My code sample should demonstrate this praxis sufficiently.

N.B. You'll notice that many of the call() method calls in my code have 0 as the second argument. This is an unused parameter called blog_id, required in most Wordpress XML-RPC method calls. It does nothing; but, you must pass something in order for Wordpress to work, so I pass 0. The 0 carries no meaning.

require 'xmlrpc/client'

server = XMLRPC::Client.new("www.example.com", "/xmlrpc.php", 80) # Do not put "http://" here; the xmlrpc library appends "http://" to the URL automatically
server.http_header_extra = {'accept-encoding' => 'identity'} # Without this, you'll get an "..xmlrpc/client.rb:506:in `do_rpc': Wrong size. Was 181, should be 132 (RuntimeError)" error
  
begin
  # Call Wordpress' demo.sayHello, a sort of "Hello, World" method that to ensrue your XMLRPC connection is working
  # If it works, it should respond with "Hello!"
  response = server.call("demo.sayHello")
  puts "Called demo.sayHello and Wordpress responded with: #{response}"

  # Call Wordpress' demo.addTwoNumbers, another XMLRPC test to ensure you can pass parameters to a method
  # If it works, it should respond with 9 (the sum of 4 and 5)
  response = server.call("demo.addTwoNumbers", 4, 5)
  puts "Called demo.addTwoNumbers and Wordpress responded with: #{response}"

  # Call Incutio XML-RPC's system.listMethods, an XMLRPC method to return the available XMLRPC methods in Wordpress
  # (Incutio XML-RPC is a PHP library that Wordpress uses to build its XML-RPC API)
  # Documented here: http://codex.wordpress.org/XML-RPC/system.listMethods
  response = server.call("system.listMethods", 0, "username", "password")
  puts "Called system.listMethods and Wordpress responded with: #{response}"

  # Call Wordpress' wp.getAuthors, an XMLRPC method to return the authors on your blog
  # If it works, it should return an array with the user_id, user_login, and display_name of each author on your blog
  # Documented here: http://codex.wordpress.org/XML-RPC_wp#wp.getAuthors
  response = server.call("wp.getAuthors", 0, "username", "password")
  puts "Called wp.getAuthors and Wordpress responded with: #{response}"

  # Call Wordpress' wp.getPosts, an XMLRPC method to get a bunch of posts
  # If it works, it should return 10 published posts from indices 100-110
  # For the sake of demonstration, I'm only printing out the post_id and post_title
  # Documented here: http://codex.wordpress.org/XML-RPC_WordPress_API/Posts#wp.getPosts
  response = server.call("wp.getPosts", 0, "username", "password", {"post_type" => "post", "post_status" => "published", "number" => "10", "offset" => "100"})
  germane_posts_info = response.map do |post|
    {post_id: post['post_id'], post_title: post['post_title']}
  end
  puts "Called wp.getPosts and Wordpress responded with #{response.size} posts: #{germane_posts_info}"

  # Call Wordpress' wp.newPost, an XMLRPC method to create a new post
  # If it works, it should respond with the ID of the draft post that was just created
  # Documented here: http://codex.wordpress.org/XML-RPC_WordPress_API/Posts#wp.newPost
  post_title = "I wrote this post programatically"
  post_body = "How cool is that?!?"
  response = server.call("wp.newPost", 0, "username", "password", {"post_type" => "post", "post_status" => "draft", "post_title" => post_title, "post_author" => 1, "post_content" => post_body })
  puts "Called wp.newPost and Wordpress responded with: #{response}"

rescue XMLRPC::FaultException => e
  puts "Error: #{e.faultCode}:#{e.faultString}"
end