prismic.io 1.0.0.rc5 → 1.0.0.rc6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ca80b38d048125991d9ddb08ae46e30ff195a315
4
- data.tar.gz: 175dbc5a5df2492651e3eb3794f9bcd0ea5d3117
3
+ metadata.gz: 8f817e26c9531dedb21f23cae69edbcf8f5a1f77
4
+ data.tar.gz: 41cd13bd44d6a052b0e770f138b6d70cf799b21e
5
5
  SHA512:
6
- metadata.gz: 4f1d0d419feeb6cfe59e08c8e1e8b3ce40371407ecfa7d0ded8971f2e943d0588edce93f469d5e1a6d5a66ccec1b7f4ed6aeacc715ac7fdc92797ea54dd2fb1f
7
- data.tar.gz: 24189dbe64510b5023e9ad339bd408910724eff3c034f60c36a6ec0d227994e9c46a973c965cfca1956f33538ba17b22600c579fa94791a28640771b89c70728
6
+ metadata.gz: 4cbfe1c5347987bd16de9c244d4d89c13bf2ea2a79315e3094215ec63a5aa9f2ba20936701e92d6aa7c6cb74291421b958b7bb785aed03845914d19fb0f7c5d8
7
+ data.tar.gz: 63767dc468b7a7f93c1bc8b4b1afcf4bedac8bf839dd4e8480e1f56cbabc1bf04ef999f565be4efaf10d477a114d1a63195cb86ffc48c90712bb20de07dbc689
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- prismic.io (1.0.0.rc5)
4
+ prismic.io (1.0.0.rc6)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -43,6 +43,7 @@ module Prismic
43
43
  # @param [Hash] opts The options
44
44
  # @option opts [String] :access_token (nil) The access_token
45
45
  # @option opts :http_client (DefaultHTTPClient) The HTTP client to use
46
+ # @option opts :cache (nil) The caching object (for instance Prismic::Cache) to use, or false for no caching
46
47
  # @overload api(url, access_token)
47
48
  # Provide the access_token (only)
48
49
  # @param [String] url The URL of the prismic.io repository
@@ -178,26 +179,31 @@ module Prismic
178
179
  self.ref(ref) if ref
179
180
  raise NoRefSetException unless @ref
180
181
 
181
- if form_method == "GET" && form_enctype == "application/x-www-form-urlencoded"
182
- data['ref'] = @ref
183
- data['access_token'] = api.access_token if api.access_token
184
- data.delete_if { |k, v| v.nil? }
182
+ # cache_key is a mix of HTTP URL and HTTP method
183
+ cache_key = form_method+'::'+form_action+'?'+data.map{|k,v|"#{k}=#{v}"}.join('&')
185
184
 
186
- response = api.http_client.get(form_action, data, 'Accept' => 'application/json')
185
+ api.caching(cache_key) {
186
+ if form_method == "GET" && form_enctype == "application/x-www-form-urlencoded"
187
+ data['ref'] = @ref
188
+ data['access_token'] = api.access_token if api.access_token
189
+ data.delete_if { |k, v| v.nil? }
187
190
 
188
- if response.code.to_s == "200"
189
- Prismic::JsonParser.documents_parser(JSON.parse(response.body))
191
+ response = api.http_client.get(form_action, data, 'Accept' => 'application/json')
192
+
193
+ if response.code.to_s == "200"
194
+ Prismic::JsonParser.documents_parser(JSON.parse(response.body))
195
+ else
196
+ body = JSON.parse(response.body) rescue nil
197
+ error = body.is_a?(Hash) ? body['error'] : response.body
198
+ raise AuthenticationException, error if response.code.to_s == "401"
199
+ raise AuthorizationException, error if response.code.to_s == "403"
200
+ raise RefNotFoundException, error if response.code.to_s == "404"
201
+ raise FormSearchException, error
202
+ end
190
203
  else
191
- body = JSON.parse(response.body) rescue nil
192
- error = body.is_a?(Hash) ? body['error'] : response.body
193
- raise AuthenticationException, error if response.code.to_s == "401"
194
- raise AuthorizationException, error if response.code.to_s == "403"
195
- raise RefNotFoundException, error if response.code.to_s == "404"
196
- raise FormSearchException, error
204
+ raise UnsupportedFormKind, "Unsupported kind of form: #{form_method} / #{enctype}"
197
205
  end
198
- else
199
- raise UnsupportedFormKind, "Unsupported kind of form: #{form_method} / #{enctype}"
200
- end
206
+ }
201
207
  end
