wp-api 0.0.2 → 0.0.3

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: be8b365075e87e981f79e61c1a7e766cd93d078b
4
- data.tar.gz: 4c59262402ba39fa3ab8ce90e6d05b24c3b285b7
3
+ metadata.gz: e47781bfa7510821225aeb90053dab50a11b7579
4
+ data.tar.gz: 74a354808fa1138efa2fcb3ee7a43312c1467ef7
5
5
  SHA512:
6
- metadata.gz: f2658d1c1d13e70bcdcaf28858a8c21c8b980b7a3413df509e99683cb8ab6b9a7274d92005cbd4afffb010341575fc34f67fafee91b1a3c80b3c4057939da8bd
7
- data.tar.gz: c55d99f6ff6c9fd6aa2d5c0c58d203dbbe664f7a681f5baa0d142464caf94b6e90c92b0cd5dd3745f3e56840df753b79deb25ce711847e2ec01359095c7e1778
6
+ metadata.gz: b9d09030d433e7a192488d991ffa4df5bb7805d90817e82fea9e0d7377dae30b432c025c0df98f9ed05569ec34e6daccb8975e5ff0d1e09650370205ee0b1c6c
7
+ data.tar.gz: b653ec85e6228bf9c61fa0a40d61a788e56977f6856128917d4f713f0995000a2463ae2fff1f20588541d4f4a571adc73872f33305bb1a21ac81c7f0f61d6f9b
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.1.2
data/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # WP::API
2
2
 
