highrise 2.0.1 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. data/Gemfile +3 -0
  2. data/Gemfile.lock +38 -0
  3. data/MIT-LICENSE +1 -1
  4. data/README.mkdn +21 -29
  5. data/Rakefile +6 -31
  6. data/autotest/discover.rb +1 -3
  7. data/examples/config_initializers_highrise.rb +1 -9
  8. data/examples/sample.rb +0 -1
  9. data/highrise.gemspec +24 -117
  10. data/lib/highrise.rb +6 -5
  11. data/lib/highrise/account.rb +0 -1
  12. data/lib/highrise/base.rb +15 -3
  13. data/lib/highrise/comment.rb +1 -2
  14. data/lib/highrise/company.rb +3 -2
  15. data/lib/highrise/deal.rb +4 -1
  16. data/lib/highrise/deal_category.rb +3 -0
  17. data/lib/highrise/group.rb +1 -2
  18. data/lib/highrise/kase.rb +13 -2
  19. data/lib/highrise/membership.rb +1 -2
  20. data/lib/highrise/pagination.rb +8 -1
  21. data/lib/highrise/party.rb +11 -0
  22. data/lib/highrise/person.rb +1 -4
  23. data/lib/highrise/recording.rb +5 -0
  24. data/lib/highrise/searchable.rb +22 -0
  25. data/lib/highrise/subject.rb +6 -0
  26. data/lib/highrise/tag.rb +0 -5
  27. data/lib/highrise/taggable.rb +4 -1
  28. data/lib/highrise/task_category.rb +3 -0
  29. data/lib/highrise/version.rb +3 -0
  30. data/spec/highrise/account_spec.rb +5 -11
  31. data/spec/highrise/base_spec.rb +45 -10
  32. data/spec/highrise/comment_spec.rb +2 -11
  33. data/spec/highrise/company_spec.rb +10 -72
  34. data/spec/highrise/deal_category_spec.rb +13 -0
  35. data/spec/highrise/deal_spec.rb +16 -13
  36. data/spec/highrise/email_spec.rb +7 -19
  37. data/spec/highrise/group_spec.rb +2 -11
  38. data/spec/highrise/kase_spec.rb +10 -18
  39. data/spec/highrise/membership_spec.rb +2 -11
  40. data/spec/highrise/note_spec.rb +8 -17
  41. data/spec/highrise/pagination_behavior.rb +20 -0
  42. data/spec/highrise/pagination_spec.rb +4 -6
  43. data/spec/highrise/party_spec.rb +16 -0
  44. data/spec/highrise/person_spec.rb +23 -80
  45. data/spec/highrise/recording_spec.rb +13 -0
  46. data/spec/highrise/searchable_behavior.rb +13 -0
  47. data/spec/highrise/searchable_spec.rb +8 -0
  48. data/spec/highrise/subject_spec.rb +20 -35
  49. data/spec/highrise/tag_spec.rb +8 -13
  50. data/spec/highrise/taggable_behavior.rb +27 -0
  51. data/spec/highrise/taggable_spec.rb +9 -0
  52. data/spec/highrise/task_category_spec.rb +13 -0
  53. data/spec/highrise/task_spec.rb +6 -18
  54. data/spec/highrise/user_spec.rb +11 -28
  55. data/spec/spec_helper.rb +9 -18
  56. metadata +55 -42
  57. data/CHANGELOG +0 -131
  58. data/VERSION.yml +0 -5
  59. data/install.rb +0 -1
  60. data/lib/cachable.rb +0 -83
  61. data/spec/cachable_spec.rb +0 -84
  62. data/spec/spec.opts +0 -7
  63. data/uninstall.rb +0 -1
data/lib/highrise/deal.rb CHANGED
@@ -1,5 +1,8 @@
1
1
  module Highrise
2
2
  class Deal < Subject
3
-
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
4
7
  end
5
8
  end
@@ -0,0 +1,3 @@
1
+ module Highrise
2
+ class DealCategory < Base; end
3
+ end
@@ -1,4 +1,3 @@
1
1
  module Highrise
2
- class Group < Base
3
- end
2
+ class Group < Base; end
4
3
  end
data/lib/highrise/kase.rb CHANGED
@@ -1,8 +1,19 @@
1
1
  module Highrise
2
2
  class Kase < Subject
3
+ def open!
4
+ update_attribute(:closed_at, nil)
5
+ end
6
+
3
7
  def close!
4
- self.closed_at = Time.now.utc
5
- save
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")
6
17
  end
7
18
  end
8
19
  end
@@ -1,4 +1,3 @@
1
1
  module Highrise
2
- class Membership < Base
3
- end
2
+ class Membership < Base; end
4
3
  end
@@ -11,12 +11,19 @@ module Highrise
11
11
  records
