highrise 1.2.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|