buttercms-ruby 1.3.2 → 1.8

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