README.md in json_api_client-1.0.1 vs README.md in json_api_client-1.0.2
- old
+ new
@@ -6,13 +6,13 @@
## Usage
You will want to create your own resource classes that inherit from `JsonApiClient::Resource` similar to how you would create an `ActiveRecord` class. You may also want to create your own abstract base class to share common behavior. Additionally, you will probably want to namespace your models. Namespacing your model will not affect the url routing to that resource.
-```
+```ruby
module MyApi
- # this is an "abstract" base class that
+ # this is an "abstract" base class that
class Base < JsonApiClient::Resource
# set the api base url in an abstract base class
self.site = "http://example.com/"
end
@@ -29,11 +29,11 @@
By convention, we figure guess the resource route from the class name. In the above example, `Article`'s path is "http://example.com/articles" and `Person`'s path would be "http://example.com/people".
Some basic example usage:
-```
+```ruby
MyApi::Article.all
MyApi::Article.where(author_id: 1).find(2)
MyApi::Article.where(author_id: 1).all
MyApi::Person.where(name: "foo").order(created_at: :desc).includes(:preferences, :cars).all
@@ -60,37 +60,39 @@
[See specification](http://jsonapi.org/format/#errors)
Out of the box, `json_api_client` handles server side validation only.
-```
+```ruby
User.create(name: "Bob", email_address: "invalid email")
-=> false
+# => false
user = User.new(name: "Bob", email_address: "invalid email")
user.save
-=> false
+# => false
# returns an error collector which is array-like
user.errors
-=> ["Email address is invalid"]
+# => ["Email address is invalid"]
# get all error titles
user.errors.full_messages
-=> ["Email address is invalid"]
+# => ["Email address is invalid"]
# get errors for a specific parameter
user.errors[:email_address]
-=> ["Email address is invalid"]
+# => ["Email address is invalid"]
user = User.find(1)
user.update_attributes(email_address: "invalid email")
-=> false
+# => false
+
user.errors
-=> ["Email address is invalid"]
+# => ["Email address is invalid"]
+
user.email_address
-=> "invalid email"
+# => "invalid email"
```
For now we are assuming that error sources are all parameters.
If you want to add client side validation, I suggest creating a form model class that uses ActiveModel's validations.
@@ -99,11 +101,11 @@
[See specification](http://jsonapi.org/format/#document-structure-meta)
If the response has a top level meta data section, we can access it via the `meta` accessor on `ResultSet`.
-```
+```ruby
# Example response:
{
"meta": {
"copyright": "Copyright 2015 Example Corp.",
"authors": [
@@ -117,67 +119,67 @@
}
}
articles = Articles.all
articles.meta.copyright
-=> "Copyright 2015 Example Corp."
+# => "Copyright 2015 Example Corp."
+
articles.meta.authors
-=> ["Yehuda Katz", "Steve Klabnik", "Dan Gebhardt"]
+# => ["Yehuda Katz", "Steve Klabnik", "Dan Gebhardt"]
```
## Top-level Links
[See specification](http://jsonapi.org/format/#document-structure-top-level-links)
If the resource returns top level links, we can access them via the `links` accessor on `ResultSet`.
-```
+```ruby
articles = Articles.find(1)
articles.links.related
```
## Nested Resources
You can force nested resource paths for your models by using a `belongs_to` association.
**Note: Using belongs_to is only necessary for setting a nested path.**
-```
+```ruby
module MyApi
class Account < JsonApiClient::Resource
- belongs_to :user
+ belongs_to :user
end
end
# try to find without the nested parameter
MyApi::Account.find(1)
-=> raises ArgumentError
+# => raises ArgumentError
# makes request to /users/2/accounts/1
MyApi::Account.where(user_id: 2).find(1)
-=> returns ResultSet
+# => returns ResultSet
```
## Custom Methods
You can create custom methods on both collections (class method) and members (instance methods).
-```
+```ruby
module MyApi
class User < JsonApiClient::Resource
+ # GET /users/search
+ custom_endpoint :search, on: :collection, request_method: :get
- # GET /users/search
- custom_endpoint :search, on: :collection, request_method: :get
-
- # PUT /users/:id/verify
- custom_endpoint :verify, on: :member, request_method: :put
+ # PUT /users/:id/verify
+ custom_endpoint :verify, on: :member, request_method: :put
end
end
# makes GET request to /users/search?name=Jeff
MyApi::User.search(name: 'Jeff')
-=> <ResultSet of MyApi::User instances>
+# => <ResultSet of MyApi::User instances>
user = MyApi::User.find(1)
# makes PUT request to /users/1/verify?foo=bar
user.verify(foo: 'bar')
```
@@ -186,11 +188,11 @@
[See specification](http://jsonapi.org/format/#fetching-includes)
If the response returns a [compound document](http://jsonapi.org/format/#document-structure-compound-documents), then we should be able to get the related resources.
-```
+```ruby
# makes request to /articles/1?include=author,comments.author
results = Article.includes(:author, :comments => :author).find(1)
# should not have to make additional requests to the server
authors = results.map(&:author)
@@ -198,28 +200,28 @@
## Sparse Fieldsets
[See specification](http://jsonapi.org/format/#fetching-sparse-fieldsets)
-```
+```ruby
# makes request to /articles?fields[articles]=title,body
article = Article.select("title,body").first
# should have fetched the requested fields
article.title
-=> "Rails is Omakase"
+# => "Rails is Omakase"
# should not have returned the created_at
article.created_at
-=> raise NoMethodError
+# => raise NoMethodError
```
## Sorting
[See specification](http://jsonapi.org/format/#fetching-sorting)
-```
+```ruby
# makes request to /people?sort=age
youngest = Person.sort(:age).all
# also makes request to /people?sort=age
youngest = Person.sort(age: :asc).all
@@ -232,11 +234,11 @@
[See specification](http://jsonapi.org/format/#fetching-pagination)
### Requesting
-```
+```ruby
# makes request to /articles?page=2&per_page=30
articles = Article.page(2).per(30).to_a
# also makes request to /articles?page=2&per_page=30
articles = Article.paginate(page: 2, per_page: 30).to_a
@@ -246,11 +248,11 @@
### Browsing
If the response contains additional pagination links, you can also get at those:
-```
+```ruby
articles = Article.paginate(page: 2, per_page: 30).to_a
articles.pages.next
articles.pages.last
```
@@ -260,11 +262,11 @@
## Filtering
[See specifiation](http://jsonapi.org/format/#fetching-filtering)
-```
+```ruby
# makes request to /people?filter[name]=Jeff
Person.where(name: 'Jeff').all
```
## Schema
@@ -275,32 +277,34 @@
**Note: This is completely optional. This will set default values and handle typecasting.**
### Example
-```
+```ruby
class User < JsonApiClient::Resource
property :name, type: :string
property :is_admin, type: :boolean, default: false
property :points_accrued, type: :int, default: 0
property :averge_points_per_day, type: :float
end
# default values
u = User.new
+
u.name
-=> nil
+# => nil
+
u.is_admin
-=> false
+# => false
+
u.points_accrued
-=> 0
+# => 0
# casting
u.average_points_per_day = "0.3"
u.average_points_per_day
-=> 0.3
-
+# => 0.3
```
### Types
The basic types that we allow are:
@@ -319,11 +323,11 @@
### Paths
You can customize this path by changing your resource's `table_name`:
-```
+```ruby
module MyApi
class SomeResource < Base
def self.table_name
"foobar"
end
@@ -336,11 +340,11 @@
### Connections
You can configure your API client to use a custom connection that implementes the `run` instance method. It should return data that your parser can handle. The default connection class wraps Faraday and lets you add middleware.
-```
+```ruby
class NullConnection
def initialize(*args)
end
def run(request_method, path, params = {}, headers = {})
@@ -350,22 +354,21 @@
end
class CustomConnectionResource < TestResource
self.connection_class = NullConnection
end
-
```
#### Connection Options
You can configure your connection using Faraday middleware. In general, you'll want
to do this in a base model that all your resources inherit from:
-```
+```ruby
MyApi::Base.connection do |connection|
# set OAuth2 headers
- connection.use Faraday::Request::Oauth2, 'MYTOKEN'
+ connection.use FaradayMiddleware::OAuth2, 'MYTOKEN'
# log responses
connection.use Faraday::Response::Logger
connection.use MyCustomMiddleware
@@ -380,14 +383,14 @@
### Custom Parser
You can configure your API client to use a custom parser that implements the `parse` class method. It should return a `JsonApiClient::ResultSet` instance. You can use it by setting the parser attribute on your model:
-```
+```ruby
class MyCustomParser
def self.parse(klass, response)
- …
+ # …
# returns some ResultSet object
end
end
class MyApi::Base < JsonApiClient::Resource
@@ -397,18 +400,18 @@
### Custom Query Builder
You can customize how the scope builder methods map to request parameters.
-```
+```ruby
class MyQueryBuilder
def def initialize(klass); end
def where(conditions = {})
end
- … add order, includes, paginate, page, first, build
+ # … add order, includes, paginate, page, first, build
end
class MyApi::Base < JsonApiClient::Resource
self.query_builder = MyQueryBuilder
end
@@ -416,10 +419,10 @@
### Custom Paginator
You can customize how your resources find pagination information from the response.
-```
+```ruby
class MyPaginator
def initialize(result_set, data); end
# implement current_page, total_entries, etc
end