Skip to content

Post to WordPress with Ruby – update

A while back I wrote a post on using ruby to post content to a WordPress blog. It has been getting a steady stream of traffic since it was posted, so it’s obvious that people are into that kinda thing.

While the solution I offer on that post is still valid, the good people who develop the NY Museum of Modern Art site have released a JSON API plugin for WordPress. You can find it here, and what it does is that it creates a nifty RESTful interface for any WordPress powered site, that can be used to programmatically interface with it in a straightforward manner.

SO, time for some fun: let’s see how we create a new post on a WordPress site using the JSON API plugin and Ruby:

  1. Install on your WordPress blog.
  2. Go to Settings > JSON API and activate the Posts controller, giving you access to the create_post method. This is deactivated by default.
  3. Write your article class. Here is a sample one to help you get started:
require 'rubygems'
require 'open-uri'
require 'json'
require 'net/http'
 
# Please note that the vanilla wp-json-api plugin does not support user authentication for create_post.
# Check out my fork for authentication support: https://github.com/Achillefs/wp-json-api
class Article
  API_URI = 'http://mywpblog.com/api/'
  API_USER = 'my_wp_username'
  API_PASS = 'my_wp_pass'
  
  attr_accessor :title, :content, :categories, :tags, :type
  
  def initialize(opts = {})
    # set all values if valid
    opts.each do |key,val|
      begin
        self.send(:"#{key}=",val)
      rescue NoMethodError => e
        raise ArgumentError("#{key} is not a valid article attribute")
      end
    end
    self.type = 'post' if self.type == nil
  end
  
  def publish!
    # Need to get a nonce token from WP in order to create a post
    nonce_response = JSON.parse(open(API_URI + "get_nonce/?controller=posts&method=create_post").read)
    if nonce_response['status'] == 'ok'
      nonce = nonce_response['nonce']
      url = URI.parse(API_URI + "posts/create_post")
      args = { 
        'nonce' => nonce, 'author' => API_USER, 'user_password' => API_PASS, 
        'status' => 'publish', 'title' => self.title, 'content' => self.content, 
        'categories' => self.categories.join(','), 'tags' => self.tags.join(','), 'type' => type
      }
      resp, data = Net::HTTP.post_form(url, args)
      response = JSON.parse(data)
      if response['status'] == 'ok'
        puts response.inspect
      else
        raise response['error'].to_s
      end
    else
      raise nonce_response['error'].to_s
    end
    
  end
end
 
a = Article.new(
  :title => 'test post', 
  :content => 'hello world', 
  :categories => %W[cat1 cat2],
  :tags => %W[tag1 tag2]
)
a.publish!

You can view the complete WordPress JSON API documentation here.
Important caveat: JSON API does NOT currently support api authentication, meaning that you need to be logged into your blog to be able to post to it, which kinda makes this whole thing not very useful. Fear not though, you can use my fork, which adds authentication support for the posts controller.

Categories: Code.

Tags: , , ,

Comment Feed

14 Responses

  1. This is just plain beauty. You just saved me. Thank you, a million.
    I’m just starting out at Ruby, and it looks very promising.
    And true – I got to your old post from writing “mechanize ruby wordpress” (no quotes) in google, so I’m guessing the traffic must be really good on that decided to give this a read as well, and I’m stunned. Thank you for sharing these awesome licks :)

  2. This rocks! Have you seen anything through the API or plugins that would allow the creation of users?

  3. Hey, the JSON API plugin does not currently feature a Users controller, although it would be straightforward to implement. Have a look around github and see if anybody has already done it in a fork, and let me know if you find anything.

  4. Thanks for sharing.

    Is there a way to post images from a Ruby CMS to a WordPress blog? Similar to the above, but with images (or any other file type).

    Thanks.

    Alex TaboneMarch 23, 2012 @ 11:36 amReply
    • I have not used the attachment functionality myself, but it sounds like there is some sort of support for it. Have a look here. I am also curious if this will work, I’ll have a look if I have time, but please share your findings if you investigate it yourself.

      — Edit —
      Looking through the source code, I see that attachments are indeed supported. Basically what you need to do is add $_FILES['attachment'] to your POST request. You can have a look at the source code for details.

  5. Would this work for retrieving an external JSON feed and creating articles with that? also, what about it creating articles in custom post types?

    Cheers,

    Jono

    • It would work for any kind of content source, yes. You simply have to parse your json, and then use this class to create and post the articles.
      Regarding custom post types, I updated the code example to include a type attribute, being set to post by default.

      Generally, you can probably tweak this to do more by having a look at what fields the wp-json-api object supports here.

  6. Hi, would you have any ideas of how to get this to post HTML? My goal would be to have something create a HTML document and then point this script at it. The script would then upload the HTML as a post. I am a Ruby newb so any pointers would be helpful.

    Thanks

    • Hey, this code can post HTML just fine. For example, try changing line #47 to

      :content => '<h1>HTML TEST</h1><hr/>'

      and then sending the post to your blog.

  7. Hi there,

    I’m trying to get this to work in rails 4.

    The plugin sends back this error: RuntimeError: You need to login with a user that has ‘edit_posts’ capacity.

    I installed your fork of the plugin but got this error:
    JSON::ParserError: A JSON text must at least contain two octets!

    Do you have a sample that works in Rails4?

    • great tut by the way, thanks

    • Hey, Rails version doesn’t enter into it. Although I don’t really maintain my fork anymore, it sounds like the problem is there and not in the ruby code. Try visiting the json-api urls in your browser and see what they return. There is also the possibility that recent WordPress updates may have broken my plugin fork in which case I’m sorry to say that this solution will not work.

  8. Hi, how’d you update/delete posts?
    I mean the methods from the non-authenticating version of this php plugin.



Some HTML is OK

or, reply to this post via trackback.