3
+ [![Circle CI](https://circleci.com/gh/colinyoung/wp-api.png?style=badge)](https://circleci.com/gh/colinyoung/wp-api)
4
+
3
5
  Makes it incredibly easy and semantic to access Wordpress blogs that have the new, RESTful WP API plugin installed.
4
6
 
5
7
  ## Installation
@@ -7,6 +9,10 @@ Makes it incredibly easy and semantic to access Wordpress blogs that have the ne
7
9
  gem 'wp-api'
8
10
  bundle
9
11
 
12
+ ## Note
13
+
14
+ This gem requires Ruby 2.0, which is the [oldest currently supported version of Ruby](https://www.ruby-lang.org/en/news/2014/07/01/eol-for-1-8-7-and-1-9-2/).
15
+
10
16
  ## Usage
11
17
 
12
18
  ```ruby
@@ -22,3 +28,4 @@ client.users
22
28
  ## Author
23
29
 
24
30
  @colinyoung
31
+
data/circle.yml ADDED
@@ -0,0 +1,3 @@
1
+ machine:
2
+ ruby:
3
+ version: 2.1.2
data/lib/wp/api/client.rb CHANGED
@@ -1,5 +1,4 @@
1
1
  require 'httparty'
2
- require 'yajl'
3
2
  require 'addressable/uri'
4
3
  require 'wp/api/endpoints'
5
4
 
@@ -20,8 +19,12 @@ module WP::API
20
19
 
21
20
  def get(resource, query = {})
22
21
  path = url_for(resource, query)
23
- body = Client.get(path).body
24
- parse(body)
22
+ response = Client.get(path)
23
+ if response.empty?
24
+ raise WP::API::ResourceNotFoundError
25
+ else
26
+ [ response.parsed_response, response.headers ] # Already parsed.
27
+ end
25
28
  end
26
29
 
27
30
  private
@@ -35,13 +38,13 @@ module WP::API
35
38
 
36
39
  def params(query)
37
40
  uri = Addressable::URI.new
38
- uri.query_values = query
39
- uri.query
40
- end
41
+ filter_hash = {}
42
+ query.each do |key, value|
43
+ filter_hash["filter[#{key}]"] = value
44
+ end
45
+ uri.query_values = filter_hash
41
46
 
42
- def parse(string)
43
- @parser ||= Yajl::Parser.new
44
- @parser.parse(string)
47
+ uri.query
45
48
  end
46
49
  end
47
50
  end
@@ -2,14 +2,18 @@ module WP::API
2
2
  module Endpoints
3
3
 
4
4
  def posts(query = {})
5
- get("posts", query).collect do |hash|
6
- Post.new(hash)
5
+ posts, headers = get("posts", query)
6
+ posts.collect do |hash|
7
+ WP::API::Post.new(hash, headers)
7
8
  end
8
9
  end
9
10
 
10
11
  def post(id, query = {})
11
- hash = get("posts/#{id}", query)
12
- Post.new(hash)
12
+ WP::API::Post.new *get("posts/#{id}", query)
13
+ end
14
+
15
+ def post_named(slug)
16
+ WP::API::Post.new *get("posts", name: slug).first
13
17
  end
14
18
 
15
19
  end
@@ -0,0 +1,3 @@
1
+ module WP::API
2
+ class ResourceNotFoundError < Exception; end
3
+ end
@@ -1,15 +1,18 @@
1
1
  require 'active_support/inflector'
2
+ require 'pry'
2
3
 
3
4
  module WP::API
4
5
  class Resource
5
- attr_reader :attributes
6
+ attr_reader :attributes, :headers
6
7
 
7
- def initialize(attributes)
8
+ def initialize(attributes, headers = {})
9
+ raise ResourceNotFoundError.new(self.class.name) if attributes.nil?
8
10
  @attributes = attributes
11
+ @headers = _downcase_keys(headers).slice("link") if headers
9
12
  end
10
13
 
11
14
  def id
12
- @attributes['ID']
15
+ attributes['ID']
13
16
  end
14
17
 
15
18
  protected
@@ -19,22 +22,22 @@ module WP::API
19
22
  determinant = key[-1]
20
23
  case determinant
21
24
  when '?' # example: post.sticky?
22
- @attributes[key.chomp(determinant)] == true
25
+ attributes[key.chomp(determinant)] == true
23
26
  when '!' # unsupported
24
27
  fail NoMethodError.new(key)
25
28
  when '=' # example: post.title = 'my new title'
26
- @attributes[key.chomp(determinant)] = new_value
29
+ attributes[key.chomp(determinant)] = new_value
27
30
  else
28
31
  # All other values. Hashes are converted to objects
29
32
  # if a resource for them exists (e.g. Authors)
30
- object key, @attributes[key]
33
+ object key, attributes[key]
31
34
  end
32
35
  end
33
36
 
34
37
  private
35
38
 
36
39
  def to_s
37
- @attributes.to_s
40
+ attributes.to_s
38
41
  end
39
42
 
40
43
  def object(key, value)
@@ -46,5 +49,13 @@ module WP::API
46
49
  value
47
50
  end
48
51
  end
52
+
53
+ def _downcase_keys(hash)
54
+ Hash.new.tap do |new_hash|
55
+ hash.each do |k, v|
56
+ new_hash[k.downcase] = v
57
+ end
58
+ end
59
+ end
49
60
  end
50
61
  end
@@ -0,0 +1,7 @@
1
+ module WP::API
2
+ class Category < Resource
3
+ def to_param
4
+ slug
5
+ end
6
+ end
7
+ end
@@ -1,4 +1,35 @@
1
1
  module WP::API
2
2
  class Post < Resource
3
+ def categories
4
+ terms['category'].collect {|cat| WP::API::Category.new(cat) }
5
+ end
6
+
7
+ def prev
8
+ item = link_header_items.find {|rel, url| rel == "prev" }
9
+ item.last if item
10
+ end
11
+
12
+ def next
13
+ item = link_header_items.find {|rel, url| rel == "next" }
14
+ item.last if item
15
+ end
16
+
17
+ def items
18
+ items = link_header_items.select {|rel, url| rel == "item" }
19
+ items.empty? ? [] : items.collect(&:last)
20
+ end
21
+
22
+ private
23
+
24
+ def link_header_items
25
+ @link_header_items ||= headers['link'].split(', ').collect do |header|
26
+ [
27
+ header.match(/rel="([^"]+)"/)[1],
28
+ header.match(/<([^>]+)>/)[1]
29
+ ]
30
+ end
31
+ rescue
32
+ []
33
+ end
3
34
  end
4
35
  end
@@ -1,5 +1,5 @@
1
1
  module WP
2
2
  module API
3
- VERSION = "0.0.2"
3
+ VERSION = "0.0.3"
4
4
  end
5
5
  end
data/lib/wp/api.rb CHANGED
@@ -1,10 +1,10 @@
1
1
  require 'wp/api/version'
2
+ require 'wp/api/errors'
2
3
  require 'wp/api/resource'
3
- Dir['lib/wp/api/resources/*.rb'].each {|resource| require resource }
4
+ Dir[File.expand_path(File.dirname(__FILE__) + '/api/resources/*.rb')].each {|resource| require resource }
4
5
  require 'wp/api/client'
5
6
 
6
7
  require 'httparty'
7
- require 'yajl'
8
8
 
9
9
  module WP
10
10
  module API
@@ -17,6 +17,14 @@ describe WP::API do
17
17
  expect(subject).to be_a WP::API::Post
18
18
  end
19
19
 
20
+ it "should have an attributes hash" do
21
+ expect(subject.attributes).to be_a Hash
22
+ end
23
+
24
+ it "should have a headers hash" do
25
+ expect(subject.headers).to be_a Hash
26
+ end
27
+
20
28
  it "should have correct IDs" do
21
29
  expect(subject.id).to eq 1
22
30
  end
@@ -1,5 +1,3 @@
1
- require 'pry'
2
-
3
1
  describe WP::API do
4
2
  context "raw HTTP request" do
5
3
  let(:response) { HTTParty.get('http://wp.example.com/wp-json/posts').body }
@@ -54,6 +52,24 @@ describe WP::API do
54
52
  expect(meta).to be_a Hash
55
53
  end
56
54
  end
55
+
56
+ context "categories" do
57
+ let(:categories) { subject.categories }
58
+
59
+ it "should be converted to a class" do
60
+ expect(categories.first).to be_a WP::API::Category
61
+ end
62
+
63
+ it "should respond to #to_param" do
64
+ expect(categories.first.to_param).to eq "foxes"
65
+ end
66
+ end
67
+
68
+ context "link headers" do
69
+ its(:next) { should == "/wp-json/posts?page=2" }
70
+ its(:prev) { should be_nil }
71
+ its('items.size') { should eq 2 }
72
+ end
57
73
  end
58
74
 
59
75
  end
@@ -165,6 +165,21 @@
165
165
  "self": "http:\/\/wp.example.com\/wp-json\/taxonomies\/post_tag\/terms\/1"
166
166
  }
167
167
  }
168
+ }],
169
+ "category": [{
170
+ "ID": 3,
171
+ "name": "Foxes",
172
+ "slug": "foxes",
173
+ "description": "",
174
+ "parent": null,
175
+ "count": 1,
176
+ "link": "http:\/\/wp.example.com\/category\/foxes\/",
177
+ "meta": {
178
+ "links": {
179
+ "collection": "http:\/\/wp.example.com\/wp-json\/taxonomies\/category\/terms",
180
+ "self": "http:\/\/wp.example.com\/wp-json\/taxonomies\/category\/terms\/3"
181
+ }
182
+ }
168
183
  }]
169
184
  }
170
- }
185
+ }
@@ -165,6 +165,21 @@
165
165
  "self": "http:\/\/wp.example.com\/wp-json\/taxonomies\/post_tag\/terms\/2"
166
166
  }
167
167
  }
168
+ }],
169
+ "category": [{
170
+ "ID": 4,
171
+ "name": "Cars",
172
+ "slug": "cars",
173
+ "description": "",
174
+ "parent": null,
175
+ "count": 1,
176
+ "link": "http:\/\/wp.example.com\/category\/cars\/",
177
+ "meta": {
178
+ "links": {
179
+ "collection": "http:\/\/wp.example.com\/wp-json\/taxonomies\/category\/terms",
180
+ "self": "http:\/\/wp.example.com\/wp-json\/taxonomies\/category\/terms\/4"
181
+ }
182
+ }
168
183
  }]
169
184
  }
170
- }
185
+ }
@@ -0,0 +1 @@
1
+ </wp-json/posts?page=2>; rel="next", <http://wp.twigtale.com/wp-json/posts/1>; rel="item"; title="First post", <http://wp.twigtale.com/wp-json/posts/2>; rel="item"; title="Second post"
@@ -165,6 +165,21 @@
165
165
  "self": "http:\/\/wp.example.com\/wp-json\/taxonomies\/post_tag\/terms\/1"
166
166
  }
167
167
  }
168
+ }],
169
+ "category": [{
170
+ "ID": 3,
171
+ "name": "Foxes",
172
+ "slug": "foxes",
173
+ "description": "",
174
+ "parent": null,
175
+ "count": 1,
176
+ "link": "http:\/\/wp.example.com\/category\/foxes\/",
177
+ "meta": {
178
+ "links": {
179
+ "collection": "http:\/\/wp.example.com\/wp-json\/taxonomies\/category\/terms",
180
+ "self": "http:\/\/wp.example.com\/wp-json\/taxonomies\/category\/terms\/3"
181
+ }
182
+ }
168
183
  }]
169
184
  }
170
185
  },
@@ -335,6 +350,21 @@
335
350
  "self": "http:\/\/wp.example.com\/wp-json\/taxonomies\/post_tag\/terms\/2"
336
351
  }
337
352
  }
353
+ }],
354
+ "category": [{
355
+ "ID": 4,
356
+ "name": "Cars",
357
+ "slug": "cars",
358
+ "description": "",
359
+ "parent": null,
360
+ "count": 1,
361
+ "link": "http:\/\/wp.example.com\/category\/cars\/",
362
+ "meta": {
363
+ "links": {
364
+ "collection": "http:\/\/wp.example.com\/wp-json\/taxonomies\/category\/terms",
365
+ "self": "http:\/\/wp.example.com\/wp-json\/taxonomies\/category\/terms\/4"
366
+ }
367
+ }
338
368
  }]
339
369
  }
340
- }]
370
+ }]
@@ -1,3 +1,5 @@
1
+ require 'yajl'
2
+
1
3
  module JSONHelper
2
4
  def parse_json(file_or_string)
3
5
  Yajl::Parser.new.parse(file_or_string)
data/spec/spec_helper.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'bundler/setup'
2
+ require 'rspec/its'
2
3
  Bundler.setup
3
4
 
4
5
  $LOAD_PATH << File.dirname(__FILE__) + "/../"
@@ -14,8 +14,8 @@ class MockWordpressServer
14
14
  protected
15
15
 
16
16
  def register_all
17
- FakeWeb.register_uri(:get, "http://#{host}/wp-json/posts", :body => support_file("posts.json"))
18
- FakeWeb.register_uri(:get, "http://#{host}/wp-json/posts/1", :body => support_file("posts/1.json"))
19
- FakeWeb.register_uri(:get, "http://#{host}/wp-json/posts/2", :body => support_file("posts/2.json"))
17
+ FakeWeb.register_uri(:get, "http://#{host}/wp-json/posts", :body => support_file("posts.json"), :content_type => "application/json", :link => support_file("posts.header.txt"))
18
+ FakeWeb.register_uri(:get, "http://#{host}/wp-json/posts/1", :body => support_file("posts/1.json"), :content_type => "application/json")
19
+ FakeWeb.register_uri(:get, "http://#{host}/wp-json/posts/2", :body => support_file("posts/2.json"), :content_type => "application/json")
20
20
  end
21
21
  end
data/wp-api.gemspec CHANGED
@@ -18,14 +18,15 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
- spec.add_dependency 'httparty', '~> 0.13.1'
22
- spec.add_dependency 'yajl-ruby', '~> 1.2.1'
23
- spec.add_dependency 'activesupport'
24
- spec.add_dependency 'addressable'
21
+ spec.add_runtime_dependency 'httparty'
22
+ spec.add_runtime_dependency 'activesupport'
23
+ spec.add_runtime_dependency 'addressable'
25
24
 
26
25
  spec.add_development_dependency "bundler", "~> 1.6"
27
- spec.add_development_dependency "rake"
28
- spec.add_development_dependency "rspec", "~> 3.1.0"
29
- spec.add_development_dependency "fakeweb", "~> 1.3.0"
26
+ spec.add_development_dependency "yajl-ruby", '~> 1.2.1'
27
+ spec.add_development_dependency "rake", '~> 0'
28
+ spec.add_development_dependency "rspec", '>= 2.0'
29
+ spec.add_development_dependency "rspec-its", '>= 1.0.1'
30
+ spec.add_development_dependency "fakeweb", '~> 1.3', '>= 1.3.0'
30
31
  spec.add_development_dependency "pry"
31
32
  end
metadata CHANGED
@@ -1,43 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wp-api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Colin Young
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-09-17 00:00:00.000000000 Z
11
+ date: 2014-09-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: httparty
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
18
- - !ruby/object:Gem::Version
19
- version: 0.13.1
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - "~>"
25
- - !ruby/object:Gem::Version
26
- version: 0.13.1
27
- - !ruby/object:Gem::Dependency
28
- name: yajl-ruby
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - "~>"
17
+ - - ">="
32
18
  - !ruby/object:Gem::Version
33
- version: 1.2.1
19
+ version: '0'
34
20
  type: :runtime
35
21
  prerelease: false
36
22
  version_requirements: !ruby/object:Gem::Requirement
37
23
  requirements:
38
- - - "~>"
24
+ - - ">="
39
25
  - !ruby/object:Gem::Version
40
- version: 1.2.1
26
+ version: '0'
41
27
  - !ruby/object:Gem::Dependency
42
28
  name: activesupport
43
29
  requirement: !ruby/object:Gem::Requirement
@@ -80,39 +66,70 @@ dependencies:
80
66
  - - "~>"
81
67
  - !ruby/object:Gem::Version
82
68
  version: '1.6'
69
+ - !ruby/object:Gem::Dependency
70
+ name: yajl-ruby
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 1.2.1
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 1.2.1
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: rake
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - ">="
87
+ - - "~>"
88
88
  - !ruby/object:Gem::Version
89
89
  version: '0'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - ">="
94
+ - - "~>"
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: rspec
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
- - - "~>"
101
+ - - ">="
102
102
  - !ruby/object:Gem::Version
103
- version: 3.1.0
103
+ version: '2.0'
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
- - - "~>"
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '2.0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rspec-its
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: 1.0.1
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
109
123
  - !ruby/object:Gem::Version
110
- version: 3.1.0
124
+ version: 1.0.1
111
125
  - !ruby/object:Gem::Dependency
112
126
  name: fakeweb
113
127
  requirement: !ruby/object:Gem::Requirement
114
128
  requirements:
115
129
  - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '1.3'
132
+ - - ">="
116
133
  - !ruby/object:Gem::Version
117
134
  version: 1.3.0
118
135
  type: :development
@@ -120,6 +137,9 @@ dependencies:
120
137
  version_requirements: !ruby/object:Gem::Requirement
121
138
  requirements:
122
139
  - - "~>"
140
+ - !ruby/object:Gem::Version
141
+ version: '1.3'
142
+ - - ">="
123
143
  - !ruby/object:Gem::Version
124
144
  version: 1.3.0
125
145
  - !ruby/object:Gem::Dependency
@@ -146,19 +166,24 @@ extra_rdoc_files: []
146
166
  files:
147
167
  - ".gitignore"
148
168
  - ".rspec"
169
+ - ".ruby-version"
149
170
  - Gemfile
150
171
  - LICENSE.txt
151
172
  - README.md
152
173
  - Rakefile
174
+ - circle.yml
153
175
  - lib/wp/api.rb
154
176
  - lib/wp/api/client.rb
155
177
  - lib/wp/api/endpoints.rb
178
+ - lib/wp/api/errors.rb
156
179
  - lib/wp/api/resource.rb
157
180
  - lib/wp/api/resources/author.rb
181
+ - lib/wp/api/resources/category.rb
158
182
  - lib/wp/api/resources/post.rb
159
183
  - lib/wp/api/version.rb
160
184
  - spec/endpoints/post_spec.rb
161
185
  - spec/endpoints/posts_spec.rb
186
+ - spec/files/posts.header.txt
162
187
  - spec/files/posts.json
163
188
  - spec/files/posts/1.json
164
189
  - spec/files/posts/2.json
@@ -195,6 +220,7 @@ summary: Easily access Wordpress blogs that have the new, RESTful WP API plugin
195
220
  test_files:
196
221
  - spec/endpoints/post_spec.rb
197
222
  - spec/endpoints/posts_spec.rb
223
+ - spec/files/posts.header.txt
198
224
  - spec/files/posts.json
199
225
  - spec/files/posts/1.json
200
226
  - spec/files/posts/2.json