plistifier icon indicating copy to clipboard operation
plistifier copied to clipboard

A rails plugin to use the .plist format to return binary plists

Plistifier

This plugin is for Rails 2 and will not work in Rails 3. If you need this functionality for Rails 3 check out https://github.com/MSchmidt/CFPropertyList-rails instead.

Adds the possibility to talk to a rails app via (Binary) Property Lists http://developer.apple.com/mac/library/documentation/Darwin/Reference/ManPages/man5/plist.5.html

It is designed to work like the JSON format. On the iPhone it is easier to use, much faster; because Plists are smaller; and it doesn't need any third party libraries for parsing like JSON, or difficult SAX-style parsing like XML.

It adds the ActiveRecord#to_plist, Array#to_plist and Hash#to_plist methods similar to ActiveRecord#to_json. The :only, :except, :methods, and :include options are supported on ActiveRecord and Array with ActiveRecord items.

Install

sudo gem install --remote CFPropertyList script/plugin install git://github.com/jeena/plistifier.git

If you should get the error "Unknown class NilClass! Try using :convert_unknown_to_string if you want to use unknown object types!" you need to upgrade to rake-0.8.7.

Example

Getting data from rails

In your PostController use for example:

def index
  @posts = Post.all

  respond_to do |format|
    format.html # index.html.erb
    format.xml  { render :xml => @posts }
    format.plist { render :plist => @posts, :only => [:id, :title] }
  end
end

def show
  @post = Post.find(params[:id])

  respond_to do |format|
    format.html # show.html.erb
    format.xml  { render :xml => @post }
		format.plist { render :plist => @post }
  end
end

def show
  @post = Post.find(params[:id])

  respond_to do |format|
		format.plist { render :plist => @post, :plist_filename => "a-testfile.plist" }
  end
end

On the iPhone use for example:

NSURL *url = [NSURL URLWithString:@"http://example.com/posts.plist"];
NSArray *posts = [[NSArray alloc] initWithContentsOfURL:url];
NSLog(@"Title: %@", [[posts objectAtIndex:0] objectForKey:@"title"]);

Sending data to rails

It is possible to send a plist back into rails. On the iPhone you have to do for example:

NSDictionary *aPost = [[NSDictionary alloc] initWithObjectsAndKeys:
				@"A title", @"title",
				@"Some text for body", @"body", nil];
NSDictionary *aDict = [[NSDictionary alloc] initWithObjectsAndKeys:aPost, @"post", nil];
NSData *data = [NSPropertyListSerialization dataFromPropertyList:aDict
			format:NSPropertyListBinaryFormat_v1_0
			errorDescription:nil];

NSURL *url = [NSURL URLWithString:@"http://example.com/posts.plist"];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"application/plist" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:data];

NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[connection release];
[request release];
[data release];
[aDict release];
[aPost release];

And on the rails side:

def create
  @post = Post.new(params[:post])

  respond_to do |format|
    if @post.save
      flash[:notice] = 'Post was successfully created.'
      format.html { redirect_to(@post) }
      format.xml  { render :xml => @post, :status => :created, :location => @post }
      format.plist  { render :plist => @post, :status => :created, :location => @post }
    else
      format.html { render :action => "new" }
      format.xml  { render :xml => @post.errors, :status => :unprocessable_entity }
			format.plist { render :plist => @post.errors, :status => :unprocessable_entity }
    end
  end
end

So you see the params variable is the property list you just send from your iPhone.

Known problems

There is one problem though, If you want to do something like this it will crash:

@post = Post.all
myplist = { :foo => "bar", :post => @post }.to_plist

You have to convert the ActionRecord @post to a hash which CFPropertyList understands and can convert for example like:

myplist = { :foo => "bar", :post => @post.to_hash }.to_plist

ActionRecord#to_hash is a method the plugin adds.

Thanks

This plugin uses Christian Kruses CFPropertyList http://github.com/ckruse/CFPropertyList to generate Plists.

This plugin started as a copy of http://github.com/chuyeow/jsonifier/ I just changed it to support and added the CFPropertyList stuff.

Thanks Alexandre Bournier from http://pixyapps.com for his great ideas on how to improve the functionality and the help with testing.

Copyright (c) 2010 Jeena Paradies, released under the MIT license