202
208
 
203
209
  # Specify a parameter for this form
@@ -440,3 +446,4 @@ require 'prismic/api'
440
446
  require 'prismic/form'
441
447
  require 'prismic/fragments'
442
448
  require 'prismic/json_parsers'
449
+ require 'prismic/cache'
@@ -1,11 +1,31 @@
1
1
  # encoding: utf-8
2
+
2
3
  module Prismic
3
4
  class API
5
+ @@cache = nil
4
6
  @@warned_create_search_form = false
5
7
  @@warned_oauth_initiate_url = false
6
8
  @@warned_oauth_check_token = false
7
9
  attr_reader :json, :access_token, :http_client
8
- attr_accessor :refs, :bookmarks, :forms, :tags, :types, :oauth
10
+ attr_accessor :refs, :bookmarks, :forms, :tags, :types, :oauth, :cache
11
+
12
+ # Is the cache enabled on this API object?
13
+ #
14
+ # @return [Boolean]
15
+ def has_cache?
16
+ !!cache
17
+ end
18
+
19
+ # Calls the given block if the provided key is not already cached
20
+ #
21
+ # If the cache is disabled, the block is always called
22
+ #
23
+ # @param key [String] the cache's key to test
24
+ #
25
+ # @return the return of the given block
26
+ def caching(key)
27
+ cache ? cache.get(key){ yield(key) } : yield(key)
28
+ end
9
29
 
10
30
  # Returns the master {Ref reference}
11
31
  # @api
@@ -14,11 +34,12 @@ module Prismic
14
34
  attr_accessor :master
15
35
  alias :master_ref :master
16
36
 
17
- def initialize(json, access_token, http_client)
37
+ def initialize(json, access_token, http_client, cache)
18
38
  @json = json
19
39
  @access_token = access_token
20
40
  @http_client = http_client
21
41
  yield self if block_given?
42
+ @cache = cache
22
43
  self.master = refs.values && refs.values.map { |ref| ref if ref.master? }.compact.first
23
44
  raise BadPrismicResponseError, "No master Ref found" unless master
24
45
  end
@@ -93,15 +114,17 @@ module Prismic
93
114
  def self.start(url, opts={})
94
115
  http_client = opts[:http_client] || Prismic::DefaultHTTPClient
95
116
  access_token = opts[:access_token]
117
+ cache = opts[:cache]
118
+ cache ||= Prismic::DefaultCache unless cache == false
96
119
  resp = get(url, access_token, http_client)
97
120
  json = JSON.load(resp.body)
98
- parse_api_response(json, access_token, http_client)
121
+ parse_api_response(json, access_token, http_client, cache)
99
122
  end
100
123
 
101
- def self.parse_api_response(data, access_token, http_client)
124
+ def self.parse_api_response(data, access_token, http_client, cache)
102
125
  data_forms = data['forms'] || []
103
126
  data_refs = data.fetch('refs'){ raise BadPrismicResponseError, "No refs given" }
