buttercms / buttercms-ruby Goto Github PK
View Code? Open in Web Editor NEWRuby API client for ButterCMS (https://buttercms.com)
License: Other
Ruby API client for ButterCMS (https://buttercms.com)
License: Other
Hey ๐
The most recent update upgrades the lib from 1.9 to 2.0. As far as I can see, the only thing that has changed iscompatibilityy with Ruby 3. Semantic versioning, which most open source libraries use, would suggest that a change from 1.9 to 2.0 involves large, breaking changes.
If for whatever reason you can't move to semver, please add a changelog so that customers like me don't need to start going through the code to try and work out what's changed between versions.
When I run the code below, I would expect to get a list of pages back, instead I get this error:
p ButterCMS::Page.all('*')
Traceback (most recent call last):
2: from (irb):11
1: from (irb):12:in `rescue in irb_binding'
TypeError (no implicit conversion of Symbol into Integer)
This behavior changed in 1.1.2 with the switch to HTTParty. In version 1.1.1 trying to find an object that does not exist would raise a RestClient::ResourceNotFound
exception, which was great because it was easy to catch inside of a Rails controller.
As of 1.1.2+ you get an invalid object.
ButterCMS::Post.find("invalid_id")
# => raises RestClient::ResourceNotFound
ButterCMS::Post.find("invalid_id")
=> #<ButterCMS::Post:0x3fec90b98af4> JSON: {
"detail": "Not found."
}
Hello ButterCMS team,
I believe we discovered u bug regarding to find
method. It is present in 2.0
and not present in 1.7
. I didn't test version 1.8
and 1.9
specifically but I'm pretty confident that it was introduced in 2.0
- more on that later.
When you run
ButterCMS::Post.find('#some-slug')
API client responds with
#<ButterCMS::Post:0x2af2bcb12c5c> JSON: {
"detail": "Incorrect authentication credentials."
}
I expected that ButterCMS::NotFound (Not found.)
will be raised, same as for non-existent slugs that do not include a #
I'm pretty sure I pinpointed the issue to this line.
Previously URI.encode_www_form_component
was called, and it would encode the #
in URL safe manner:
URI.encode_www_form_component('#ddff')
=> "%23ddff"
However it is not called any more, so the URL contains a raw #
. When the request is made the HTTP client thinks this is beginning of the fragment part of the URL. This leads it to ignore the query part of the URL which includes the API key. This leads to auth_token
param not being parsed correctly and we get the Incorrect authentication credentials.
error back.
We currently have a combined total of 178 published and draft posts on butter.
Given this code
array = []
array += ButterCMS::Post.all(page_size: 100, page: 1, preview: 1).to_a
array += ButterCMS::Post.all(page_size: 100, page: 2, preview: 1).to_a
array.length => 178
That set of params correctly returns the number of posts into the array variable. I correctly get 178 back.
If I change the page_size param from 100 to 20, I'm missing two posts.
array = []
array += ButterCMS::Post.all(page_size: 20, page: 1, preview: 1).to_a
array += ButterCMS::Post.all(page_size: 20, page: 2, preview: 1).to_a
array += ButterCMS::Post.all(page_size: 20, page: 3, preview: 1).to_a
array += ButterCMS::Post.all(page_size: 20, page: 4, preview: 1).to_a
array += ButterCMS::Post.all(page_size: 20, page: 5, preview: 1).to_a
array += ButterCMS::Post.all(page_size: 20, page: 6, preview: 1).to_a
array += ButterCMS::Post.all(page_size: 20, page: 7, preview: 1).to_a
array += ButterCMS::Post.all(page_size: 20, page: 8, preview: 1).to_a
array += ButterCMS::Post.all(page_size: 20, page: 9, preview: 1).to_a
array.length => 176
I ran the code above with page_size ranging from 1 - 100 and it seems only the number 20 incorrectly returns the number of blog posts.
The bug does appear to occur only when I pass in the preview param in combination with page_size = 20.
Hi ๐
There's some invalid Ruby code in a couple of places in the README. Listed is a hash key fields.headline: 'foo bar'
, which is not valid Ruby code.
params = { page: 1, page_size: 10, locale: 'en', preview: 1, fields.headline: 'foo bar', levels: 2 } # optional
^^^^^^^^^^^^^^^
I assume from the API docs this is intended to be passed as a string like 'fields.headline' => 'foo bar'
as a string. Is that correct?
params = { page: 1, page_size: 10, locale: 'en', preview: 1, "fields.headline" => 'foo bar', levels: 2 } # optional
We're using Rails cache to store our Butter API call results. The dynamically generated methods on ButterResource
are not restored when restored from cache, leading to unreliable errors like NameError: undefined method
seo_title' for #ButterCMS::Post:0x00007fec4faa2cb8`. This happens any time the server restarts.
Because of the way ButterResource is dynamically creating methods, the methods are not restored when a ButterCollection
is restored from cache. Ruby only calls initialize on the main object when restoring via Marshal.load
.
ButterResource
, the initialize
method is called.ButterCollection
, the initialize
method of the ButterCollection
is called, but not the internal ButterResource
s.There's a couple different ways to fix this, which is why I am making an issue instead of a PR:
marshal_dump
and marshal_load
methods on ButterResource
to dynamically add the methods in marshal_load
. I think this is the only solution that preserves the current behaviormethod_missing
to pass through the unknown calls to the @data
OpenStruct
. This could break existing code if people are checking for respond_to?
The marshal code would look something like this:
# unfortunately, Ruby expects you to define both methods for this to work,
# so the dump has to be manually specified as well
def marshal_dump
{ json: @json, data: @data, meta: @meta }
end
def marshal_load(dump)
@json = dump[:json]
@data = dump[:data]
@meta = dump[:meta]
return unless @data.respond_to?(:each_pair)
@data.each_pair do |key, value|
instance_variable_set("@#{key}", @data.send(key))
self.class.send(:attr_reader, key)
end
end
I expect that the first option is the best for preserving backwards compatibility, what do you think?
Given that you are on Ruby 2.7, the buttercms-ruby gem triggers the following warning:
lib/buttercms-ruby.rb:75: warning: URI.escape is obsolete
More information: https://docs.knapsackpro.com/2020/uri-escape-is-obsolete-percent-encoding-your-query-string
Unfortunately, it seems like in our haste to help, we actually made things worse!
The older PR filtered the path name through encode_www_form
, which is expecting a Hash object (like query params)... but the path is a string, so this errors. The test suite also doesn't currently pass on the main branch.
PR incoming!
(Also, let us know if you want help setting up ruby CI for this project... would help with the tests!)
1) ButterCMS.request raises NotFound on 404
Failure/Error:
expect { ButterCMS.request("/posts/slug/") }
.to raise_error(ButterCMS::NotFound)
expected ButterCMS::NotFound, got #<NoMethodError: undefined method `map' for "/posts/slug/":String
Did you mean? tap> with backtrace:
# ./lib/buttercms-ruby.rb:74:in `api_request'
# ./lib/buttercms-ruby.rb:99:in `request'
# ./spec/lib/butter-ruby_spec.rb:32:in `block (4 levels) in <top (required)>'
# ./spec/lib/butter-ruby_spec.rb:32:in `block (3 levels) in <top (required)>'
# /Users/hcatlin/.rvm/gems/ruby-2.7.2/gems/webmock-3.11.2/lib/webmock/rspec.rb:37:in `block (2 levels) in <top (required)>'
# ./spec/lib/butter-ruby_spec.rb:32:in `block (3 levels) in <top (required)>'
# /Users/hcatlin/.rvm/gems/ruby-2.7.2/gems/webmock-3.11.2/lib/webmock/rspec.rb:37:in `block (2 levels) in <top (required)>'
2) ButterCMS.request with an api token should make an api request
Failure/Error: path = "#{@api_url.path}#{URI.encode_www_form(path)}?#{URI.encode_www_form(query)}"
NoMethodError:
undefined method `map' for "":String
Did you mean? tap
# ./lib/buttercms-ruby.rb:74:in `api_request'
# ./lib/buttercms-ruby.rb:99:in `request'
# ./spec/lib/butter-ruby_spec.rb:14:in `block (4 levels) in <top (required)>'
# /Users/hcatlin/.rvm/gems/ruby-2.7.2/gems/webmock-3.11.2/lib/webmock/rspec.rb:37:in `block (2 levels) in <top (required)>'
Finished in 0.02238 seconds (files took 0.17304 seconds to load)
14 examples, 2 failures
The ButterCMS::Content does not expose it's meta object with prevents us from being able to iterate over respective pages.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.