peterosullivan-highrise 3.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. data/.gitignore +2 -0
  2. data/.travis.yml +9 -0
  3. data/Gemfile +3 -0
  4. data/Gemfile.lock +46 -0
  5. data/MIT-LICENSE +20 -0
  6. data/README.md +89 -0
  7. data/Rakefile +14 -0
  8. data/autotest/discover.rb +1 -0
  9. data/examples/config_initializers_highrise.rb +4 -0
  10. data/examples/extending.rb +31 -0
  11. data/examples/sample.rb +9 -0
  12. data/highrise.gemspec +33 -0
  13. data/lib/highrise/account.rb +7 -0
  14. data/lib/highrise/base.rb +25 -0
  15. data/lib/highrise/comment.rb +3 -0
  16. data/lib/highrise/company.rb +15 -0
  17. data/lib/highrise/deal.rb +8 -0
  18. data/lib/highrise/deal_category.rb +3 -0
  19. data/lib/highrise/email.rb +9 -0
  20. data/lib/highrise/group.rb +3 -0
  21. data/lib/highrise/kase.rb +19 -0
  22. data/lib/highrise/membership.rb +3 -0
  23. data/lib/highrise/note.rb +9 -0
  24. data/lib/highrise/pagination.rb +72 -0
  25. data/lib/highrise/party.rb +11 -0
  26. data/lib/highrise/person.rb +45 -0
  27. data/lib/highrise/recording.rb +5 -0
  28. data/lib/highrise/rfc822.rb +30 -0
  29. data/lib/highrise/searchable.rb +23 -0
  30. data/lib/highrise/subject.rb +31 -0
  31. data/lib/highrise/tag.rb +12 -0
  32. data/lib/highrise/taggable.rb +20 -0
  33. data/lib/highrise/task.rb +11 -0
  34. data/lib/highrise/task_category.rb +3 -0
  35. data/lib/highrise/user.rb +17 -0
  36. data/lib/highrise/version.rb +3 -0
  37. data/lib/highrise.rb +22 -0
  38. data/spec/highrise/account_spec.rb +10 -0
  39. data/spec/highrise/base_spec.rb +48 -0
  40. data/spec/highrise/comment_spec.rb +5 -0
  41. data/spec/highrise/company_spec.rb +17 -0
  42. data/spec/highrise/deal_category_spec.rb +13 -0
  43. data/spec/highrise/deal_spec.rb +23 -0
  44. data/spec/highrise/email_spec.rb +13 -0
  45. data/spec/highrise/group_spec.rb +5 -0
  46. data/spec/highrise/kase_spec.rb +17 -0
  47. data/spec/highrise/membership_spec.rb +5 -0
  48. data/spec/highrise/note_spec.rb +14 -0
  49. data/spec/highrise/pagination_behavior.rb +50 -0
  50. data/spec/highrise/pagination_spec.rb +8 -0
  51. data/spec/highrise/party_spec.rb +16 -0
  52. data/spec/highrise/person_spec.rb +33 -0
  53. data/spec/highrise/recording_spec.rb +7 -0
  54. data/spec/highrise/searchable_behavior.rb +13 -0
  55. data/spec/highrise/searchable_spec.rb +8 -0
  56. data/spec/highrise/subject_spec.rb +34 -0
  57. data/spec/highrise/tag_spec.rb +18 -0
  58. data/spec/highrise/taggable_behavior.rb +27 -0
  59. data/spec/highrise/taggable_spec.rb +9 -0
  60. data/spec/highrise/task_category_spec.rb +13 -0
  61. data/spec/highrise/task_spec.rb +11 -0
  62. data/spec/highrise/user_spec.rb +18 -0
  63. data/spec/spec_helper.rb +11 -0
  64. metadata +182 -0
