prismic.io 1.0.0.rc5 → 1.0.0.rc6

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.
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