12
12
  end
13
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
+ private
20
+
14
21
  def each(options = {})
15
22
  options[:params] ||= {}
16
23
  options[:params][:n] = 0
17
24
 
18
25
  loop do
19
- if (records = self.find(:all, options)).any?
26
+ if (records = self.find(:all, options)).try(:any?)
20
27
  records.each { |record| yield record }
21
28
  options[:params][:n] += records.size
22
29
  else
@@ -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
@@ -2,11 +2,8 @@ module Highrise
2
2
  class Person < Subject
3
3
  include Pagination
4
4
  include Taggable
5
+ include Searchable
5
6
 
6
- def self.find_all_across_pages_since(time)
7
- find_all_across_pages(:params => { :since => time.utc.to_s(:db).gsub(/[^\d]/, '') })
8
- end
9
-
10
7
  def company
11
8
  Company.find(company_id) if company_id
12
9
  end
@@ -0,0 +1,5 @@
1
+ module Highrise
2
+ class Recording < Base
3
+ include Pagination
4
+ end
5
+ end
@@ -0,0 +1,22 @@
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
+ search_params = options.inject({}) { |h, (k, v)| h["criteria[#{k}]"] = v; h }
13
+ # This might have to be changed in the future if other non-pagable resources become searchable
14
+ if self.respond_to?(:find_all_across_pages)
15
+ self.find_all_across_pages(:from => "/#{self.collection_name}/search.xml", :params => search_params)
16
+ else
17
+ self.find(:all, {:from => "/#{self.collection_name}/search.xml", :params => search_params})
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -9,6 +9,12 @@ module Highrise
9
9
  attrs[:subject_type] = self.label
10
10
  Note.create attrs
11
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
12
18
 
13
19
  def emails
14
20
  Email.find_all_across_pages(:from => "/#{self.class.collection_name}/#{id}/emails.xml")
data/lib/highrise/tag.rb CHANGED
@@ -3,10 +3,5 @@ module Highrise
3
3
  def ==(object)
4
4
  (object.instance_of?(self.class) && object.id == self.id && object.name == self.name)
5
5
  end
6
-
7
- # You can't find :one because that finds all *objects* with that tag
8
- def self.find_by_name(arg)
9
- tags = self.find(:all).detect{|tag| tag.name == arg}
10
- end
11
6
  end
12
7
  end
@@ -3,13 +3,16 @@ module Highrise
3
3
  def tags
4
4
  self.get(:tags)
5
5
  end
6
+
6
7
  def tag!(tag_name)
7
8
  self.post(:tags, :name => tag_name) unless tag_name.blank?
8
9
  end
10
+
9
11
  def untag!(tag_name)
10
12
  to_delete = self.tags.find{|tag| tag['name'] == tag_name} unless tag_name.blank?
11
13
  self.untag_id!(to_delete['id']) unless to_delete.nil?
12
- end
14
+ end
15
+ protected
13
16
  def untag_id!(tag_id)
14
17
  self.delete("tags/#{tag_id}")
15
18
  end
@@ -0,0 +1,3 @@
1
+ module Highrise
2
+ class TaskCategory < Base; end
3
+ end
@@ -0,0 +1,3 @@
1
+ module Highrise
2
+ VERSION = "3.0.0"
3
+ end
@@ -1,16 +1,10 @@
1
- require File.dirname(__FILE__) + '/../spec_helper'
1
+ require 'spec_helper'
2
2
 
3
3
  describe Highrise::Account do
4
- before(:each) do
5
- @account = Highrise::Account.new
6
- end
7
-
8
- it "should be instance of Highrise::Base" do
9
- @account.kind_of?(Highrise::Base).should be_true
10
- end
4
+ it { should be_a_kind_of Highrise::Base }
11
5
 
12
- it "should delegate to find(:one, :from => '/account.xml') when account is called" do
13
- Highrise::Account.should_receive(:find).with(:one, {:from => "/account.xml"}).and_return(@account)
14
- Highrise::Account.me.should == @account
6
+ it ".me" do
7
+ Highrise::Account.should_receive(:find).with(:one, {:from => "/account.xml"}).and_return(subject)
8
+ Highrise::Account.me.should == subject
15
9
  end
16
10
  end
@@ -1,13 +1,48 @@
1
- require File.dirname(__FILE__) + '/../spec_helper'
1
+ require 'spec_helper'
2
2
 
3
3
  describe Highrise::Base do