104
- new(data, access_token, http_client) {|api|
127
+ new(data, access_token, http_client, cache) {|api|
105
128
  api.bookmarks = data['bookmarks']
106
129
  api.forms = Hash[data_forms.map { |k, form|
107
130
  [k, Form.new(
@@ -0,0 +1,123 @@
1
+ # encoding: utf-8
2
+ module Prismic
3
+ # This is a simple cache class provided with the prismic.io Ruby kit.
4
+ # It is pretty dumb but effective:
5
+ # * everything is stored in memory,
6
+ # * invalidation: not needed for prismic.io documents (they are eternally immutable), but we don't want the cache to expand indefinitely; therefore all cache but the new master ref is cleared when a new master ref gets published.
7
+ #
8
+ # If you need a smarter caching (for instance, caching in files), you can extend this class and replace its methods,
9
+ # and when creating your API object like this for instance: Prismic.api(url, options), pass the name of the class you created
10
+ # as a :cache option.
11
+ # Therefore, to use this simple cache, you can create your API object like this: Prismic.api(url, cache: Prismic::DefaultCache)
12
+ class Cache
13
+
14
+ # Based on http://stackoverflow.com/questions/1933866/efficient-ruby-lru-cache
15
+ # The Hash are sorted, so the age is represented by the key order
16
+
17
+ # Returns the cache object holding the responses to "results" queries (lists of documents).
18
+ # This is a Hash in a Hash: keys in the outer Hash are the refs (so that it's easy to invalidate entire refs at once);
19
+ # keys in the inner Hash are the query strings (URLs) of each query.
20
+ # The object that is stored as a cache_object is what is returned by Prismic::JsonParser::results_parser
21
+ # (so that we don't have to parse anything again, it's stored already parsed).
22
+ #
23
+ # @return [Hash<String,Object>]
24
+ attr_reader :intern
25
+
26
+ # Returns the maximum of keys to store
27
+ #
28
+ # @return [Fixum]
29
+ attr_reader :max_size
30
+
31
+ # @param max_size [Fixnum] (100) The default maximum of keys to store
32
+ def initialize(max_size=100)
33
+ @intern = {}
34
+ @max_size = max_size
35
+ end
36
+
37
+ # Add a cache entry.
38
+ #
39
+ # @param key [String] the key
40
+ # @param value the value to store
41
+ #
42
+ # @return the value
43
+ def store(key, value)
44
+ @intern.delete(key)
45
+ @intern[key] = value
46
+ if @intern.length > @max_size
47
+ @intern.delete(@intern.first[0])
48
+ end
49
+ value
50
+ end
51
+ alias :[]= :store
52
+
53
+ # Update the maximun number of keys to store
54
+ #
55
+ # Prune the cache old oldest keys if the new max_size is older than the keys
56
+ # number.
57
+ #
58
+ # @param max_size [Fixnum] the new maximun number of keys to store
59
+ def max_size=(max_size)
60
+ raise ArgumentError.new(:max_size) if max_size < 1
61
+ @max_size = max_size
62
+ if @max_size < @intern.size
63
+ @intern.keys[0 .. (@max_size-@intern.size)].each { |k|
64
+ @intern.delete(k)
65
+ }
66
+ end
67
+ end
68
+
69
+ # Get a cache entry
70
+ #
71
+ # A block can be provided: it will be used to compute (and store) the value
72
+ # if the key is missing.
73
+ #
74
+ # @param key [String] the key to fetch
75
+ #
76
+ # @return [Object] the cache object as was stored
77
+ def get(key)
78
+ found = true
79
+ value = @intern.delete(key){ found = false }
80
+ if found
81
+ @intern[key] = value
82
+ else
83
+ self[key] = yield(key)
84
+ end
85
+ end
86
+ alias :[] :get
87
+
88
+ # Checks if a cache entry exists
89
+ #
90
+ # @param key [String] the key to test
91
+ #
92
+ # @return [Boolean]
93
+ def include?(key)
94
+ @intern.include?(key)
95
+ end
96
+
97
+ # Invalidates all the cache
98
+ def invalidate_all!
99
+ @intern.clear
100
+ end
101
+ alias :clear! :invalidate_all!
102
+
103
+ # Expose a Hash of the keys of both Hashes. The keys of this Hash is the ref_ids, the values are arrays of cache_keys.
104
+ # This is only for displaying purposes, if you want to check out what's stored in your cache without checking out the
105
+ # quite verbose cache_objects.
106
+ #
107
+ # @return [Array<String>]
108
+ def keys
109
+ @intern.keys
110
+ end
111
+
112
+ # Return the number of stored keys
113
+ #
114
+ # @return [Fixum]
115
+ def size
116
+ @intern.size
117
+ end
118
+ alias :length :size
119
+
120
+ end
121
+
122
+ DefaultCache = Cache.new
123
+ end
@@ -148,14 +148,13 @@ module Prismic
148
148
  Prismic::Fragments::StructuredText::Block::Image.new(view)
149
149
  when 'embed'
150
150
  boembed = block['oembed']
151
- embed = Prismic::Fragments::Embed.new(
151
+ Prismic::Fragments::Embed.new(
152
152
  boembed['type'],
153
153
  boembed['provider_name'],
154
154
  boembed['provider_url'],
155
155
  boembed['html'],
156
156
  boembed
157
157
  )
158
- Prismic::Fragments::StructuredText::Block::Image.new(embed)
159
158
  else
160
159
  puts "Unknown bloc type: #{block['type']}"
161
160
  end
@@ -1,6 +1,6 @@
1
1
  # encoding: utf-8
2
2
  module Prismic
3
3
 
4
- VERSION = "1.0.0.rc5"
4
+ VERSION = "1.0.0.rc6"
5
5
 
6
6
  end
@@ -0,0 +1,73 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+
4
+ describe "Cache's" do
5
+
6
+ describe 'on/off switch' do
7
+ before do
8
+ @api = Prismic.api("https://lesbonneschoses.prismic.io/api", cache: Prismic::Cache.new(3))
9
+ @cache = @api.cache
10
+ @master_ref = @api.master_ref
11
+ end
12
+
13
+ it "is properly on" do
14
+ @api.has_cache?.should == true
15
+ @cache.is_a?(Prismic::Cache).should == true
16
+ end
17
+
18
+ it "is properly off" do
19
+ api = Prismic.api("https://lesbonneschoses.prismic.io/api", cache: false)
20
+ api.has_cache?.should == false
21
+ end
22
+
23
+ describe 'storage and retrieval' do
24
+ it 'stores properly' do
25
+ @cache.intern.size.should == 0
26
+ @api.form('products').submit(@master_ref)
27
+ @cache.intern.size.should == 1
28
+ end
29
+
30
+ it 'does not cache /api' do
31
+ # do not call anything, so the only request made is the /api one
32
+ @cache.intern.size.should == 0
33
+ end
34
+ end
35
+
36
+ describe 'cache storage' do
37
+ before do
38
+ # max_size = 3
39
+ @cache['fake_key1'] = 1
40
+ @cache['fake_key2'] = 2
41
+ @cache['fake_key3'] = 3
42
+ end
43
+ it 'contains some keys' do
44
+ @cache.include?('fake_key1').should be_true
45
+ end
46
+ it 'contains all keys' do
47
+ @cache.intern.size.should == 3
48
+ end
49
+ it 'can return all keys' do
50
+ @cache.keys.should == %w(fake_key1 fake_key2 fake_key3)
51
+ end
52
+ it 'deletes oldest key when updating max_size' do
53
+ @cache.max_size = 1
54
+ @cache.size.should == 1
55
+ @cache.include?('fake_key1').should be_false
56
+ @cache.include?('fake_key2').should be_false
57
+ @cache.include?('fake_key3').should be_true
58
+ end
59
+ it 'deletes oldest key when adding new one (at max_size)' do
60
+ @cache['fake_key4'] = 4
61
+ @cache.max_size = 3
62
+ @cache.size.should == 3
63
+ @cache.include?('fake_key1').should be_false
64
+ end
65
+ it 'keeps readed keys alive' do
66
+ @cache['fake_key1']
67
+ @cache['fake_key4'] = 4
68
+ @cache.include?('fake_key1').should be_true
69
+ @cache.include?('fake_key2').should be_false
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,18 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+
4
+ describe 'micro' do
5
+ before do
6
+ @api = Prismic.api("https://micro.prismic.io/api", nil)
7
+ @master_ref = @api.master_ref
8
+ @link_resolver = Prismic.link_resolver("master"){|doc_link| "http://localhost/#{doc_link.id}" }
9
+ end
10
+
11
+ describe 'embed block in structured text fragments' do
12
+ it 'is of the right Embed object, and serializes well' do
13
+ fragment = @api.form("everything").query(%([[:d = at(document.id, "UrjI1gEAALOCeO5i")]])).submit(@master_ref)[0]['article.body']
14
+ fragment.blocks[4].is_a?(Prismic::Fragments::Embed).should == true
15
+ fragment.as_html(@link_resolver).gsub(/[\n\r]+/, '').gsub(/ +/, ' ').gsub(/&#39;/, "'").should == %(<h2>The meta-micro mailing-list</h2><p>This is where you go to give feedback, and discuss the future of micro. <a href="https://groups.google.com/forum/?hl=en#!forum/micro-meta-framework">Subscribe to the list now</a>!</p><h2>The micro GitHub repository</h2><p>This is where you get truly active, by forking the project's source code, and making it better. Please always feel free to send us pull requests.</p> <div data-oembed="" data-oembed-type="link" data-oembed-provider="object"><div data-type="object"><a href="https://github.com/rudyrigot/meta-micro"><h1>rudyrigot/meta-micro</h1><img src="https://avatars2.githubusercontent.com/u/552279?s=400"><p>The meta-micro-framework you simply need</p></a></div></div><h2>Report bugs on micro</h2><p>If you think micro isn't working properly in one of its features, <a href="https://github.com/rudyrigot/meta-micro/issues">open a new issue in the micro GitHub repository</a>.</p><h2>Ask for help</h2><p>Feel free to ask a new question <a href="http://stackoverflow.com/questions/tagged/meta-micro">on StackOverflow</a>.</p>)
16
+ end
17
+ end
18
+ end
@@ -5,7 +5,7 @@ describe 'Api' do
5
5
  before do
6
6
  json_representation = '{"foo": "bar"}'
7
7
  @oauth_initiate_url = "https://lesbonneschoses.prismic.io/auth"
8
- @api = Prismic::API.new(json_representation, nil, Prismic::DefaultHTTPClient){|api|
8
+ @api = Prismic::API.new(json_representation, nil, Prismic::DefaultHTTPClient, false){|api|
9
9
  api.bookmarks = {}
10
10
  api.tags = {}
11
11
  api.types = {}
@@ -111,18 +111,18 @@ describe 'Api' do
111
111
  before do
112
112
  @data = File.read("#{File.dirname(__FILE__)}/responses_mocks/api.json")
113
113
  @json = JSON.parse(@data)
114
- @parsed = Prismic::API.parse_api_response(@json, nil, Prismic::DefaultHTTPClient)
114
+ @parsed = Prismic::API.parse_api_response(@json, nil, Prismic::DefaultHTTPClient, false)
115
115
  end
116
116
 
117
117
  it "does not allow to be created without master Ref" do
118
118
  expect {
119
- Prismic::API.parse_api_response({"refs" => []}, nil, Prismic::DefaultHTTPClient)
119
+ Prismic::API.parse_api_response({"refs" => []}, nil, Prismic::DefaultHTTPClient, false)
120
120
  }.to raise_error(Prismic::API::BadPrismicResponseError, "No master Ref found")
121
121
  end
122
122
 
123
123
  it "does not allow to be created without any Ref" do
124
124
  expect {
125
- Prismic::API.parse_api_response({}, nil, Prismic::DefaultHTTPClient)
125
+ Prismic::API.parse_api_response({}, nil, Prismic::DefaultHTTPClient, false)
126
126
  }.to raise_error(Prismic::API::BadPrismicResponseError, "No refs given")
127
127
  end
128
128
 
@@ -259,11 +259,11 @@ describe 'LinkResolver' do
259
259
  '/'+doc.link_type+'/'+doc.id+'/'+doc.slug
260
260
  end
261
261
  end
262
-
262
+
263
263
  it "builds the right URL from a DocumentLink" do
264
264
  @link_resolver.link_to(@doc_link).should == '/blog-post/id/my-slug'
265
265
  end
266
-
266
+
267
267
  it "builds the right URL from a Document" do
268
268
  @link_resolver.link_to(@document).should == '/blog-post/id/my-slug'
269
269
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: prismic.io
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.rc5
4
+ version: 1.0.0.rc6
5
5
  platform: ruby
6
6
  authors:
7
7
  - "Étienne Vallette d'Osia"
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-03-04 00:00:00.000000000 Z
12
+ date: 2014-04-11 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -82,6 +82,7 @@ files:
82
82
  - Rakefile
83
83
  - lib/prismic.rb
84
84
  - lib/prismic/api.rb
85
+ - lib/prismic/cache.rb
85
86
  - lib/prismic/form.rb
86
87
  - lib/prismic/fragments.rb
87
88
  - lib/prismic/fragments/color.rb
@@ -99,9 +100,11 @@ files:
99
100
  - lib/prismic/json_parsers.rb
100
101
  - lib/prismic/version.rb
101
102
  - prismic.gemspec
103
+ - spec/cache_spec.rb
102
104
  - spec/fragments_spec.rb
103
105
  - spec/json_parsers_spec.rb
104
106
  - spec/lesbonneschoses_spec.rb
107
+ - spec/micro_spec.rb
105
108
  - spec/oauth_spec.rb
106
109
  - spec/prismic_spec.rb
107
110
  - spec/responses_mocks/api.json
@@ -138,9 +141,11 @@ signing_key:
138
141
  specification_version: 4
139
142
  summary: Prismic.io development kit
140
143
  test_files:
144
+ - spec/cache_spec.rb
141
145
  - spec/fragments_spec.rb
142
146
  - spec/json_parsers_spec.rb
143
147
  - spec/lesbonneschoses_spec.rb
148
+ - spec/micro_spec.rb
144
149
  - spec/oauth_spec.rb
145
150
  - spec/prismic_spec.rb
146
151
  - spec/responses_mocks/api.json