Skip to content

Instantly share code, notes, and snippets.

@lukeredpath
Created January 25, 2010 13:56
Show Gist options
  • Select an option

  • Save lukeredpath/285874 to your computer and use it in GitHub Desktop.

Select an option

Save lukeredpath/285874 to your computer and use it in GitHub Desktop.
require 'rubygems'
require 'restclient'
require 'crack'
require 'mash'
require 'active_support'
RestClient::Resource.class_eval do
def root
self.class.new(URI.parse(url).merge('/').to_s, options)
end
end
module FreeAgent
class Company
def initialize(domain, username, password)
@resource = RestClient::Resource.new(
"https://#{domain}.freeagentcentral.com",
:user => username, :password => password
)
end
def invoices
@invoices ||= Collection.new(@resource['/invoices'], :entity => :invoice)
end
def contacts
@contacts ||= Collection.new(@resource['/contacts'], :entity => :contact)
end
def expenses(user_id, options={})
options.assert_valid_keys(:view, :from, :to)
options.reverse_merge!(:view => 'recent')
if options[:from] && options[:to]
options[:view] = "#{options[:from].strftime('%Y-%m-%d')}_#{options[:to].strftime('%Y-%m-%d')}"
end
Collection.new(@resource["/users/#{user_id}/expenses?view=#{options[:view]}"], :entity => :expense)
end
end
class Collection
def initialize(resource, options={})
@resource = resource
@entity = options.delete(:entity)
end
def url
@resource.url
end
def find(id)
entity_for_id(id).reload
end
def find_all
case (response = @resource.get).code
when 200
if entities = Crack::XML.parse(response)[@entity.to_s.pluralize]
entities.map do |attributes|
entity_for_id(attributes['id'], attributes)
end
else
[]
end
end
end
def create(attributes)
payload = attributes.to_xml(:root => @entity.to_s )
case (response = @resource.post(payload,
:content_type => 'application/xml', :accept => 'application/xml')).code
when 201
resource_path = URI.parse(response.headers[:location]).path
Entity.new(@resource.root[resource_path], @entity)
end
end
def update(id, attributes)
entity_for_id(id).update(attributes, headers)
end
def destroy(id)
entity_for_id(id).destroy
end
private
def entity_for_id(id, attributes={})
Entity.new(@resource["/#{id}"], @entity, attributes)
end
end
class Entity
attr_reader :attributes
def initialize(resource, entity, attributes = {})
@resource, @entity = resource, entity
@attributes = attributes.to_mash
end
def url
@resource.url
end
def collection(path, entity)
Collection.new(@resource[path], :entity => entity)
end
def reload
returning(self) do
@attributes = Crack::XML.parse(@resource.get)[@entity.to_s].to_mash
end
end
def update(attributes = {})
@resource.put(attributes.to_xml(:root => @entity.to_s.downcase),
:content_type =>'application/xml', :accept => 'application/xml')
end
def destroy
@resource.delete
end
private
def method_missing(*args)
@attributes.send(*args)
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment