buttercms-ruby 1.3.2 → 1.8

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
- SHA1:
3
- metadata.gz: c7b4c68f74294cbca04ea1d4c68fa40f241a5f92
4
- data.tar.gz: 124e11b182d91dc136042d7a2ae35a09e4e19d2c
2
+ SHA256:
3
+ metadata.gz: 2a4629771fdc42b53b03a97bb2488e52cebcaa99e08812927fdb3e9a51ab9bd4
4
+ data.tar.gz: 9b7044c488d00e7a800233f36b167cb880f48931d27abfac68c8c699174cf314
5
5
  SHA512:
6
- metadata.gz: e4eb9a5fab1a68b855786b401a5870deb6d962d1b00bca58b2cfa1e44d975b5d5721361944c8192597c5b5866964f166411d46c38e4be88e4c460a3682c619fe
7
- data.tar.gz: 8560d77aee2ad9615c0f6ec985a9badb83c6cf95e00ff35fac70289bf6421e89919670558f8e31351c4fc4561c56249755e49753cc6259e724f98857aa1c9395
6
+ metadata.gz: 3018b0ab7b461986646e43733bf769ff3fd06a868fe7eef970b623c6558f8d689903bf144889572cf6c8a6bd23a3d6f63dba6135947c54d09ab1650eba43b865
7
+ data.tar.gz: aee9e833f1f9422e5609b8b16f273fd5db5b6d188b25b3502e8831e8a572c438a1ad03445103138d77907bcad98f4e51da3cd92dae6dec178cbad39b4656c43e
data/.gitignore CHANGED
@@ -19,4 +19,5 @@ tmp
19
19
  .ruby-version
20
20
  .rvmrc
21
21
  *.rdb
22
- *.store
22
+ *.store
23
+ test.rb
data/README.md CHANGED
@@ -26,30 +26,42 @@ To setup your project, follow these steps:
26
26
 
27
27
  # Set read timeout (Default is 5.0)
28
28
  # ButterCMS::read_timeout = 5.0
29
+
30
+ # Set open timeout (Default is 2.0)
31
+ # ButterCMS::open_timeout = 2.0
29
32
  ```
30
33
 
31
34
  ## Pages
32
35
 
36
+ https://buttercms.com/docs/api/?ruby#pages
37
+
38
+
33
39
  ```ruby
34
- params = {foo: 'bar'} # optional
40
+ params = {page: 1, page_size: 10, locale: 'en', preview: 1, 'fields.headline': 'foo bar', levels: 2} # optional
35
41
  pages = ButterCMS::Page.list('news', params)
36
42
  page = ButterCMS::Page.get('news', 'hello-world', params)
37
43
  ```
38
44
 
39
- ## Content Fields
45
+ ## Collections
46
+
47
+ https://buttercms.com/docs/api/?ruby#retrieve-a-collection
40
48
 
41
49
  ```ruby
42
- ButterCMS::Content.fetch(['homepage_headline'])
50
+ # list each instance of a given collection with meta data for fetching the next page.
51
+ params = { page: 1, page_size: 10, locale: 'en', preview: 1, 'fields.headline': 'foo bar', levels: 2 } # optional
52
+ ButterCMS::Content.list('collection1', params)
43
53
 
44
- # Localization
45
- ButterCMS::Content.fetch(['homepage_headline'], locale: 'es')
54
+ # list instances for multiple collections, this will not return meta data for pagination control.
55
+ ButterCMS::Content.fetch(['collection1', 'collection2'], params)
46
56
 
47
- # Test mode can be used to setup a staging website for previewing Content Fields or for testing content during local development. To fetch content from test mode add the following configuration:
57
+ # Test mode can be used to setup a staging website for previewing Collections or for testing content during local development. To fetch content from test mode add the following configuration:
48
58
  ButterCMS::test_mode = true
49
59
  ```
50
60
 
51
61
  ## Blog Engine
52
62
 
63
+ https://buttercms.com/docs/api/?ruby#blog-engine
64
+
53
65
  ```ruby
54
66
  posts = ButterCMS::Post.all({:page => 1, :page_size => 10})
55
67
  puts posts.first.title
@@ -61,6 +73,39 @@ puts posts.first.title
61
73
  post = ButterCMS::Post.find("post-slug")
62
74
  puts post.title
63
75
 
76
+ # Create a Post.
77
+ ButterCMS::write_api_token = "YourWriteToken"
78
+ ButterCMS::Post.create({
79
+ slug: 'blog-slug',
80
+ title: 'blog-title'
81
+ })
82
+
83
+ # Update a Post
84
+ ButterCMS::Post.update('blog-slug', {
85
+ title: 'blog-title-v2'
86
+ })
87
+
88
+ # Create a page
89
+ ButterCMS::Page.create({
90
+ slug: 'page-slug',
91
+ title: 'page-title',
92
+ status: 'published',
93
+ "page-type": 'page_type',
94
+ fields: {
95
+ meta_title: 'test meta title'
96
+ }
97
+ })
98
+
99
+ # update a Page
100
+ ButterCMS::Page.update('page-slug-2', {
101
+ status: 'published',
102
+ fields: {
103
+ meta_title: 'test meta title'
104
+ }
105
+ })
106
+
107
+
108
+
64
109
  author = ButterCMS::Author.find("author-slug")
65
110
  puts author.first_name
66
111
 
@@ -93,3 +138,5 @@ ButterCMS::logger = MyLogger.new
93
138
  ### Other
94
139
 