data/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ pkg/**
2
+ .rvmrc
data/.travis.yml ADDED
@@ -0,0 +1,9 @@
1
+ rvm:
2
+ - 1.9.2
3
+ - 1.8.7
4
+ - ree-1.8.7
5
+ - 1.8.7-p249
6
+ - jruby
7
+ # branches:
8
+ # only:
9
+ # - master
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,46 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ highrise (3.0.1)
5
+ activeresource (~> 3.0)
6
+
7
+ GEM
8
+ remote: http://rubygems.org/
9
+ specs:
10
+ activemodel (3.1.0)
11
+ activesupport (= 3.1.0)
12
+ bcrypt-ruby (~> 3.0.0)
13
+ builder (~> 3.0.0)
14
+ i18n (~> 0.6)
15
+ activeresource (3.1.0)
16
+ activemodel (= 3.1.0)
17
+ activesupport (= 3.1.0)
18
+ activesupport (3.1.0)
19
+ multi_json (~> 1.0)
20
+ bcrypt-ruby (3.0.0)
21
+ bcrypt-ruby (3.0.0-java)
22
+ builder (3.0.0)
23
+ diff-lcs (1.1.2)
24
+ i18n (0.6.0)
25
+ multi_json (1.0.3)
26
+ rake (0.8.7)
27
+ rspec (2.0.1)
28
+ rspec-core (~> 2.0.1)
29
+ rspec-expectations (~> 2.0.1)
30
+ rspec-mocks (~> 2.0.1)
31
+ rspec-core (2.0.1)
32
+ rspec-expectations (2.0.1)
33
+ diff-lcs (>= 1.1.2)
34
+ rspec-mocks (2.0.1)
35
+ rspec-core (~> 2.0.1)
36
+ rspec-expectations (~> 2.0.1)
37
+
38
+ PLATFORMS
39
+ java
40
+ ruby
41
+
42
+ DEPENDENCIES
43
+ activeresource (~> 3.0)
44
+ highrise!
45
+ rake (= 0.8.7)
46
+ rspec (~> 2.0.1)
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 Ken Mayer & Marcos Tapajos
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,89 @@
1
+ ##whats in this fork
2
+
3
+ This fork is very close to the orginal gem. I have added a few features and shortcut methods;
4
+
5
+
6
+ Highrise::Tag.delete_by_name('tag_name')
7
+
8
+ Highrise::Person.url_for(123)
9
+ Highrise::Person.find(123).tagged?('tag_name')
10
+ Highrise::Person.find(123).email_address
11
+ Highrise::Person.find(123).email_valid?
12
+ Highrise::Person.find(123).phone_number
13
+
14
+ # Highrise (3.0.0) [![Build Status](https://secure.travis-ci.org/tapajos/highrise.png)](http://travis-ci.org/tapajos/highrise)
15
+
16
+ ## What is it?
17
+
18
+ This gem provides a set of classes to access information on [Highrise][h] via the published [API][api]:
19
+
20
+ Account, Comment, Company, Deal, DealCategory, Email, Group, Case, Membership, Note, Party, Person, Recording, Subject, Tag, Task, TaskCategory and User.
21
+
22
+ All these classes are inherited from ActiveResouce::Base. Refer to the [ActiveResouce][ar] documentation for more information.
23
+
24
+ ## Installing
25
+
26
+ gem install peterosullivan-highrise
27
+
28
+ ### Dependencies (see <code>highrise.gemspec</code> or run <code>bundle check</code>)
29
+
30
+ ### Documentation
31
+
32
+ I'm on [rdoc.info][rdoc]
33
+
34
+ ### Configure your key
35
+
36
+ require 'highrise'
37
+
38
+ Highrise::Base.site = 'https://your_site.highrisehq.com'
39
+ Highrise::Base.user = 'api-auth-token'
40
+
41
+ If you are using this in a Rails application, putting this code in a config/initializers/highrise.rb
42
+ file is recommended. See config_initializers_highrise.rb in the examples/ directory.
43
+
44
+ ## Usage
45
+
46
+ @tags = Highrise::Tag.find(:all)
47
+
48
+ @people = Highrise::Person.find_all_across_pages(:params => {:tag_id => 12345})
49
+
50
+ @person.tag!("VIP")
51
+
52
+ ## License
53
+
54
+ This code is free to be used under the terms of the [MIT license][mit].
55
+
56
+ ## Bugs, Issues, Kudos and Catcalls
57
+
58
+ Comments are welcome. Send your feedback through the [issue tracker on GitHub][i]
59
+
60
+ If you have fixes: Submit via pull requests. Do not include version changes to the
61
+ version file.
62
+
63
+ ## Authors
64
+
65
+ * [Marcos Tapajós][tapajos]
66
+ * [Ken Mayer][kmayer]
67
+
68
+ ## Contributors
69
+
70
+ * [Nicolas Bianco][slainer86]
71
+ * [Luis Gustavo][luisbebop]
72
+ * [Thiago Lelis][ThiagoLelis]
73
+ * [Denis Odorcic][odorcicd]
74
+
75
+
76
+
77
+ [api]: http://developer.37signals.com/highrise
78
+ [ar]: http://api.rubyonrails.org/classes/ActiveResource/Base.html
79
+ [c]: http://api.rubyonrails.org/classes/ActiveSupport/Cache
80
+ [h]: http://www.highrisehq.com/
81
+ [i]: https://github.com/tapajos/highrise/issues
82
+ [kmayer]: https://github.com/kmayer
83
+ [luisbebop]: https://github.com/luisbebop
84
+ [mit]:http://www.opensource.org/licenses/mit-license.php
85
+ [slainer86]: https://github.com/slainer86
86
+ [odorcicd]: https://github.com/odorcicd
87
+ [rdoc]: http://rdoc.info/projects/tapajos/highrise
88
+ [tapajos]: http://www.improveit.com.br/en/company/tapajos
89
+ [ThiagoLelis]: https://github.com/ThiagoLelis
data/Rakefile ADDED
@@ -0,0 +1,14 @@
1
+ # encoding: utf-8
2
+ require 'bundler'
3
+ Bundler::GemHelper.install_tasks
4
+
5
+ require 'rspec/core/rake_task'
6
+
7
+ desc 'Default: run unit tests.'
8
+ task :default => :spec
9
+
10
+ desc "Run all specs"
11
+ RSpec::Core::RakeTask.new do |t|
12
+ t.pattern = 'spec/**/*_spec.rb'
13
+ t.rspec_opts = ["-c", "-f progress"]
14
+ end
@@ -0,0 +1 @@
1
+ Autotest.add_discovery { "rspec2" }
@@ -0,0 +1,4 @@
1
+ if Rails.env != 'test' then
2
+ Highrise::Base.site = 'https://example.com.i'
3
+ Highrise::Base.user = 'my_fancy_auth_token'
4
+ end
@@ -0,0 +1,31 @@
1
+ #
2
+ # Example of extending a class when you need to synthesize an attribute.
3
+ #
4
+ # Adds Highrise::Person.{phone,fax,email} to the Person class inside your
5
+ # module
6
+ #
7
+
8
+ module MyModule
9
+ include Highrise
10
+
11
+ Highrise::Person.class_eval do
12
+ class << self
13
+ def lookup(id, list, item, location)
14
+ module_eval <<-EOT
15
+ def #{id}
16
+ contact_data.#{list}.each do |i|
17
+ return i.#{item}.strip if i.location == "#{location}"
18
+ end
19
+ ''
20
+ end
21
+ EOT
22
+ end
23
+
24
+ private :lookup
25
+ end
26
+
27
+ lookup(:phone, 'phone_numbers', 'number', 'Work')
28
+ lookup(:fax, 'phone_numbers', 'number', 'Fax')
29
+ lookup(:email, 'email_addresses', 'address', 'Work')
30
+ end
31
+ end
@@ -0,0 +1,9 @@
1
+ require 'highrise'
2
+ require 'pp'
3
+
4
+ Highrise::Base.site = 'https://yoursite.highrisehq.com'
5
+ Highrise::Base.user = 'xxx'
6
+
7
+ @tags = Highrise::Tag.find(:all)
8
+
9
+ pp @tags
data/highrise.gemspec ADDED
@@ -0,0 +1,33 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "highrise/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "peterosullivan-highrise"
7
+ s.version = Highrise::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+
10
+ s.required_rubygems_version = ">= 1.3.6"
11
+ s.add_dependency "activeresource", "~>3.0"
12
+ s.add_development_dependency "rspec", "~>2.0.1"
13
+ s.add_development_dependency "rake", "=0.8.7"
14
+
15
+ s.files = `git ls-files`.split("\n")
16
+ s.test_files = `git ls-files -- {test,spec,features,examples}/*`.split("\n")
17
+ s.require_paths = ["lib"]
18
+
19
+ s.authors = ["Marcos Tapaj\303\263s", "Ken Mayer", "Peter O'Sullivan"]
20
+ s.email = ["marcos@tapajos.me", "kmayer@bitwrangler.com", "peter@peterosullivan.net"]
21
+ s.homepage = "https://github.com/peterosullivan/highrise"
22
+ s.summary = %q{Ruby wrapper around Highrise API}
23
+ s.description = <<-EOT
24
+ Based on the original API module from DHH, http://developer.37signals.com/highrise/, this
25
+ gem is a cleaned up, tested version of the same. A fork of Tapaj gem. See the homepage for add features.
26
+
27
+ Configure by adding the following:
28
+
29
+ require 'highrise'
30
+ Highrise::Base.site = 'http://your_site.highrisehq.com/'
31
+ Highrise::Base.user = 'your_api_auth_token'
32
+ EOT
33
+ end
@@ -0,0 +1,7 @@
1
+ module Highrise
2
+ class Account < Base
3
+ def self.me
4
+ find(:one, :from => "/account.xml")
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,25 @@
1
+ require 'active_resource'
2
+
3
+ module Highrise
4
+ class Base < ActiveResource::Base
5
+
6
+ def self.url_for(n)
7
+ base = site.to_s.split('@')[1]
8
+ File.join('https://', base, element_path(n)).gsub(".xml",'')
9
+ end
10
+
11
+ protected
12
+ # Dynamic finder for attributes
13
+ def self.method_missing(method, *args)
14
+ if method.to_s =~ /^find_(all_)?by_([_a-zA-Z]\w*)$/
15
+ raise ArgumentError, "Dynamic finder method must take an argument." if args.empty?
16
+ options = args.extract_options!
17
+ resources = respond_to?(:find_all_across_pages) ? send(:find_all_across_pages, options) : send(:find, :all)
18
+ resources.send($1 == 'all_' ? 'select' : 'detect') { |container| container.send($2) == args.first }
19
+ else
20
+ super
21
+ end
22
+ end
23
+
24
+ end
25
+ end
@@ -0,0 +1,3 @@
1
+ module Highrise
2
+ class Comment < Base; end
3
+ end
@@ -0,0 +1,15 @@
1
+ module Highrise
2
+ class Company < Subject
3
+ include Pagination
4
+ include Taggable
5
+ include Searchable
6
+
7
+ def people
8
+ Person.find_all_across_pages(:from => "/companies/#{id}/people.xml")
9
+ end
10
+
11
+ def label
12
+ 'Party'
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,8 @@
1
+ module Highrise
2
+ class Deal < Subject
3
+ def update_status(status)
4
+ raise ArgumentError, "status must be one of 'pending', 'won', or 'lost'" unless %w[pending won lost].include?(status)
5
+ self.put(:status, :status => {:name => status})
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,3 @@
1
+ module Highrise
2
+ class DealCategory < Base; end
3
+ end
@@ -0,0 +1,9 @@
1
+ module Highrise
2
+ class Email < Base
3
+ include Pagination
4
+
5
+ def comments
6
+ Comment.find(:all, :from => "/emails/#{email_id}/comments.xml")
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,3 @@
1
+ module Highrise
2
+ class Group < Base; end
3
+ end
@@ -0,0 +1,19 @@
1
+ module Highrise
2
+ class Kase < Subject
3
+ def open!
4
+ update_attribute(:closed_at, nil)
5
+ end
6
+
7
+ def close!
8
+ update_attribute(:closed_at, Time.now.utc)
9
+ end
10
+
11
+ def self.open
12
+ Kase.find(:all, :from => "/kases/open.xml")
13
+ end
14
+
15
+ def self.closed
16
+ Kase.find(:all, :from => "/kases/closed.xml")
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,3 @@
1
+ module Highrise
2
+ class Membership < Base; end
3
+ end
@@ -0,0 +1,9 @@
1
+ module Highrise
2
+ class Note < Base
3
+ include Pagination
4
+
5
+ def comments
6
+ Comment.find(:all, :from => "/notes/#{id}/comments.xml")
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,72 @@
1
+ module Highrise
2
+ module Pagination
3
+ def self.included(base)
4
+ base.extend(ClassMethods)
5
+ end
6
+
7
+ module ClassMethods
8
+ def find_all_across_pages(options = {})
9
+ records = []
10
+ each(options) { |record| records << record }
11
+ records
12
+ end
13
+
14
+ # This only is usefull for company, person & recordings, but should be safely ignored by other classes
15
+ def find_all_across_pages_since(time)
16
+ find_all_across_pages(:params => { :since => time.utc.strftime("%Y%m%d%H%M%S") })
17
+ end
18
+
19
+ # This is useful only for Company, Person, Note, Comment, Email and Task, but should be safely ignored by other classes
20
+ def find_all_deletions_across_pages(options = {})
21
+ # point to the global deletions feed
22
+ options[:from] = '/deletions.xml'
23
+
24
+ records = []
25
+ each_deletions(options) { |record| records << record }
26
+ records
27
+ end
28
+
29
+ # This is useful only for Company, Person, Note, Comment, Email and Task, but should be safely ignored by other classes
30
+ def find_all_deletions_across_pages_since(time)
31
+ find_all_deletions_across_pages(:params => { :since => time.utc.strftime("%Y%m%d%H%M%S") })
32
+ end
33
+
34
+ private
35
+
36
+ def each(options = {})
37
+ options[:params] ||= {}
38
+ options[:params][:n] = 0
39
+
40
+ loop do
41
+ if (records = self.find(:all, options)).try(:any?)
42
+ records.each { |record| yield record }
43
+ options[:params][:n] += records.size
44
+ else
45
+ break # no people included on that page, thus no more people total
46
+ end
47
+ end
48
+ end
49
+
50
+ def each_deletions(options = {})
51
+ options[:params] ||= {}
52
+ # first index for deletions is 1
53
+ options[:params][:n] = 1
54
+
55
+ loop do
56
+ if (records = self.find(:all, options)).try(:any?)
57
+ # reject the records whose resource type is different from self
58
+ records.reject!{|r| r.class.to_s.split('::').last != self.to_s.split('::').last}
59
+
60
+ records.each{ |record| yield record }
61
+
62
+ # index increment for deletions is 1 per page of 500 resources
63
+ options[:params][:n] += 1
64
+ else
65
+ break # no deletions included on that page, thus no more deletions
66
+ end
67
+ end
68
+ end
69
+
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,11 @@
1
+ module Highrise
2
+ class Party < Base
3
+ def self.recently_viewed
4
+ find(:all, :from => "/parties/recently_viewed.xml")
5
+ end
6
+
7
+ def self.deletions_since(time)
8
+ find(:all, :from => "/parties/deletions.xml", :params => { :since => time.utc.strftime("%Y%m%d%H%M%S") })
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,45 @@
1
+ module Highrise
2
+ class Person < Subject
3
+ require 'highrise/rfc822'
4
+ include Pagination
5
+ include Taggable
6
+ include Searchable
7
+
8
+ def company
9
+ Company.find(company_id) if company_id
10
+ end
11
+
12
+ def name
13
+ "#{first_name rescue ''} #{last_name rescue ''}".strip
14
+ end
15
+
16
+ def address
17
+ contact_data.addresses.first
18
+ end
19
+
20
+ def web_address
21
+ contact_data.web_addresses.first
22
+ end
23
+
24
+ def label
25
+ 'Party'
26
+ end
27
+
28
+ def phone_number
29
+ contact_data.phone_numbers.first.number rescue nil
30
+ end
31
+
32
+ def email_valid?
33
+ !!(email_address && (email_address =~ RFC822::EmailAddress))
34
+ end
35
+
36
+ def email_address
37
+ contact_data.email_addresses.first.address rescue nil
38
+ end
39
+
40
+ def tagged? name
41
+ tags.any?{ | tag | tag['name'].to_s == name}
42
+ end
43
+
44
+ end
45
+ end
@@ -0,0 +1,5 @@
1
+ module Highrise
2
+ class Recording < Base
3
+ include Pagination
4
+ end
5
+ end
@@ -0,0 +1,30 @@
1
+ #
2
+ # RFC822 Email Address Regex
3
+ # --------------------------
4
+ #
5
+ # Originally written by Cal Henderson
6
+ # c.f. http://iamcal.com/publish/articles/php/parsing_email/
7
+ #
8
+ # Translated to Ruby by Tim Fletcher, with changes suggested by Dan Kubb.
9
+ #
10
+ # Licensed under a Creative Commons Attribution-ShareAlike 2.5 License
11
+ # http://creativecommons.org/licenses/by-sa/2.5/
12
+ #
13
+ module RFC822
14
+ EmailAddress = begin
15
+ qtext = '[^\\x0d\\x22\\x5c\\x80-\\xff]'
16
+ dtext = '[^\\x0d\\x5b-\\x5d\\x80-\\xff]'
17
+ atom = '[^\\x00-\\x20\\x22\\x28\\x29\\x2c\\x2e\\x3a-' +
18
+ '\\x3c\\x3e\\x40\\x5b-\\x5d\\x7f-\\xff]+'
19
+ quoted_pair = '\\x5c[\\x00-\\x7f]'
20
+ domain_literal = "\\x5b(?:#{dtext}|#{quoted_pair})*\\x5d"
21
+ quoted_string = "\\x22(?:#{qtext}|#{quoted_pair})*\\x22"
22
+ domain_ref = atom
23
+ sub_domain = "(?:#{domain_ref}|#{domain_literal})"
24
+ word = "(?:#{atom}|#{quoted_string})"
25
+ domain = "#{sub_domain}(?:\\x2e#{sub_domain})*"
26
+ local_part = "#{word}(?:\\x2e#{word})*"
27
+ addr_spec = "#{local_part}\\x40#{domain}"
28
+ pattern = /\A#{addr_spec}\z/
29
+ end
30
+ end
@@ -0,0 +1,23 @@
1
+ module Highrise
2
+ module Searchable
3
+ def self.included(base)
4
+ base.extend(ClassMethods)
5
+ end
6
+
7
+ module ClassMethods
8
+ # List By Search Criteria
9
+ # Ex: Highrise::Person.search(:email => "john.doe@example.com", :country => "CA")
10
+ # Available criteria are: city, state, country, zip, phone, email
11
+ def search(options = {})
12
+ raise ArgumentError, "cannot convert #{options}:#{options.class} to hash" if options.kind_of?(String)
13
+ search_params = options.inject({}) { |h, (k, v)| h["criteria[#{k}]"] = v; h }
14
+ # This might have to be changed in the future if other non-pagable resources become searchable
15
+ if self.respond_to?(:find_all_across_pages)
16
+ self.find_all_across_pages(:from => "/#{self.collection_name}/search.xml", :params => search_params)
17
+ else
18
+ self.find(:all, {:from => "/#{self.collection_name}/search.xml", :params => search_params})
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,31 @@
1
+ module Highrise
2
+ class Subject < Base
3
+ def notes
4
+ Note.find_all_across_pages(:from => "/#{self.class.collection_name}/#{id}/notes.xml")
5
+ end
6
+
7
+ def add_note(attrs={})
8
+ attrs[:subject_id] = self.id
9
+ attrs[:subject_type] = self.label
10
+ Note.create attrs
11
+ end
12
+
13
+ def add_task(attrs={})
14
+ attrs[:subject_id] = self.id
15
+ attrs[:subject_type] = self.label
16
+ Task.create attrs
17
+ end
18
+
19
+ def emails
20
+ Email.find_all_across_pages(:from => "/#{self.class.collection_name}/#{id}/emails.xml")
21
+ end
22
+
23
+ def upcoming_tasks
24
+ Task.find(:all, :from => "/#{self.class.collection_name}/#{id}/tasks.xml")
25
+ end
26
+
27
+ def label
28
+ self.class.name.split('::').last
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,12 @@
1
+ module Highrise
2
+ class Tag < Base
3
+ def ==(object)
4
+ (object.instance_of?(self.class) && object.id == self.id && object.name == self.name)
5
+ end
6
+
7
+ def self.delete_by_name(name)
8
+ tag = find_by_name(name)
9
+ tag.destroy if tag
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,20 @@
1
+ module Highrise
2
+ module Taggable
3
+ def tags
4
+ self.get(:tags)
5
+ end
6
+
7
+ def tag!(tag_name)
8
+ self.post(:tags, :name => tag_name) unless tag_name.blank?
9
+ end
10
+
11
+ def untag!(tag_name)
12
+ to_delete = self.tags.find{|tag| tag['name'] == tag_name} unless tag_name.blank?
13
+ self.untag_id!(to_delete['id']) unless to_delete.nil?
14
+ end
15
+ protected
16
+ def untag_id!(tag_id)
17
+ self.delete("tags/#{tag_id}")
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,11 @@
1
+ module Highrise
2
+ class Task < Base
3
+ # find(:all, :from => :upcoming)
4
+ # find(:all, :from => :assigned)
5
+ # find(:all, :from => :completed)
6
+
7
+ def complete!
8
+ load_attributes_from_response(post(:complete))
9
+ end
10
+ end
11
+ end