highrise 1.2.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +42 -2
- data/README.mkdn +2 -2
- data/Rakefile +2 -0
- data/VERSION.yml +2 -2
- data/examples/config_initializers_highrise.rb +2 -2
- data/examples/sample.rb +1 -1
- data/lib/cachable.rb +51 -56
- data/lib/highrise/tag.rb +4 -17
- data/spec/cachable_spec.rb +41 -23
- data/spec/highrise/note_spec.rb +1 -0
- data/spec/highrise/person_spec.rb +2 -0
- metadata +26 -13
data/CHANGELOG
CHANGED
@@ -1,3 +1,43 @@
|
|
1
|
+
Author: Kenneth Mayer <kmayer@bitwrangler.com>
|
2
|
+
Date: Wed Feb 17 09:42:25 2010 -1000
|
3
|
+
|
4
|
+
Version bump to 2.0.0 -- Complete rewrite of Cachable. Interface has changed, see docs and examples.
|
5
|
+
|
6
|
+
Author: Kenneth Mayer <kmayer@bitwrangler.com>
|
7
|
+
Date: Mon Feb 15 13:41:28 2010 -1000
|
8
|
+
|
9
|
+
Version bump to 1.2.0
|
10
|
+
|
11
|
+
Added Account class to handle the /account.xml end point.
|
12
|
+
|
13
|
+
Author: Marcos Tapajós <tapajos@gmail.com>
|
14
|
+
Date: Wed Feb 10 22:57:34 2010 -0200
|
15
|
+
|
16
|
+
Version bump to 1.1.0 -- Added Deal class, .add_note helper, /me.xml endpoint
|
17
|
+
|
18
|
+
Author: Kenneth Mayer <kmayer@bitwrangler.com>
|
19
|
+
Date: Wed Sep 2 08:56:42 2009 -1000
|
20
|
+
|
21
|
+
Version bump to 1.0.1
|
22
|
+
|
23
|
+
Added a couple of convenience methods.
|
24
|
+
|
25
|
+
Author: Kenneth Mayer <kmayer@bitwrangler.com>
|
26
|
+
Date: Tue Sep 1 21:32:19 2009 -1000
|
27
|
+
|
28
|
+
Version bump to 1.0.0
|
29
|
+
|
30
|
+
Revised Taggable interface to support new tag API from 37Sigs and (removed curl dependencies)
|
31
|
+
|
32
|
+
Refactored Cachable
|
33
|
+
|
34
|
+
Author: Kenneth Mayer <kmayer@bitwrangler.com>
|
35
|
+
Date: Fri May 29 22:34:03 2009 -1000
|
36
|
+
|
37
|
+
Version bump to 0.13.0
|
38
|
+
|
39
|
+
Added Tag.find_by_name
|
40
|
+
|
1
41
|
2009-05-27 Ken Mayer <kmayer@bitwrangler.com>
|
2
42
|
|
3
43
|
* Version 0.12.0
|
@@ -84,8 +124,8 @@
|
|
84
124
|
* Add Person.tag that show a array of tags, and Perton.tag(name), add a new
|
85
125
|
tag to a person.
|
86
126
|
|
87
|
-
2009-01-14
|
127
|
+
2009-01-14 Marcos Tapajós
|
88
128
|
|
89
129
|
* Version 0.5.0
|
90
130
|
|
91
|
-
* Initial import
|
131
|
+
* Initial import
|
data/README.mkdn
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Highrise (
|
1
|
+
# Highrise (2.0.0)
|
2
2
|
|
3
3
|
## What is it?
|
4
4
|
|
@@ -28,7 +28,7 @@ All these classes are inherited from ActiveResouce::Base. Refer to the [ActiveRe
|
|
28
28
|
|
29
29
|
and, if you want [caching][c]:
|
30
30
|
|
31
|
-
Highrise::Base.cache_store= <your normal ActiveSupport::Caching options>
|
31
|
+
Highrise::Base.connection.cache_store= <your normal ActiveSupport::Caching options>
|
32
32
|
|
33
33
|
If you are using this in a Rails application, putting this code in a config/initializers/highrise.rb
|
34
34
|
file is recommended. See config_initializers_highrise.rb in the examples/ directory.
|
data/Rakefile
CHANGED
data/VERSION.yml
CHANGED
@@ -7,6 +7,6 @@ if Rails.env != 'test' then
|
|
7
7
|
Highrise::Base.site = 'https://my_fancy_auth_token@example.com.i'
|
8
8
|
end
|
9
9
|
# The cache store can be anything that ActiveSupport can handle
|
10
|
-
Highrise::Base.cache_store = ActiveSupport::Cache.lookup_store :mem_cache_store
|
11
|
-
Highrise::Base.store_options = { :expires_in => 60.seconds }
|
10
|
+
Highrise::Base.connection.cache_store = ActiveSupport::Cache.lookup_store :mem_cache_store
|
11
|
+
Highrise::Base.connection.store_options = { :expires_in => 60.seconds }
|
12
12
|
end
|
data/examples/sample.rb
CHANGED
data/lib/cachable.rb
CHANGED
@@ -7,10 +7,8 @@
|
|
7
7
|
#
|
8
8
|
# require 'cachable'
|
9
9
|
#
|
10
|
-
# module CachedResource
|
11
|
-
#
|
12
|
-
# include ::Cachable
|
13
|
-
# end
|
10
|
+
# module CachedResource < ActiveResource::Base
|
11
|
+
# include ::Cachable
|
14
12
|
# end
|
15
13
|
#
|
16
14
|
#
|
@@ -21,68 +19,65 @@
|
|
21
19
|
# these stores
|
22
20
|
#
|
23
21
|
# === Configuration examples ('off' is the default):
|
24
|
-
# CachedResource.cache_store = ActiveSupport::Cache.lookup_store :memory_store
|
25
|
-
# CachedResource.cache_store = ActiveSupport::Cache.lookup_store :file_store, "/path/to/cache/directory"
|
26
|
-
# CachedResource.cache_store = ActiveSupport::Cache.lookup_store :drb_store, "druby://localhost:9192"
|
27
|
-
# CachedResource.cache_store = ActiveSupport::Cache.lookup_store :mem_cache_store, "localhost"
|
28
|
-
# CachedResource.cache_store = MyOwnStore.new("parameter")
|
22
|
+
# CachedResource.connection.cache_store = ActiveSupport::Cache.lookup_store :memory_store
|
23
|
+
# CachedResource.connection.cache_store = ActiveSupport::Cache.lookup_store :file_store, "/path/to/cache/directory"
|
24
|
+
# CachedResource.connection.cache_store = ActiveSupport::Cache.lookup_store :drb_store, "druby://localhost:9192"
|
25
|
+
# CachedResource.connection.cache_store = ActiveSupport::Cache.lookup_store :mem_cache_store, "localhost"
|
26
|
+
# CachedResource.connection.cache_store = MyOwnStore.new("parameter")
|
29
27
|
#
|
30
28
|
# === If you are using a store that has write options, you can set them
|
31
|
-
# CachedResource.
|
29
|
+
# CachedResource.connection.cache_options = { :expires_in => 60.seconds }
|
32
30
|
#
|
33
31
|
# Note: To ensure that caching is turned off, set CachedResource.connection.cache_store = nil
|
34
32
|
#
|
35
|
-
# FYI: You can use this with *any* active resource
|
33
|
+
# FYI: You can use this with *any* active resource class, not just Highrise.
|
36
34
|
|
37
35
|
module Cachable
|
38
36
|
def self.included(base)
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
alias_method_chain :find_every, :cache
|
43
|
-
alias_method_chain :find_single, :cache
|
37
|
+
ActiveResource::Connection.class_eval do
|
38
|
+
def cache_store
|
39
|
+
@cache_store ||= nil
|
44
40
|
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
module ClassMethods
|
49
|
-
attr_writer :cache_store, :store_options
|
50
|
-
|
51
|
-
def cache_store
|
52
|
-
@cache_store ||= nil
|
53
|
-
end
|
54
|
-
|
55
|
-
def store_options
|
56
|
-
@store_options ||= {}
|
57
|
-
end
|
58
|
-
|
59
|
-
def is_caching?
|
60
|
-
!@cache_store.nil?
|
61
|
-
end
|
62
|
-
|
63
|
-
private
|
64
|
-
|
65
|
-
# A little hacky -- we need to intercept the finds, but not get too deep inside the connection
|
66
|
-
def find_every_with_cache(options)
|
67
|
-
return find_every_without_cache(options) unless is_caching?
|
68
|
-
prefix_options, query_options = split_options(options[:params])
|
69
|
-
path = collection_path(prefix_options, query_options)
|
70
|
-
fetch(path) { find_every_without_cache(options)}
|
71
|
-
end
|
72
|
-
|
73
|
-
def find_single_with_cache(scope, options)
|
74
|
-
return find_single_without_cache(scope, options) unless is_caching?
|
75
|
-
prefix_options, query_options = split_options(options[:params])
|
76
|
-
path = element_path(scope, prefix_options, query_options)
|
77
|
-
fetch(path) { find_single_without_cache(scope, options)}
|
78
|
-
end
|
79
41
|
|
80
|
-
|
81
|
-
|
82
|
-
|
42
|
+
def cache_store=(store)
|
43
|
+
@cache_store = store
|
44
|
+
end
|
45
|
+
|
46
|
+
def cache_options
|
47
|
+
@cache_options ||= {}
|
48
|
+
end
|
49
|
+
alias :store_options :cache_options
|
50
|
+
|
51
|
+
def cache_options=(options)
|
52
|
+
@cache_options = options
|
53
|
+
end
|
54
|
+
alias :store_options= :cache_options=
|
55
|
+
|
56
|
+
def is_caching?
|
57
|
+
!@cache_store.nil?
|
58
|
+
end
|
59
|
+
|
60
|
+
def get_with_cache(path, headers = {})
|
61
|
+
return get_without_cache(path, headers) unless is_caching?
|
62
|
+
cache_store.fetch(cache_key(path), cache_options) {get_without_cache(path, headers)}
|
63
|
+
end
|
64
|
+
alias_method_chain :get, :cache
|
83
65
|
|
84
|
-
|
85
|
-
|
66
|
+
def put_with_cache(path, body = '', headers = {})
|
67
|
+
cache_store.delete(cache_key(path))
|
68
|
+
put_without_cache(path, body, headers)
|
69
|
+
end
|
70
|
+
alias_method_chain :put, :cache
|
71
|
+
|
72
|
+
def delete_with_cache(path, headers = {})
|
73
|
+
cache_store.delete(cache_key(path))
|
74
|
+
delete_without_cache(path, headers)
|
75
|
+
end
|
76
|
+
alias_method_chain :delete, :cache
|
77
|
+
|
78
|
+
def cache_key(*args)
|
79
|
+
args.join(':')
|
80
|
+
end
|
86
81
|
end
|
87
|
-
end
|
82
|
+
end
|
88
83
|
end
|
data/lib/highrise/tag.rb
CHANGED
@@ -1,25 +1,12 @@
|
|
1
1
|
module Highrise
|
2
|
-
class Tag < Base
|
3
|
-
@cache = self.cache_store || ActiveSupport::Cache::MemoryStore.new
|
4
|
-
|
2
|
+
class Tag < Base
|
5
3
|
def ==(object)
|
6
4
|
(object.instance_of?(self.class) && object.id == self.id && object.name == self.name)
|
7
5
|
end
|
8
6
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
@cache.fetch(to_key([self.to_s, arg])) {
|
13
|
-
tags = self.find(:all).each{|tag| @cache.write(to_key([self.to_s, tag.name]), tag)}
|
14
|
-
tags.find{|tag| tag.name == arg}
|
15
|
-
}
|
16
|
-
end
|
17
|
-
|
18
|
-
private
|
19
|
-
|
20
|
-
def to_key(*args)
|
21
|
-
args.join('/')
|
22
|
-
end
|
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}
|
23
10
|
end
|
24
11
|
end
|
25
12
|
end
|
data/spec/cachable_spec.rb
CHANGED
@@ -1,66 +1,84 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/spec_helper'
|
2
2
|
|
3
|
-
|
3
|
+
class CachedResource < ActiveResource::Base
|
4
|
+
include ::Cachable
|
5
|
+
end
|
6
|
+
|
7
|
+
describe CachedResource, "class configuration" do
|
4
8
|
before(:each) do
|
5
|
-
|
9
|
+
CachedResource.site = 'http://example.com.i:3000'
|
6
10
|
end
|
7
11
|
|
8
12
|
it "should tell us if caching is active" do
|
9
|
-
|
10
|
-
|
13
|
+
CachedResource.connection.cache_store = ActiveSupport::Cache.lookup_store :memory_store
|
14
|
+
CachedResource.connection.is_caching?.should == true
|
11
15
|
end
|
12
16
|
|
13
17
|
it "should tell us if caching is not active" do
|
14
|
-
|
15
|
-
|
18
|
+
CachedResource.connection.cache_store = nil
|
19
|
+
CachedResource.connection.is_caching?.should == false
|
16
20
|
end
|
17
21
|
end
|
18
22
|
|
19
|
-
describe
|
23
|
+
describe CachedResource do
|
20
24
|
before(:all) do
|
21
|
-
|
22
|
-
|
25
|
+
CachedResource.site = 'http://example.com.i:3000'
|
26
|
+
CachedResource.connection.cache_store = ActiveSupport::Cache.lookup_store :memory_store
|
23
27
|
end
|
24
28
|
|
25
29
|
after(:all) do
|
26
|
-
|
30
|
+
CachedResource.connection.cache_store = :none
|
27
31
|
end
|
28
32
|
|
29
33
|
before(:each) do
|
30
|
-
@thing =
|
34
|
+
@thing = CachedResource.new(:id => 1)
|
31
35
|
@key = :key
|
32
|
-
|
36
|
+
CachedResource.connection.stub!(:cache_key).and_return(@key)
|
33
37
|
end
|
34
38
|
|
35
39
|
context "when a cached response is available" do
|
36
40
|
before(:each) do
|
37
|
-
|
41
|
+
CachedResource.connection.cache_store.write(@key, @thing.attributes)
|
38
42
|
end
|
39
43
|
|
40
44
|
it "should NOT make a request to the RESTful server" do
|
41
|
-
|
42
|
-
|
45
|
+
CachedResource.connection.should_not_receive(:get_without_cache)
|
46
|
+
CachedResource.find(1)
|
43
47
|
end
|
44
48
|
|
45
49
|
it "should read from the cache" do
|
46
|
-
|
50
|
+
CachedResource.find(1).should == @thing
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should delete from the cache when an object is DELETEd" do
|
54
|
+
CachedResource.connection.should_receive(:delete_without_cache)
|
55
|
+
CachedResource.delete(1)
|
56
|
+
CachedResource.connection.cache_store.read(@key).should == nil
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should delete from the cache when an object is modified" do
|
60
|
+
thing = CachedResource.find(1)
|
61
|
+
thing.stub(:load_attributes_from_response).and_return(@thing.attributes)
|
62
|
+
CachedResource.connection.should_receive(:put_without_cache)
|
63
|
+
thing.save
|
64
|
+
CachedResource.connection.cache_store.read(@key).should == nil
|
47
65
|
end
|
48
66
|
end
|
49
67
|
|
50
68
|
context "when a cached response is NOT available" do
|
51
69
|
before(:each) do
|
52
|
-
|
70
|
+
CachedResource.connection.cache_store.delete(@key)
|
53
71
|
end
|
54
72
|
|
55
|
-
it "SHOULD perform an
|
56
|
-
|
57
|
-
|
73
|
+
it "SHOULD perform an ActiveResource request" do
|
74
|
+
CachedResource.connection.should_receive(:get_without_cache).and_return(@thing.attributes)
|
75
|
+
CachedResource.find(1)
|
58
76
|
end
|
59
77
|
|
60
78
|
it "should cache the response using the caching key" do
|
61
|
-
|
62
|
-
|
63
|
-
|
79
|
+
CachedResource.connection.should_receive(:get_without_cache).and_return(@thing.attributes)
|
80
|
+
CachedResource.find(1)
|
81
|
+
CachedResource.connection.cache_store.read(@key).should == @thing.attributes
|
64
82
|
end
|
65
83
|
end
|
66
84
|
end
|
data/spec/highrise/note_spec.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: highrise
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 2
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
version: 2.0.0
|
5
10
|
platform: ruby
|
6
11
|
authors:
|
7
12
|
- "Marcos Tapaj\xC3\xB3s"
|
@@ -10,29 +15,35 @@ autorequire:
|
|
10
15
|
bindir: bin
|
11
16
|
cert_chain: []
|
12
17
|
|
13
|
-
date: 2010-
|
18
|
+
date: 2010-04-23 00:00:00 -03:00
|
14
19
|
default_executable:
|
15
20
|
dependencies:
|
16
21
|
- !ruby/object:Gem::Dependency
|
17
22
|
name: activeresource
|
18
|
-
|
19
|
-
|
20
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
21
25
|
requirements:
|
22
26
|
- - ">="
|
23
27
|
- !ruby/object:Gem::Version
|
28
|
+
segments:
|
29
|
+
- 2
|
30
|
+
- 1
|
24
31
|
version: "2.1"
|
25
|
-
|
32
|
+
type: :runtime
|
33
|
+
version_requirements: *id001
|
26
34
|
- !ruby/object:Gem::Dependency
|
27
35
|
name: activesupport
|
28
|
-
|
29
|
-
|
30
|
-
version_requirements: !ruby/object:Gem::Requirement
|
36
|
+
prerelease: false
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
31
38
|
requirements:
|
32
39
|
- - ">="
|
33
40
|
- !ruby/object:Gem::Version
|
41
|
+
segments:
|
42
|
+
- 2
|
43
|
+
- 1
|
34
44
|
version: "2.1"
|
35
|
-
|
45
|
+
type: :runtime
|
46
|
+
version_requirements: *id002
|
36
47
|
description: "\n\
|
37
48
|
Based on the original API module from DHH, http://developer.37signals.com/highrise/, this\n\
|
38
49
|
gem is a cleaned up, tested version of the same. Contributors have added support for tags \n\
|
@@ -114,18 +125,20 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
114
125
|
requirements:
|
115
126
|
- - ">="
|
116
127
|
- !ruby/object:Gem::Version
|
128
|
+
segments:
|
129
|
+
- 0
|
117
130
|
version: "0"
|
118
|
-
version:
|
119
131
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
120
132
|
requirements:
|
121
133
|
- - ">="
|
122
134
|
- !ruby/object:Gem::Version
|
135
|
+
segments:
|
136
|
+
- 0
|
123
137
|
version: "0"
|
124
|
-
version:
|
125
138
|
requirements: []
|
126
139
|
|
127
140
|
rubyforge_project:
|
128
|
-
rubygems_version: 1.3.
|
141
|
+
rubygems_version: 1.3.6
|
129
142
|
signing_key:
|
130
143
|
specification_version: 3
|
131
144
|
summary: Ruby wrapper around Highrise API
|