4
-
5
- before(:each) do
6
- @base = Highrise::Base.new
7
- end
8
-
9
- it "should be instance of ActiveResource::Base" do
10
- @base.kind_of?(ActiveResource::Base).should be_true
4
+ it { subject.should be_a_kind_of ActiveResource::Base }
5
+
6
+ describe "dynamic finder methods" do
7
+ context "without pagination" do
8
+ before do
9
+ @deal_one = Highrise::Base.new(:id => 1, :name => "A deal")
10
+ @deal_two = Highrise::Base.new(:id => 2, :name => "A deal")
11
+ @deal_three = Highrise::Base.new(:id => 3, :name => "Another deal")
12
+ Highrise::Base.should_receive(:find).with(:all).and_return([@deal_one, @deal_two, @deal_three])
13
+ end
14
+ it ".find_by_(attribute) finds one" do
15
+ Highrise::Base.find_by_name("A deal").should == @deal_one
16
+ end
17
+
18
+ it ".find_all_by_(attribute) finds all" do
19
+ Highrise::Base.find_all_by_name("A deal").should == [@deal_one, @deal_two]
20
+ end
21
+ end
22
+
23
+ context "with pagination" do
24
+ before do
25
+ class PaginatedBaseClass < Highrise::Base; include Highrise::Pagination; end
26
+ @john_doe = PaginatedBaseClass.new(:id => 1, :first_name => "John")
27
+ @john_baker = PaginatedBaseClass.new(:id => 2, :first_name => "John")
28
+ @joe_smith = PaginatedBaseClass.new(:id => 3, :first_name => "Joe")
29
+ PaginatedBaseClass.should_receive(:find_all_across_pages).and_return([@john_doe, @john_baker, @joe_smith])
30
+ end
31
+ it ".find_by_(attribute) finds one" do
32
+ PaginatedBaseClass.find_by_first_name("John").should == @john_doe
33
+ end
34
+
35
+ it ".find_all_by_(attribute) finds all" do
36
+ PaginatedBaseClass.find_all_by_first_name("John").should == [@john_doe, @john_baker]
37
+ end
38
+ end
39
+
40
+ it "expects arguments to the finder" do
41
+ expect { Highrise::Base.find_all_by_first_name }.to raise_error(ArgumentError)
42
+ end
43
+
44
+ it "falls back to regular method missing" do
45
+ expect { Highrise::Base.any_other_method }.to raise_error(NoMethodError)
46
+ end
11
47
  end
12
-
13
- end
48
+ end
@@ -1,14 +1,5 @@
1
- require File.dirname(__FILE__) + '/../spec_helper'
1
+ require 'spec_helper'
2
2
 
3
3
  describe Highrise::Comment do
4
-
5
- before(:each) do
6
- @comment = Highrise::Comment.new
7
- end
8
-
9
- it "should be instance of Highrise::Base" do
10
- @comment.kind_of?(Highrise::Base).should be_true
11
- end
12
-
13
-
4
+ it { should be_a_kind_of Highrise::Base }
14
5
  end
@@ -1,79 +1,17 @@
1
- require File.dirname(__FILE__) + '/../spec_helper'
1
+ require 'spec_helper'
2
2
 
3
3
  describe Highrise::Company do
4
-
5
- before(:each) do
6
- Highrise::Base.site = 'http://example.com.i:3000'
7
- @company = Highrise::Company.new(:id => 1)
8
- returning @tags = [] do
9
- @tags << {'id' => "414578", 'name' => "cliente"}
10
- @tags << {'id' => "414580", 'name' => "ged"}
11
- @tags << {'id' => "414579", 'name' => "iepc"}
12
- end
13
- end
14
-
15
- it "should be instance of Highrise::Base" do
16
- @company.kind_of?(Highrise::Base).should be_true
17
- end
18
-
19
- describe ".find_all_across_pages_since" do
20
-
21
- it "should delegate to find_all_across_pages with correct params" do
22
- time = Time.parse("Wed Jan 14 15:43:11 -0200 2009")
23
- Highrise::Company.should_receive(:find_all_across_pages).with({:params=>{:since=>"20090114174311"}}).and_return("result")
24
- Highrise::Company.find_all_across_pages_since(time).should == "result"
25
- end
26
-
27
- end
4
+ subject { Highrise::Company.new(:id => 1) }
28
5
 
29
- describe "people" do
30
-
31
- it "should delegate to Highrise::Person.find with correct params" do
32
- Highrise::Person.should_receive(:find).with(:all, {:from=>"/companies/1/people.xml"}).and_return("people")
33
- @company.people.should == "people"
34
- end
6
+ it { should be_a_kind_of Highrise::Base }
7
+ it_should_behave_like "a paginated class"
8
+ it_should_behave_like "a taggable class"
9
+ it_should_behave_like "a searchable class"
35
10
 
11
+ it "#people" do
12
+ Highrise::Person.should_receive(:find_all_across_pages).with(:from=>"/companies/1/people.xml").and_return("people")
13
+ subject.people.should == "people"
36
14
  end
37
15
 
