diff --git a/CHANGELOG.textile b/CHANGELOG.textile
deleted file mode 100644
index 3318f718..00000000
--- a/CHANGELOG.textile
+++ /dev/null
@@ -1,119 +0,0 @@
-h2. 2.1.0, released 19/11/2012
-
-* Add ability to create payments via the API
-* Allow creation of Payments via the API
-* Add check for valid invoice_type
-
-h2. 2.0.19, released 13/07/2012
-
-* Handle additional payment fields (payment_id, currency_rate)
-
-h2. 2.0.18, released 12/07/2012
-
-* Add accessor for the expires_at time when renewing access tokens
-
-h2. 2.0.15, released 15/06/2012
-
-* Add support for manual journals
-
-h2. 2.0.14, released 07/05/2012
-
-* Add support for bank transactions
-
-h2. 2.0.13, released 14/09/2011
-
-* Add new Organisation attributes
-* Partner app implementation
-* Add Invoice#sent_to_contact
-
-h2. 2.0.12, released 25/05/2011
-
-* Add OUTPUT2 and EC Zero-rated income as valid tax types
-* Add support for updating invoices
-* Add support for oauth_callback
-
-h2. 2.0.11, released 18/04/2011
-
-* Bug fixes
-
-h2. 2.0.10, released 12/04/2011
-
-* Fix issue with TrackingCategory#to_xml
-
-h2. 2.0.9, released 12/04/2011
-
-* Improve handling of ApiExceptions
-
-h2. 2.0.8, released 14/02/2011
-
-* Add support for new undocumented organisation attributes
-
-h2. 2.0.7, released 09/12/2010
-
-* Bug fixes
-
-h2. 2.0.6, released 14/11/2010
-
-* Bug fixes
-
-h2. 2.0.5, released 21/10/2010
-
-* Add support for credit notes. Thanks to malclocke and wasabhi for their contributions
-
-h2. 2.0.4, released 29/09/2010
-
-* Use bundler for dependency management
-
-h2. 2.0.3, released 29/09/2010
-
-* Fix issue caused by Xero updating the Tracking Category XML structure
-
-h2. 2.0.2, released 23/08/2010
-
-* Xero Api version 2.0
-
-h2. 1.0.5, released 25/09/2009
-
-* This will be the final release before switching to the Xero API version 2.0
-* Allow multiple tracking options per line item
-
-h2. 1.0.4, released 13/08/2009
-
-* Auto-assign Contact#contact_id and Invoice#invoice_id on creation of either of these records.
-* Add Xero::Gateway#build_contact and Xero::Gateway#build_invoice factory methods to create Contact/Invoice objects associated with the gateway.
-* Add Contact#save method to create/update a contact record based on if it has a contact_id or contact_number.
-* Add Invoice#save method to create (insert only currently supported by Xero API) the invoice.
-* Add #valid? method to each model class to validate it's contents with the minimum required by the API (without calling the API).
-* Add useful API constants throughout the library.
-* Allow Invoice and LineItem to auto-calculate line_amount, sub_total, total_tax and total fields. Existing setters for these fields remain (for backwards compatability) but will be deprecated in the future.
-* Create XeroGateway::AccountList class to make working with the accounts response more powerful and faster (as it caches the last result).
-* Add :updated_after parameter to XeroGateway::Gateway#get_contacts
-* Add XeroGateway::Gateway#update_contacts
-* Add XeroGateway::Gateway#create_invoices
-
-h2. 1.0.3, released 09/12/2008
-
-* Major refactorings to DRY out gateway.rb
-* Removed all messages classes in favour of invoice.to_xml and Invoice.from_xml(element)
-* Added unit tests for the handing of errors from Xero
-
-h2. 1.0.2, released 04/12/2008
-
-* Added implementation of GET /api.xro/1.0/tracking
-
-
-h2. 1.0.1, released 02/12/2008
-
-* Added implementation of GET /api.xro/1.0/accounts
-* Replaced Invoice.id, Contact.id etc with Invoice.invoice_id, Contact.contact_id to avoid Object.id errors
-
-
-h2. 1.0.0, released 01/12/2008
-
-* Initial release, including:
-* PUT /api.xro/1.0/contact
-* GET /api.xro/1.0/contact
-* GET /api.xro/1.0/contacts
-* PUT /api.xro/1.0/invoice
-* GET /api.xro/1.0/invoice
-* GET /api.xro/1.0/invoices
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
new file mode 100644
index 00000000..d05f4bc0
--- /dev/null
+++ b/CODE_OF_CONDUCT.md
@@ -0,0 +1,74 @@
+# Contributor Covenant Code of Conduct
+
+## Our Pledge
+
+In the interest of fostering an open and welcoming environment, we as
+contributors and maintainers pledge to making participation in our project and
+our community a harassment-free experience for everyone, regardless of age, body
+size, disability, ethnicity, gender identity and expression, level of experience,
+nationality, personal appearance, race, religion, or sexual identity and
+orientation.
+
+## Our Standards
+
+Examples of behavior that contributes to creating a positive environment
+include:
+
+* Using welcoming and inclusive language
+* Being respectful of differing viewpoints and experiences
+* Gracefully accepting constructive criticism
+* Focusing on what is best for the community
+* Showing empathy towards other community members
+
+Examples of unacceptable behavior by participants include:
+
+* The use of sexualized language or imagery and unwelcome sexual attention or
+advances
+* Trolling, insulting/derogatory comments, and personal or political attacks
+* Public or private harassment
+* Publishing others' private information, such as a physical or electronic
+ address, without explicit permission
+* Other conduct which could reasonably be considered inappropriate in a
+ professional setting
+
+## Our Responsibilities
+
+Project maintainers are responsible for clarifying the standards of acceptable
+behavior and are expected to take appropriate and fair corrective action in
+response to any instances of unacceptable behavior.
+
+Project maintainers have the right and responsibility to remove, edit, or
+reject comments, commits, code, wiki edits, issues, and other contributions
+that are not aligned to this Code of Conduct, or to ban temporarily or
+permanently any contributor for other behaviors that they deem inappropriate,
+threatening, offensive, or harmful.
+
+## Scope
+
+This Code of Conduct applies both within project spaces and in public spaces
+when an individual is representing the project or its community. Examples of
+representing a project or community include using an official project e-mail
+address, posting via an official social media account, or acting as an appointed
+representative at an online or offline event. Representation of a project may be
+further defined and clarified by project maintainers.
+
+## Enforcement
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be
+reported by contacting the project team at [INSERT EMAIL ADDRESS]. All
+complaints will be reviewed and investigated and will result in a response that
+is deemed necessary and appropriate to the circumstances. The project team is
+obligated to maintain confidentiality with regard to the reporter of an incident.
+Further details of specific enforcement policies may be posted separately.
+
+Project maintainers who do not follow or enforce the Code of Conduct in good
+faith may face temporary or permanent repercussions as determined by other
+members of the project's leadership.
+
+## Attribution
+
+This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
+available at [http://contributor-covenant.org/version/1/4][version]
+
+[homepage]: http://contributor-covenant.org
+[version]: http://contributor-covenant.org/version/1/4/
diff --git a/README.md b/README.md
index 2ce89bea..01e7ca76 100644
--- a/README.md
+++ b/README.md
@@ -1,110 +1,140 @@
Xero API wrapper [![Build Status](https://travis-ci.org/xero-gateway/xero_gateway.svg?branch=master)](https://travis-ci.org/xero-gateway/xero_gateway) [![Gem Version](https://badge.fury.io/rb/xero_gateway.svg)](https://badge.fury.io/rb/xero_gateway)
================
-Introduction
-------------
+# Getting Started
-This library is designed to help ruby / rails based applications
-communicate with the publicly available API for Xero. If you are
-unfamiliar with the API, you should first read the documentation,
-located here
+This is a Ruby gem for communicating with the Xero API.
+You can find more information about the Xero API at .
-Usage
------
+## Installation
- require 'xero_gateway'
- gateway = XeroGateway::Gateway.new(YOUR_OAUTH_CONSUMER_KEY, YOUR_OAUTH_CONSUMER_SECRET)
+Just add the `xero_gateway` gem to your Gemfile, like so:
-Authenticating with OAuth
--------------------------
+```ruby
+ gem 'xero_gateway'
+```
-OAuth is built into this library in a very similar manner to the Twitter
-gem by John Nunemaker
-([http://github.com/jnunemaker/twitter](http://github.com/jnunemaker/twitter)).
-So if you've used that before this will all seem familiar.
+## Usage
-### Consumer Key & Secret
+```ruby
+ gateway = XeroGateway::Gateway.new(YOUR_OAUTH_CONSUMER_KEY, YOUR_OAUTH_CONSUMER_SECRET)
+```
-First off, you'll need to get a Consumer Key/Secret pair for your
-application from Xero.\
-Head to , log in and then click My Applications
-> Add Application.
+### Authenticating with OAuth
-If you want to create a private application (that accesses your own Xero
-account rather than your users), you'll need to generate an RSA keypair
-and an X509 certificate. This can be done with OpenSSL as below:
+The Xero Gateway uses [OAuth 1.0a](https://oauth.net/core/1.0a/) for authentication. Xero Gateway
+implements OAuth in a very similar manner to the [Twitter gem by John Nunemaker](http://github.com/jnunemaker/twitter)
+, so if you've used that before this will all seem familiar.
- openssl genrsa –out privatekey.pem 1024
- openssl req –newkey rsa:1024 –x509 –key privatekey.pem –out publickey.cer –days 365
- openssl pkcs12 –export –out public_privatekey.pfx –inkey privatekey.pem –in publickey.cer
+ 1. **Get a Consumer Key & Secret**
-On the right-hand-side of your application's page there's a box titled
-"OAuth Credentials". Use the Key and Secret from this box in order to
-set up a new Gateway instance.
+ First off, you'll need to get a Consumer Key/Secret pair for your
+ application from Xero.\
+ Head to , log in and then click My Applications
+ > Add Application.
-(If you're unsure about the Callback URL, specify nothing - it will
-become clear a bit later)
+ If you want to create a private application (that accesses your own Xero
+ account rather than your users), you'll need to generate an RSA keypair
+ and an X509 certificate. This can be done with OpenSSL as below:
-### Xero Gateway Initialization
+ ```
+ openssl genrsa –out privatekey.pem 1024
+ openssl req –newkey rsa:1024 –x509 –key privatekey.pem –out publickey.cer –days 365
+ openssl pkcs12 –export –out public_privatekey.pfx –inkey privatekey.pem –in publickey.cer
+ ```
- require 'xero_gateway'
- gateway = XeroGateway::Gateway.new(YOUR_OAUTH_CONSUMER_KEY, YOUR_OAUTH_CONSUMER_SECRET)
+ On the right-hand-side of your application's page there's a box titled
+ "OAuth Credentials". Use the Key and Secret from this box in order to
+ set up a new Gateway instance.
-or for private applications
+ (If you're unsure about the Callback URL, specify nothing - it will
+ become clear a bit later)
- require 'xero_gateway'
- gateway = XeroGateway::PrivateApp.new(YOUR_OAUTH_CONSUMER_KEY, YOUR_OAUTH_CONSUMER_SECRET, PATH_TO_YOUR_PRIVATE_KEY)
+ 2. **Create a Xero Gateway in your App**
-### Request Token
+ ```ruby
+ gateway = XeroGateway::Gateway.new(YOUR_OAUTH_CONSUMER_KEY, YOUR_OAUTH_CONSUMER_SECRET)
+ ```
-You'll then need to get a Request Token from Xero.
+ or for Private applications
- request_token = gateway.request_token
+ ```ruby
+ require 'xero_gateway'
+ gateway = XeroGateway::PrivateApp.new(YOUR_OAUTH_CONSUMER_KEY, YOUR_OAUTH_CONSUMER_SECRET, PATH_TO_YOUR_PRIVATE_KEY)
+ ```
-You should keep this around - you'll need it to exchange for an Access
-Token later. (If you're using Rails, this means storing it in the
-session or something similar)
+ 3. **Creating a Request Token**
-Next, you need to redirect your user to the authorisation url for this
-request token. In Rails, that looks something like this:
+ You'll then need to get a Request Token from Xero.
- redirect_to request_token.authorize_url
+ ```ruby
+ request_token = gateway.request_token
+ ```
-You may also provide a callback parameter, which is the URL within your
-app the user will be redirected to. See next section for more
-information on what parameters Xero sends with this request.
+ You should keep this around - you'll need it to exchange for an Access
+ Token later. (If you're using Rails, this means storing it in the
+ session or something similar)
- redirect_to request_token(:oauth_callback => "http://www.something.com/xero/complete").authorize_url
+ Next, you need to redirect your user to the authorization url for this
+ request token. In Rails, that looks something like this:
-### Retrieving an Access Token
+ ```ruby
+ redirect_to request_token.authorize_url
+ ```
-If you've specified a Callback URL when setting up your application or
-provided an oauth\_callback parameter on your request token, your user
-will be redirected to that URL with an OAuth Verifier as a GET
-parameter. You can then exchange your Request Token for an Access Token
-like this (assuming Rails, once again):
+ You may also provide a callback parameter, which is the URL within your
+ app the user will be redirected to. See next section for more
+ information on what parameters Xero sends with this request.
- gateway.authorize_from_request(request_token.token, request_token.secret, :oauth_verifier => params[:oauth_verifier])
+ ```ruby
+ request_token = request_token(oauth_callback: "http://yourapp.comcom/xero/callback")
+ redirect_to request_token.authorize_url
+ ```
-(If you haven't specified a Callback URL, the user will be presented
-with a numeric verifier which they must copy+paste into your
-application; see examples/oauth.rb for an example)
+ 4. **Retrieving an Access Token**
-Now you can access Xero API methods:
+ If you've specified a Callback URL when setting up your application or
+ provided an oauth\_callback parameter on your request token, your user
+ will be redirected to that URL with an OAuth Verifier as a GET
+ parameter. You can then exchange your Request Token for an Access Token
+ like this (assuming Rails, once again):
- gateway.get_contacts
+ ```ruby
+ gateway.authorize_from_request(request_token.token, request_token.secret, oauth_verifier: params[:oauth_verifier])
+ ```
+
+ (If you haven't specified a Callback URL, the user will be presented
+ with a numeric verifier which they must copy+paste into your
+ application; see examples/oauth.rb for an example)
+
+ Now you can access Xero API methods:
+
+ ```ruby
+ gateway.get_contacts
+ # => # params[:oauth_verifier])
+ def create
+ @xero_gateway.authorize_from_request(session[:request_token], session[:request_secret],
+ oauth_verifier: params[:oauth_verifier])
- session[:xero_auth] = { :access_token => @xero_gateway.access_token.token,
- :access_secret => @xero_gateway.access_token.secret }
+ session[:xero_auth] = { access_token: @xero_gateway.access_token.token,
+ access_secret: @xero_gateway.access_token.secret }
- session.data.delete(:request_token); session.data.delete(:request_secret)
- end
+ session.data.delete(:request_token)
+ session.data.delete(:request_secret)
+ end
- def destroy
- session.data.delete(:xero_auth)
- end
+ def destroy
+ session.data.delete(:xero_auth)
+ end
- private
-
- def get_xero_gateway
- @xero_gateway = XeroGateway::Gateway.new(YOUR_OAUTH_CONSUMER_KEY, YOUR_OAUTH_CONSUMER_SECRET)
- end
+ private
+ def get_xero_gateway
+ @xero_gateway = XeroGateway::Gateway.new(YOUR_OAUTH_CONSUMER_KEY, YOUR_OAUTH_CONSUMER_SECRET)
end
+ end
+```
+
Note that I'm just storing the Access Token + Secret in the session here
- you could equally store them in the database if you felt like
refreshing them every 30 minutes ;)
-Implemented interface methods
------------------------------
-
-### GET /api.xro/2.0/contact (get\_contact\_by\_id)
-
-Gets a contact record for a specific Xero organisation
-
- result = gateway.get_contact_by_id(contact_id)
- contact = result.contact if result.success?
-
-### GET /api.xro/2.0/contact (get\_contact\_by\_number)
-
-Gets a contact record for a specific Xero organisation
-
- gateway.get_contact_by_number(contact_number)
-
-### GET /api.xro/2.0/contacts (get\_contacts)
-
-Gets all contact records for a particular Xero customer.
-
- gateway.get_contacts(:type => :all, :sort => :name, :direction => :desc)
- gateway.get_contacts(:type => :all, :modified_since => 1.month.ago) # modified since 1 month ago
-
-### PUT /api.xro/2.0/contact
-
-Saves a contact record for a particular Xero customer.
-
- contact = gateway.build_contact
- contact.name = "The contacts name"
- contact.email = "whoever@something.com"
- contact.phone.number = "555 123 4567"
- contact.address.line_1 = "LINE 1 OF THE ADDRESS"
- contact.address.line_2 = "LINE 2 OF THE ADDRESS"
- contact.address.city = "WELLINGTON"
- contact.address.region = "WELLINGTON"
- contact.address.country = "NEW ZEALAND"
- contact.address.post_code = "6021"
-
- contact.save
-
-### POST /api.xro/2.0/contact
-
-Updates an existing contact record.
-
- contact_retrieved_from_xero.email = "something_new@something.com"
- contact_retrieved_from_xero.save
-
-### POST /api.xro/2.0/contacts
-
-Creates a list of contacts or updates them if they have a matching
-contact\_id, contact\_number or name.\
-This method uses only a single API request to create/update multiple
-contacts.
-
- contacts = [XeroGateway::Contact.new(:name => 'Joe Bloggs'), XeroGateway::Contact.new(:name => 'Jane Doe')]
- result = gateway.update_contacts(contacts)
-
-### GET /api.xro/2.0/invoice (get\_invoice)
-
-Gets an invoice record for a specific Xero organisation by either id or
-number
-
- gateway.get_invoice(invoice_id_or_number)
-
-### GET /api.xro/2.0/invoices (get\_invoices)
-
-Gets all invoice records for a particular Xero customer.
-
- gateway.get_invoices
- gateway.get_invoices(:modified_since => 1.month.ago) # modified since 1 month ago
-
-### PUT /api.xro/2.0/invoice
-
-Inserts an invoice for a specific organization in Xero (Currently only
-adding new invoices is allowed).
-
-Invoice and line item totals are calculated automatically.
-
- invoice = gateway.build_invoice({
- :invoice_type => "ACCREC",
- :due_date => 1.month.from_now,
- :invoice_number => "YOUR INVOICE NUMBER",
- :reference => "YOUR REFERENCE (NOT NECESSARILY UNIQUE!)",
- :line_amount_types => "Inclusive" # "Inclusive", "Exclusive" or "NoTax"
- })
- invoice.contact.name = "THE NAME OF THE CONTACT"
- invoice.contact.phone.number = "12345"
- invoice.contact.address.line_1 = "LINE 1 OF THE ADDRESS"
-
- line_item = XeroGateway::LineItem.new(
- :description => "THE DESCRIPTION OF THE LINE ITEM",
- :account_code => 200,
- :unit_amount => 1000
- )
-
- line_item.tracking << XeroGateway::TrackingCategory.new(:name => "tracking category", :options => "tracking option")
-
- invoice.line_items << line_item
-
- invoice.create
-
-### POST /api.xro/2.0/invoice
-
-Updates an existing invoice record.
+## API Methods
- invoice_retrieved_from_xero.due_date = Date.today
- invoice_retrieved_from_xero.save
+You can find a full listing of all implemented methods on [the wiki page](https://github.com/xero-gateway/xero_gateway/wiki/API-Methods).
-### PUT /api.xro/2.0/invoices
+## Logging
-Inserts multiple invoices for a specific organization in Xero (currently
-only adding new invoices is allowed).\
-This method uses only a single API request to create/update multiple
-contacts.
-
- invoices = [XeroGateway::Invoice.new(...), XeroGateway::Invoice.new(...)]
- result = gateway.create_invoices(invoices)
-
-### GET /api.xro/2.0/credit\_note (get\_credit\_note\_by\_id)
-
-Gets an credit\_note record for a specific Xero organisation
-
- gateway.get_credit_note_by_id(credit_note_id)
-
-### GET /api.xro/2.0/credit\_note (get\_credit\_note\_by\_number)
-
-Gets a credit note record for a specific Xero organisation
-
- gateway.get_credit_note_by_number(credit_note_number)
-
-### GET /api.xro/2.0/credit\_notes (get\_credit\_notes)
-
-Gets all credit note records for a particular Xero customer.
-
- gateway.get_credit_notes
- gateway.get_credit_notes(:modified_since => 1.month.ago) # modified since 1 month ago
-
-### PUT /api.xro/2.0/credit\_note
-
-Inserts a credit note for a specific organization in Xero (Currently
-only adding new credit notes is allowed).
-
-CreditNote and line item totals are calculated automatically.
-
- credit_note = gateway.build_credit_note({
- :credit_note_type => "ACCRECCREDIT",
- :credit_note_number => "YOUR CREDIT NOTE NUMBER",
- :reference => "YOUR REFERENCE (NOT NECESSARILY UNIQUE!)",
- :line_amount_types => "Inclusive" # "Inclusive", "Exclusive" or "NoTax"
- })
- credit_note.contact.name = "THE NAME OF THE CONTACT"
- credit_note.contact.phone.number = "12345"
- credit_note.contact.address.line_1 = "LINE 1 OF THE ADDRESS"
- credit_note.add_line_item({
- :description => "THE DESCRIPTION OF THE LINE ITEM",
- :unit_amount => 1000,
- :tax_amount => 125,
- :tracking_category => "THE TRACKING CATEGORY FOR THE LINE ITEM",
- :tracking_option => "THE TRACKING OPTION FOR THE LINE ITEM"
- })
-
- credit_note.create
-
-### PUT /api.xro/2.0/credit\_notes
-
-Inserts multiple credit notes for a specific organization in Xero
-(currently only adding new credit notes is allowed).\
-This method uses only a single API request to create/update multiple
-contacts.
-
- credit_notes = [XeroGateway::CreditNote.new(...), XeroGateway::CreditNote.new(...)]
- result = gateway.create_credit_notes(credit_notes)
-
-### GET /api.xro/2.0/accounts
-
-Gets all accounts for a specific organization in Xero.
-
- gateway.get_accounts
-
-For more advanced (and cached) access to the accounts list, use the
-following.
-
- accounts_list = gateway.get_accounts_list
-
-Finds account with code of '200'
-
- sales_account = accounts_list.find_by_code(200)
-
-Finds all EXPENSE accounts. For a list of valid account types see
-XeroGateway::Account::TYPE
-
- all_expense_accounts = accounts_list.find_all_by_type('EXPENSE')
-
-Finds all accounts with tax\_type == 'OUTPUT'. For a list of valid tax
-types see XeroGateway::Account::TAX\_TYPE
-
- all_output_tax_accounts = accounts_list.find_all_by_tax_type('OUTPUT')
-
-### GET /api.xro/2.0/tracking
-
-Gets all tracking categories and their options for a specific
-organization in Xero.
-
- gateway.get_tracking_categories
-
-### GET /api.xero/2.0/Organisation
-
-Retrieves organisation details for the authorised application.
-
- gateway.get_organisation.organisation
-
-### GET /api.xero/2.0/Currencies
-
-Retrieves currencies in use for the authorised application.
-
- gateway.get_currencies.currencies
-
-### GET /api.xero/2.0/TaxRates
+You can specify a logger to use (so you can track down those tricky
+exceptions) by using:
-Retrieves Tax Rates in use for the authorised application.
+```ruby
+ gateway.logger = ActiveSupport::BufferedLogger.new("log_file_name.log")
+```
- gateway.get_tax_rates.tax_rates
+Your logger simply needs to respond to `info`.
-Logging
--------
+## Contributing
-You can specify a logger to use (so you can track down those tricky
-exceptions) by using:
+We welcome contributions, thanks for pitching in! :sparkles:
- gateway.logger = ActiveSupport::BufferedLogger.new("log_file_name.log")
+1. Fork the repo
+2. Create your feature branch (`git checkout -b my-new-feature`)
+3. Make sure you have some tests, and they pass! (`bundle exec rake`)
+4. Commit your changes (`git commit -am 'Added some feature'`)
+5. Push to the branch (`git push origin my-new-feature`)
+6. Create new Pull Request
-It doesn't have to be a buffered logger - anything that responds to
-"info" will do just fine.
+This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
diff --git a/init.rb b/init.rb
deleted file mode 100644
index 67079ab1..00000000
--- a/init.rb
+++ /dev/null
@@ -1 +0,0 @@
-require 'xero_gateway'
\ No newline at end of file
diff --git a/lib/xero_gateway/address.rb b/lib/xero_gateway/address.rb
index d0f2a169..de4e89bb 100644
--- a/lib/xero_gateway/address.rb
+++ b/lib/xero_gateway/address.rb
@@ -1,44 +1,44 @@
module XeroGateway
class Address
-
+
ADDRESS_TYPE = {
'STREET' => 'Street',
'POBOX' => 'PO Box'
} unless defined?(ADDRESS_TYPE)
-
+
# Any errors that occurred when the #valid? method called.
attr_reader :errors
-
- attr_accessor :address_type, :line_1, :line_2, :line_3, :line_4, :city, :region, :post_code, :country
-
+
+ attr_accessor :address_type, :line_1, :line_2, :line_3, :line_4, :city, :region, :post_code, :country, :attention_to
+
def initialize(params = {})
@errors ||= []
-
+
params = {
:address_type => "POBOX"
}.merge(params)
-
+
params.each do |k,v|
self.send("#{k}=", v)
end
end
-
+
# Validate the Address record according to what will be valid by the gateway.
#
- # Usage:
+ # Usage:
# address.valid? # Returns true/false
- #
+ #
# Additionally sets address.errors array to an array of field/error.
def valid?
@errors = []
-
+
if address_type && !ADDRESS_TYPE[address_type]
@errors << ['address_type', "must be one of #{ADDRESS_TYPE.keys.join('/')} and is currently #{address_type}"]
end
-
+
@errors.size == 0
- end
-
+ end
+
def to_xml(b = Builder::XmlMarkup.new)
b.Address {
b.AddressType address_type
@@ -50,44 +50,46 @@ def to_xml(b = Builder::XmlMarkup.new)
b.Region region if region
b.PostalCode post_code if post_code
b.Country country if country
+ b.AttentionTo attention_to if attention_to
}
end
-
+
def self.from_xml(address_element)
address = Address.new
address_element.children.each do |element|
case(element.name)
- when "AddressType" then address.address_type = element.text
+ when "AddressType" then address.address_type = element.text
when "AddressLine1" then address.line_1 = element.text
when "AddressLine2" then address.line_2 = element.text
when "AddressLine3" then address.line_3 = element.text
- when "AddressLine4" then address.line_4 = element.text
- when "City" then address.city = element.text
- when "Region" then address.region = element.text
- when "PostalCode" then address.post_code = element.text
- when "Country" then address.country = element.text
+ when "AddressLine4" then address.line_4 = element.text
+ when "City" then address.city = element.text
+ when "Region" then address.region = element.text
+ when "PostalCode" then address.post_code = element.text
+ when "Country" then address.country = element.text
+ when "AttentionTo" then address.attention_to = element.text
end
end
address
end
-
+
def self.parse(string)
address = Address.new
-
+
parts = string.split("\r\n")
-
+
if(parts.size > 3)
parts = [parts.shift, parts.shift, parts.shift, parts.join(", ")]
end
-
+
parts.each_with_index do |line, index|
address.send("line_#{index+1}=", line)
end
address
end
-
+
def ==(other)
- [:address_type, :line_1, :line_2, :line_3, :line_4, :city, :region, :post_code, :country].each do |field|
+ [:address_type, :line_1, :line_2, :line_3, :line_4, :city, :region, :post_code, :country, :attention_to].each do |field|
return false if send(field) != other.send(field)
end
return true
diff --git a/test/unit/address_test.rb b/test/unit/address_test.rb
new file mode 100644
index 00000000..a7c66605
--- /dev/null
+++ b/test/unit/address_test.rb
@@ -0,0 +1,34 @@
+require File.join(File.dirname(__FILE__), '../test_helper.rb')
+
+class AddressTest < Test::Unit::TestCase
+
+ test "build and parse XML" do
+ address = create_test_address
+
+ # Generate the XML message
+ address_xml = address.to_xml
+
+ # Parse the XML message and retrieve the address element
+ address_element = REXML::XPath.first(REXML::Document.new(address_xml), "/Address")
+
+ # Build a new contact from the XML
+ result_address = XeroGateway::Address.from_xml(address_element)
+
+ # Check the contact details
+ assert_equal address, result_address
+ end
+
+ private
+
+ def create_test_address
+ XeroGateway::Address.new(
+ line_1: "25 Taranaki St",
+ line_2: "Te Aro",
+ city: "Wellington",
+ post_code: "6011",
+ country: "New Zealand",
+ attention_to: "Hashigo Zake"
+ )
+ end
+
+end
diff --git a/test/unit/contact_test.rb b/test/unit/contact_test.rb
index 21503955..3939de7f 100644
--- a/test/unit/contact_test.rb
+++ b/test/unit/contact_test.rb
@@ -4,21 +4,21 @@ class ContactTest < Test::Unit::TestCase
def setup
@schema = LibXML::XML::Schema.document(LibXML::XML::Document.file(File.join(File.dirname(__FILE__), '../xsd/create_contact.xsd')))
end
-
+
# Tests that the XML generated from a contact object validates against the Xero XSD
def test_build_xml
contact = create_test_contact
-
+
message = contact.to_xml
# Check that the document matches the XSD
assert LibXML::XML::Parser.string(message).parse.validate_schema(@schema), "The XML document generated did not validate against the XSD"
end
-
+
# Tests that a contact can be converted into XML that Xero can understand, and then converted back to a contact
def test_build_and_parse_xml
contact = create_test_contact
-
+
# Generate the XML message
contact_as_xml = contact.to_xml
@@ -27,17 +27,17 @@ def test_build_and_parse_xml
# Build a new contact from the XML
result_contact = XeroGateway::Contact.from_xml(contact_element)
-
+
# Check the contact details
assert_equal contact, result_contact
end
-
+
# Test Contact#add_address helper creates a valid XeroGateway::Contact object with the passed in values
# and appends it to the Contact#addresses attribute.
def test_add_address_helper
contact = create_test_contact
assert_equal(1, contact.addresses.size)
-
+
new_values = {
:address_type => 'POBOX',
:line_1 => 'NEW LINE 1',
@@ -50,7 +50,7 @@ def test_add_address_helper
:country => 'Australia'
}
contact.add_address(new_values)
-
+
assert_equal(2, contact.addresses.size)
assert_kind_of(XeroGateway::Address, contact.addresses.last)
new_values.each { |k,v| assert_equal(v, contact.addresses.last.send("#{k}")) }
@@ -58,10 +58,10 @@ def test_add_address_helper
# Test Contact#add_phone helper creates a valid XeroGateway::Phone object with the passed in values
# and appends it to the Contact#phones attribute.
- def test_add_address_helper2
+ def test_add_phone_helper
contact = create_test_contact
assert_equal(1, contact.phones.size)
-
+
new_values = {
:phone_type => 'MOBILE',
:country_code => '61',
@@ -69,7 +69,7 @@ def test_add_address_helper2
:number => '123456'
}
contact.add_phone(new_values)
-
+
assert_equal(2, contact.phones.size)
assert_kind_of(XeroGateway::Phone, contact.phones.last)
new_values.each { |k,v| assert_equal(v, contact.phones.last.send("#{k}")) }
@@ -84,7 +84,7 @@ def test_valid_phone_number
})
assert(phone.valid?)
end
-
+
def test_invalid_phone_number
phone = XeroGateway::Phone.new({
:phone_type => 'MOBILE',
@@ -94,9 +94,9 @@ def test_invalid_phone_number
})
assert(!phone.valid?)
end
-
+
private
-
+
def create_test_contact
contact = XeroGateway::Contact.new(:contact_id => "55555")
contact.contact_number = "aaa111"
@@ -113,4 +113,4 @@ def create_test_contact
contact
end
-end
\ No newline at end of file
+end