95
140
  View Ruby [Blog engine](https://buttercms.com/ruby-blog-engine/) and [Full CMS](https://buttercms.com/ruby-cms/) for other examples of using ButterCMS with Ruby.
141
+
142
+ ### Development
@@ -27,8 +27,10 @@ module ButterCMS
27
27
 
28
28
  class << self
29
29
  attr_accessor :api_token
30
+ attr_accessor :write_api_token
30
31
  attr_accessor :test_mode
31
32
  attr_accessor :read_timeout
33
+ attr_accessor :open_timeout
32
34
  attr_reader :data_store
33
35
  attr_writer :logger
34
36
  end
@@ -71,13 +73,6 @@ module ButterCMS
71
73
 
72
74
  path = "#{@api_url.path}#{URI.encode(path)}?#{URI.encode_www_form(query)}"
73
75
 
74
- http_options = {
75
- open_timeout: 2.0,
76
- read_timeout: read_timeout || 5.0,
77
- ssl_timeout: 2.0,
78
- use_ssl: @api_url.scheme == "https",
79
- }
80
-
81
76
  response =
82
77
  Net::HTTP.start(@api_url.host, @api_url.port, http_options) do |http|
83
78
  request = Net::HTTP::Get.new(path)
@@ -128,4 +123,60 @@ module ButterCMS
128
123
 
129
124
  return JSON.parse(result)
130
125
  end
126
+
127
+ def self.write_request(path, options = {})
128
+ raise ArgumentError.new "Please set your write API token" unless write_api_token
129
+ result = write_api_request(path, options)
130
+
131
+ return JSON.parse(result)
132
+ end
133
+
134
+ def self.write_api_request(path, options = {})
135
+ query = options.dup
136
+ token_for_request = query.delete(:auth_token) || write_api_token
137
+
138
+ path = "#{@api_url.path}#{URI.encode(path)}"
139
+
140
+ response =
141
+ Net::HTTP.start(@api_url.host, @api_url.port, http_options) do |http|
142
+ write_type = query.delete(:method) || "Post"
143
+ request_type = "Net::HTTP::#{write_type}".constantize
144
+ request = request_type.new(path)
145
+ request["User-Agent"] = "ButterCMS/Ruby #{ButterCMS::VERSION}"
146
+ request["Accept"] = "application/json"
147
+ request["Content-Type"] = "application/json"
148
+ request["Authorization"] = "Token #{token_for_request}"
149
+ request.body = query.except(:auth_token).to_json
150
+
151
+ http.request(request)
152
+ end
153
+
154
+ case response
155
+ when Net::HTTPNotFound
156
+ raise ::ButterCMS::NotFound, JSON.parse(response.body)["detail"]
157
+ when Net::HTTPBadRequest
158
+ parsed_body = JSON.parse(response.body)
159
+ errors = if parsed_body.is_a?(Array)
160
+ parsed_body.join(' ')
161
+ else
162
+ parsed_body.map do |k, v|
163
+ "#{k}: #{v}"
164
+ end.join(" ")
165
+ end
166
+ raise ::ButterCMS::BadRequest, errors
167
+ end
168
+
169
+ response.body
170
+ end
171
+
172
+ private
173
+
174
+ def self.http_options
175
+ {
176
+ open_timeout: open_timeout || 2.0,
177
+ read_timeout: read_timeout || 5.0,
178
+ ssl_timeout: 2.0,
179
+ use_ssl: @api_url.scheme == "https",
180
+ }
181
+ end
131
182
  end
@@ -2,6 +2,7 @@ module ButterCMS
2
2
  class ButterCollection
3
3
  include Enumerable
4
4
 
5
+ attr_reader :items
5
6
  attr_reader :meta
6
7
 
7
8
  def initialize(klass, json)
@@ -18,4 +19,4 @@ module ButterCMS
18
19
  end
19
20
  end
20
21
  end
21
- end
22
+ end
@@ -7,12 +7,19 @@ module ButterCMS
7
7
  @data = HashToObject.convert(json["data"])
8
8
  @meta = HashToObject.convert(json["meta"]) if json["meta"]
9
9
 
10
- if json["data"].is_a?(Hash)
11
- json["data"].each do |key, value|
12
- instance_variable_set("@#{key}", @data.send(key))
13
- self.class.send(:attr_reader, key)
14
- end
15
- end
10
+ define_attribute_methods(@data)
11
+ end
12
+
13
+ def marshal_dump
14
+ { json: @json, data: @data, meta: @meta }
15
+ end
16
+
17
+ def marshal_load(dump)
18
+ @json = dump[:json]
19
+ @data = dump[:data]
20
+ @meta = dump[:meta]
21
+
22
+ define_attribute_methods(@data)
16
23
  end
17
24
 
18
25
  def inspect
@@ -26,6 +33,12 @@ module ButterCMS
26
33
  resource_path + (id ? "#{id}/" : '')
27
34
  end
28
35
 
36
+ def self.patch_endpoint(id)
37
+ # Append trailing slash when id is added to path because
38
+ # API expects all endpoints to include trailing slashes
39
+ resource_path + "*/#{id}/"
40
+ end
41
+
29
42
  def self.resource_path
30
43
  raise "resource_path must be set"
31
44
  end
@@ -42,6 +55,25 @@ module ButterCMS
42
55
  self.create_object(response)
43
56
  end
44
57
 
58
+ def self.create(options = {})
59
+ options[:method] = 'Post'
60
+ response = ButterCMS.write_request(self.endpoint, options)
61
+
62
+ self.create_object(response)
63
+ end
64
+
65
+ def self.update(id, options = {})
66
+ options[:method] = 'Patch'
67
+ _endpoint = if resource_path.include?("/pages/")
68
+ self.patch_endpoint(id)
69
+ else
70
+ self.endpoint(id)
71
+ end
72
+ response = ButterCMS.write_request(_endpoint, options)
73
+
74
+ self.create_object(response)
75
+ end
76
+
45
77
  private
46
78
 
47
79
  def self.create_collection(response)
@@ -51,5 +83,14 @@ module ButterCMS
51
83
  def self.create_object(response)
52
84
  self.new(response)
53
85
  end
86
+
87
+ def define_attribute_methods(methods)
88
+ return unless methods.respond_to?(:each_pair)
89
+
90
+ methods.each_pair do |key, value|
91
+ instance_variable_set("@#{key}", value)
92
+ self.class.send(:attr_reader, key)
93
+ end
94
+ end
54
95
  end
55
96
  end
@@ -1,22 +1,19 @@
1
1
  module ButterCMS
2
- class Content
3
- attr_reader :data
4
-
5
- def initialize(json)
6
- @json = json
7
- @data = HashToObject.convert(json["data"])
8
- end
9
-
10
- def inspect
11
- id_string = (self.respond_to?(:id) && !self.id.nil?) ? " id=#{self.id}" : ""
12
- "#<#{self.class}:0x#{self.object_id.to_s(16)}#{id_string}> JSON: " + JSON.pretty_generate(@json)
2
+ class Content < ButterResource
3
+ def self.resource_path
4
+ "/content/"
13
5
  end
14
6
 
15
- def self.fetch(keys = [], options = {})
16
- params = {keys: keys.join(',')}.merge(options)
17
-
18
- response = ButterCMS.request("/content/", params)
7
+ def self.list(collection_slug, options = {})
8
+ response = ButterCMS.request(self.endpoint(collection_slug), options)
19
9
 
10
+ self.create_collection(response)
11
+ end
12
+
13
+ def self.fetch(collection_slugs, options = {})
14
+ params = { keys: collection_slugs.join(',') }.merge(options)
15
+ response = ButterCMS.request(self.resource_path, params)
16
+
20
17
  self.new(response)
21
18
  end
22
19
  end
@@ -6,4 +6,7 @@ module ButterCMS
6
6
  # NotFound is raised when a resource cannot be found
7
7
  class NotFound < Error
8
8
  end
9
+
10
+ class BadRequest < Error
11
+ end
9
12
  end
@@ -1,3 +1,3 @@
1
1
  module ButterCMS
2
- VERSION = '1.3.2'
3
- end
2
+ VERSION = '1.8'
3
+ end
@@ -0,0 +1,10 @@
1
+ require 'bundler/inline'
2
+
3
+ gemfile do
4
+ source 'https://rubygems.org'
5
+ gem 'buttercms-ruby', :path => '../buttercms-ruby'
6
+ end
7
+
8
+ # start a REPL session
9
+ ButterCMS::api_token = "" # add your dev token here
10
+ binding.irb
@@ -4,6 +4,12 @@ describe ButterCMS::ButterCollection do
4
4
  let(:json) { {"data" => ["foo"], "meta" => {}} }
5
5
  let(:klass) { double('klass', :new => 'bar') }
6
6
 
7
+ it 'implements #items' do
8
+ collection = ButterCMS::ButterCollection.new(klass, json)
9
+
10
+ expect(collection.items).to match_array(["bar"])
11
+ end
12
+
7
13
  it 'implements #meta' do
8
14
  collection = ButterCMS::ButterCollection.new(klass, json)
9
15
 
@@ -15,4 +21,20 @@ describe ButterCMS::ButterCollection do
15
21
 
16
22
  expect(collection.count).to eq 1
17
23
  end
18
- end
24
+
25
+ # Marshal.load (used by Rails for caching) was not restoring the ButterResource's dynamic methods
26
+ # See https://github.com/ButterCMS/buttercms-ruby/issues/13
27
+ describe 'marshal load' do
28
+ subject { described_class.new(ButterCMS::ButterResource, 'data' => [{ 'name' => 'Test Name', 'description' => 'Test Description' }]) }
29
+
30
+ it 'restores the ButterResource dynamic methods' do
31
+ collection = Marshal.load(Marshal.dump(subject))
32
+ resource = collection.first
33
+
34
+ aggregate_failures do
35
+ expect(resource.name).to eq('Test Name')
36
+ expect(resource.description).to eq('Test Description')
37
+ end
38
+ end
39
+ end
40
+ end
@@ -8,10 +8,21 @@ describe ButterCMS::ButterResource do
8
8
  allow(ButterCMS::ButterResource).to receive(:resource_path).and_return('')
9
9
  end
10
10
 
11
+ describe 'auto-generated methods' do
12
+ let(:resource) { described_class.new('data' => { 'name' => 'Test Name', 'description' => 'Test Description' }) }
13
+
14
+ it 'creates attribute reader methods for data pairs' do
15
+ aggregate_failures do
16
+ expect(resource.name).to eq('Test Name')
17
+ expect(resource.description).to eq('Test Description')
18
+ end
19
+ end
20
+ end
21
+
11
22
  describe '.all' do
12
23
 
13
24
  it 'should make a request with the correct endpoint' do
14
- expect(ButterCMS).to receive(:request).with('/', {})
25
+ expect(ButterCMS).to receive(:request).with('', {})
15
26
  ButterCMS::ButterResource.all()
16
27
  end
17
28
 
@@ -24,7 +35,7 @@ describe ButterCMS::ButterResource do
24
35
 
25
36
  describe '.find' do
26
37
  it 'should make a request with the correct endpoint' do
27
- expect(ButterCMS).to receive(:request).with('/1', {})
38
+ expect(ButterCMS).to receive(:request).with('1/', {})
28
39
  ButterCMS::ButterResource.find(1)
29
40
  end
30
41
 
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+
3
+ describe ButterCMS::Content do
4
+ before do
5
+ allow(ButterCMS).to receive(:token).and_return('test123')
6
+ allow(ButterCMS).to receive(:request).and_return({
7
+ "meta"=>{
8
+ "next_page"=>2,
9
+ "previous_page"=>nil,
10
+ "count"=>2
11
+ },
12
+ "data"=>{
13
+ "author"=>[
14
+ { "name"=>"Charles Dickens"},
15
+ { "name"=>"J.K. Rowling"}
16
+ ]
17
+ }
18
+ })
19
+
20
+ @response = ButterCMS::Content.list('slug', {
21
+ page: 1,
22
+ page_size: 2
23
+ })
24
+ end
25
+
26
+ it "has meta and collection info" do
27
+ expect(@response.meta.next_page).to eq(2)
28
+ expect(@response.to_a.first.data.first).to eq('author')
29
+ expect(@response.to_a.first.data.last.first).to have_attributes(
30
+ name: "Charles Dickens"
31
+ )
32
+ end
33
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: buttercms-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.2
4
+ version: '1.8'
5
5
  platform: ruby
6
6
  authors:
7
7
  - ButterCMS
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-06-20 00:00:00.000000000 Z
11
+ date: 2020-07-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -52,7 +52,6 @@ files:
52
52
  - LICENSE
53
53
  - README.md
54
54
  - Rakefile
55
- - VERSION
56
55
  - buttercms-ruby.gemspec
57
56
  - lib/buttercms-ruby.rb
58
57
  - lib/buttercms/author.rb
@@ -69,10 +68,12 @@ files:
69
68
  - lib/buttercms/post.rb
70
69
  - lib/buttercms/tag.rb
71
70
  - lib/buttercms/version.rb
71
+ - lib/console.rb
72
72
  - lib/core_ext/ostruct.rb
73
73
  - spec/lib/butter-ruby_spec.rb
74
74
  - spec/lib/buttercms/butter_collection_spec.rb
75
75
  - spec/lib/buttercms/butter_resource_spec.rb
76
+ - spec/lib/buttercms/content_spec.rb
76
77
  - spec/lib/buttercms/hash_to_object_spec.rb
77
78
  - spec/spec_helper.rb
78
79
  homepage: https://buttercms.com/docs
@@ -94,8 +95,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
94
95
  - !ruby/object:Gem::Version
95
96
  version: '0'
96
97
  requirements: []
97
- rubyforge_project:
98
- rubygems_version: 2.6.12
98
+ rubygems_version: 3.0.3
99
99
  signing_key:
100
100
  specification_version: 4
101
101
  summary: A simple Ruby client for the buttercms.com REST API
@@ -103,5 +103,6 @@ test_files:
103
103
  - spec/lib/butter-ruby_spec.rb
104
104
  - spec/lib/buttercms/butter_collection_spec.rb
105
105
  - spec/lib/buttercms/butter_resource_spec.rb
106
+ - spec/lib/buttercms/content_spec.rb
106
107
  - spec/lib/buttercms/hash_to_object_spec.rb
107
108
  - spec/spec_helper.rb
data/VERSION DELETED
@@ -1 +0,0 @@
1
- 1.3.2