38
- describe ".tags" do
39
-
40
- it "should return an array of all tags for that company." do
41
- @company.should_receive(:get).with(:tags).and_return(@tags)
42
- @company.tags.should == @tags
43
- end
44
-
45
- end
46
-
47
- describe "tag!(tag_name)" do
48
-
49
- it "should create a tag for this company." do
50
- @company.should_receive(:post).with(:tags, :name => "client" ).and_return(true)
51
- @company.tag!("client").should be_true
52
- end
53
-
54
- end
55
-
56
- describe "untag!(tag_name)" do
57
-
58
- it "should delete a tag for this company." do
59
- @company.should_receive(:get).with(:tags).and_return(@tags)
60
- @company.should_receive(:delete).with("tags/414578").and_return(true)
61
- @company.untag!("cliente").should be_true
62
- end
63
-
64
- end
65
-
66
- describe ".label" do
67
- it "should return 'Party' for label" do
68
- @company.label.should == 'Party'
69
- end
70
- end
71
-
72
- describe ".add_note" do
73
- it "should delegate to Highrise::Note.create with correct params" do
74
- Highrise::Note.should_receive(:create).with({:body=>"body", :subject_id=>1, :subject_type=>'Party'}).and_return(mock('note'))
75
- @company.add_note :body=>'body'
76
- end
77
- end
78
-
16
+ it { subject.label.should == 'Party' }
79
17
  end
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+
3
+ describe Highrise::DealCategory do
4
+ subject { Highrise::DealCategory.new(:id => 1, :name => "Deal Category") }
5
+
6
+ it { should be_a_kind_of Highrise::Base }
7
+
8
+ it ".find_by_name" do
9
+ deal_category = Highrise::DealCategory.new(:id => 2, :name => "Another Deal Category")
10
+ Highrise::DealCategory.should_receive(:find).with(:all).and_return([deal_category, subject])
11
+ Highrise::DealCategory.find_by_name("Deal Category").should == subject
12
+ end
13
+ end
@@ -1,20 +1,23 @@
1
- require File.dirname(__FILE__) + '/../spec_helper'
1
+ require 'spec_helper'
2
2
 
3
3
  describe Highrise::Deal do
4
-
5
- before(:each) do
6
- @deal = Highrise::Deal.new(:id => 1)
7
- end
4
+ subject { Highrise::Deal.new(:id => 1) }
5
+
6
+ it { should be_a_kind_of Highrise::Subject }
8
7
 
9
- it "should be instance of Highrise::Subject" do
10
- @deal.kind_of?(Highrise::Subject).should be_true
8
+ it ".add_note" do
9
+ Highrise::Note.should_receive(:create).with({:body=>"body", :subject_id=>1, :subject_type=>'Deal'}).and_return(mock('note'))
10
+ subject.add_note :body=>'body'
11
11
  end
12
12
 
13
- describe ".add_note" do
14
- it "should delegate to Highrise::Note.create with correct params" do
15
- Highrise::Note.should_receive(:create).with({:body=>"body", :subject_id=>1, :subject_type=>'Deal'}).and_return(mock('note'))
16
- @deal.add_note :body=>'body'
13
+ describe ".update_status" do
14
+ it { expect { subject.update_status("invalid") }.to raise_error(ArgumentError) }
15
+
16
+ %w[pending won lost].each do |status|
17
+ it "updates status to #{status}" do
18
+ subject.should_receive(:put).with(:status, :status => {:name => status})
19
+ subject.update_status(status)
20
+ end
17
21
  end
18
22
  end
19
-
20
- end
23
+ end
@@ -1,25 +1,13 @@
1
- require File.dirname(__FILE__) + '/../spec_helper'
1
+ require 'spec_helper'
2
2
 
3
3
  describe Highrise::Email do
4
+ it { should be_a_kind_of Highrise::Base }
4
5
 
5
- before(:each) do
6
- @mail = Highrise::Email.new
7
- end
8
-
9
- it "should be instance of Highrise::Base" do
10
- @mail.kind_of?(Highrise::Base).should be_true
11
- end
6
+ it_should_behave_like "a paginated class"
12
7
 
13
- describe "comments" do
14
-
15
- it "should delegate to Highrise::Comment.find with correct params" do
16
- @mail.should_receive(:email_id).and_return(1)
17
- Highrise::Comment.should_receive(:find).with(:all, {:from=>"/emails/1/comments.xml"}).and_return("comments")
18
- @mail.comments.should == "comments"
19
- end
20
-
8
+ it "#comments" do
9
+ subject.should_receive(:email_id).and_return(1)
10
+ Highrise::Comment.should_receive(:find).with(:all, {:from=>"/emails/1/comments.xml"}).and_return("comments")
11
+ subject.comments.should == "comments"
21
12
  end
22
-
23
-
24
-
25
13
  end