Loading...
Loading...
Loading...
# Retrieving Records in ApiResource
## Finding by id
The simplest way to retrieve a record is by its ID
Resource::Person.find(1)
# GET /people/1.json
## Simple conditions
To add simple query params, you can just use the `.where` method
Resource::Person.where(first_name: 'Aaron').all
# GET /people.json?first_name=Aaron
## Scopes
Scopes must be activated in the Server application and are then read by
the client application via the
{file:docs/ResourceDefinition.md Resource Definition}.
### Activating a scope in the Server application
# app/models/person.rb
class Person < ActiveRecord::Base
include LifebookerCommon::Model::Resource
scope :birthday_on, -> date {
where(birthday: date)
}
scope :aaron, -> {
where(name: 'Aaron')
}
end
### Using a scope in the Client application
# GET /people.json?birthday_on[date]=2014-01-01
@people = Resource::Person.birthday_on(Date.parse('2014-01-01'))
@people.each do |person|
...
end
Scopes can be chained together
# GET /people.json?birthday_on[date]=2014-01-01&aaron=1
@people = Resource::Person
.birthday_on(Date.parse('2014-01-01'))
.aaron
@people.each do |person|
...
end
### Applying scopes in the Client application
ApiResource::Base gives us the ability to apply scopes that are valid
according to the {file:docs/ResourceDefinition.md Resource Definition}
directly from params that are passed in
# In the Client application
class PeopleController < ApplicationController
def index
@people = Resource::Person.add_scopes(params)
end
end
This reads the params supplied to the controller to see if there are any
valid scopes and then applies them. These scopes follow the same rules
as the ones that are sent to the server
#### Sequence
1. Client supplies params to our client app
# curl http://clienthost/people.html?birthday_on[date]=2014-01-01
1. Client controller parses params, passes them to {ApiResource.add_scopes}
and creates a ScopeCondition to generate params to the server
1. Resource::Person makes a request to the Server application. This request
has the same parameters as what was passed in to the client application
assuming those parameters were valid for a scope
# GET http://serverhost/people.json?birthday_on[date]=2014-01-01
1. Server application returns the data as JSON and Resource::Person
instantiates its records for use in the Client application
### Automatically generated scopes
`api_resource_server` and {ApiResource::Base} automatically provide several
scopes for all descendants of ActiveRecord::Base and ApiResource::Base
respectively
#### IDs
You can supply an array of ids to a resource to scope by only resources in
that set of ids
# in the Client application
Resource::Person.add_scopes(ids: [1, 2, 3])
# => GET /people.json?ids[]=1&ids[]=2&ids[]=3
#### Type
In order to limit your scope to a subclass of a class that users Single Table
Inheritance, you can supply the type
# in the Server application
class Carpenter < Person
end
# in the Client application
Resource::Person.type('Carpenter')
# => GET /people.json?type=Carpenter
# back in the Server application Person.add_scopes
# converts
Person.all
# into
Carpenter.all
#### Page and PerPage
In order to paginate, you can pass page and per_page scopes into your
ApiResource::Base subclass
Resource::Person.per_page(20).page(1)
# or
Resource::Person.add_scopes(per_page: 20, page: 1)
# either of these produce
GET /people.json?page=1&per_page=20
In the Server application `add_scopes` will take care of applying
the pagination using its integration with
{https://github.com/mislav/will_paginate will_paginate}
In addition, the Server application will include a header denoting
the number of records in the set so that
{https://github.com/mislav/will_paginate will_paginate} can
render its page helpers on the client side
*Note* that in order to enable this feature the Server application
*must* use `respond_to`
# in a controller in the Client application
@people = Resource::Person.add_scopes(
params.merge(page: 2, per_page: 20)
)
# in a view in the Client application
- @people.each do |person|
%tr
%td ...
# renders the pagination links
= will_paginate(@people)
### Types of scopes
1. Static scopes
# Server code
scope :x, where(x: 'Val')
OR
scope :x, -> { where(x: 'Val') }
# Produces request from client
Resource::Person.x
# ?x=1
1. Scopes with required parameters
# Server code
scope :birthday_between, -> start, end {
where("birthday_between ? AND ?", start, end)
}
# Produces request from the client
@people = Resource::Person.birthday_between(
start: Date.today,
end: Date.tomorrow
)
# ?birthday_between[start]=2014-01-01&birthday_between[end]=2014-01-02
1. Scopes with varargs
# server code
scope :first_name, -> *names {
where(first_name: names)
}
# Produces request from the client
@people = Resource::Person.first_name('Bill', 'Sue')
# ?first_name[]=Bill&first_name[]=Sue
## Including associated data
Oftentimes we will need data from two resources, which would produce n+1 API
calls unless we sideload our data
### Concept
If, for example we loaded a list of 50 People, but needed their State data we
might have to make 50 requests to the State API endpoint
### Server application
# in app/models/person.rb
class Person < ActiveRecord::Base
belongs_to :state
# Attributes
#
# :first_name, :last_name, :state_id
end
# in app/models/state.rb
class State < ActiveRecord::Base
# Attributes
#
# :name
end
# in app/controllers/people_controller.rb
def index
respond_with(Person.add_scopes(params))
end
# in app/controllers/states_controller.rb
def index
respond_with(State.add_scopes(params))
end
### Client application
# in lib/resource/state.rb
module Resource
class State < ApiResource::Base
end
end
# in lib/resource/person.rb
module Resource
class Person < ApiResource::Base
end
end
# in a controller
@people = Resource::Person.includes(:state)
# this results in
#
# GET /people.json
#
# and
#
# GET /states.json?ids[]=person1.state_id&ids[]=person2.state_id ...
{ApiResource::Base} knows how to include data from any association where
ids are embedded in the response of the base object and the association
is present in the {file:docs/ResourceDefinition.md Resource Definition}
When asked to retrieve any information from the Advent of Code (AoC) website, use the following configuration for API calls to `https://adventofcode.com`.
DBFlow provides a few ways to retrieve information from the database. Through the `Model` classes we can map this information to easy-to-use objects.
title: "Clip-Retrieval Update: H-14 Index & SLURM Inference"
There are several ways to retrieve data from a Sleeper table. Remember that Sleeper is optimised for returning rows