flexirest 1.6.5 → 1.6.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/README.md +92 -1243
- data/docs/associations.md +181 -0
- data/docs/authentication.md +76 -0
- data/docs/automatic-conversion-of-fields-to-datedatetime.md +34 -0
- data/docs/basic-usage.md +103 -0
- data/docs/body-types.md +33 -0
- data/docs/caching.md +26 -0
- data/docs/combined-example.md +72 -0
- data/docs/debugging.md +32 -0
- data/docs/default-parameters.md +37 -0
- data/docs/faking-calls.md +22 -0
- data/docs/faraday-configuration.md +28 -0
- data/docs/filtering-result-lists.md +16 -0
- data/docs/httpparse-error-handling.md +17 -0
- data/{CONTRIBUTING.md → docs/internals.md} +4 -6
- data/docs/json-api.md +42 -0
- data/docs/lazy-loading.md +31 -0
- data/{Migrating-from-ActiveRestClient.md → docs/migrating-from-activerestclient.md} +2 -2
- data/docs/parallel-requests.md +28 -0
- data/docs/per-request-parameter-encoding.md +32 -0
- data/docs/per-request-timeouts.md +13 -0
- data/docs/plain-requests.md +30 -0
- data/docs/proxying-apis.md +86 -0
- data/docs/raw-requests.md +38 -0
- data/docs/required-parameters.md +17 -0
- data/docs/root-elements.md +34 -0
- data/{Ruby-on-Rails-Integration.md → docs/ruby-on-rails-integration.md} +16 -12
- data/docs/{Flexirest Internals.graffle → source/Flexirest Internals.graffle} +0 -0
- data/docs/{Flexirest Logo.sketch → source/Flexirest Logo.sketch} +0 -0
- data/docs/translating-apis.md +31 -0
- data/docs/updating-only-changed-dirty-attributes.md +37 -0
- data/docs/using-callbacks.md +114 -0
- data/docs/validation.md +89 -0
- data/docs/xml-responses.md +58 -0
- data/lib/flexirest/configuration.rb +36 -20
- data/lib/flexirest/request.rb +12 -4
- data/lib/flexirest/version.rb +1 -1
- data/spec/lib/request_spec.rb +28 -0
- metadata +35 -7
@@ -0,0 +1,114 @@
|
|
1
|
+
# *Flexirest:* Using callbacks
|
2
|
+
|
3
|
+
You can use callbacks to alter get/post parameters, the URL or set the post body (doing so overrides normal parameter insertion in to the body) before a request or to adjust the response after a request. This can either be a block or a named method (like ActionController's `before_callback`/`before_action` methods).
|
4
|
+
|
5
|
+
The callback is passed the name of the method (e.g. `:save`) and an object (a request object for `before_request` and a response object for `after_request`). The request object has four public attributes `post_params` (a Hash of the POST parameters), `get_params` (a Hash of the GET parameters), `headers` and `url` (a `String` containing the full URL without GET parameters appended).
|
6
|
+
|
7
|
+
```ruby
|
8
|
+
require 'secure_random'
|
9
|
+
|
10
|
+
class Person < Flexirest::Base
|
11
|
+
before_request do |name, request|
|
12
|
+
if request.post? || name == :save
|
13
|
+
id = request.post_params.delete(:id)
|
14
|
+
request.get_params[:id] = id
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
before_request :replace_token_in_url
|
19
|
+
|
20
|
+
before_request :add_authentication_details
|
21
|
+
|
22
|
+
before_request :replace_body
|
23
|
+
|
24
|
+
before_request :override_default_content_type
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def replace_token_in_url(name, request)
|
29
|
+
request.url.gsub!("#token", SecureRandom.hex)
|
30
|
+
end
|
31
|
+
|
32
|
+
def add_authentication_details(name, request)
|
33
|
+
request.headers["X-Custom-Authentication-Token"] = ENV["AUTH_TOKEN"]
|
34
|
+
end
|
35
|
+
|
36
|
+
def replace_body(name, request)
|
37
|
+
if name == :create
|
38
|
+
request.body = request.post_params.to_json
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def override_default_content_type(name, request)
|
43
|
+
if name == :save
|
44
|
+
request.headers["Content-Type"] = "application/json"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
```
|
49
|
+
|
50
|
+
If you need to, you can create a custom parent class with a `before_request` callback and all children will inherit this callback.
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
class MyProject::Base < Flexirest::Base
|
54
|
+
before_request do |name, request|
|
55
|
+
request.get_params[:api_key] = "1234567890-1234567890"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
class Person < MyProject::Base
|
60
|
+
# No need to declare a before_request for :api_key, already defined by the parent
|
61
|
+
end
|
62
|
+
```
|
63
|
+
|
64
|
+
After callbacks work in exactly the same way:
|
65
|
+
|
66
|
+
```ruby
|
67
|
+
class Person < Flexirest::Base
|
68
|
+
get :all, "/people"
|
69
|
+
|
70
|
+
after_request :fix_empty_content
|
71
|
+
after_request :cache_all_people
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
def fix_empty_content(name, response)
|
76
|
+
if response.status == 204 && response.body.blank?
|
77
|
+
response.body = '{"empty": true}'
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def cache_all_people(name, response)
|
82
|
+
if name == :all
|
83
|
+
response.response_headers["Expires"] = 1.hour.from_now.iso8601
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
```
|
88
|
+
|
89
|
+
**Note:** since v1.3.21 the empty response trick above isn't necessary, empty responses for 204 are accepted normally (the method returns `true`), but this is here to show an example of an `after_request` callback adjusting the body. The `cache_all_people` example shows how to cache a response even if the server doesn't send the correct headers.
|
90
|
+
|
91
|
+
If you want to trap an error in an `after_request` callback and retry the request, this can be done - but retries will only happen once for each request (so we'd recommend checking all conditions in a single `after_request` and then retrying after fixing them all). You achieve this by returning `:retry` from the callback.
|
92
|
+
|
93
|
+
```ruby
|
94
|
+
class Person < Flexirest::Base
|
95
|
+
get :all, "/people"
|
96
|
+
|
97
|
+
after_request :fix_invalid_request
|
98
|
+
|
99
|
+
private
|
100
|
+
|
101
|
+
def fix_invalid_request(name, response)
|
102
|
+
if response.status == 401
|
103
|
+
# Do something to fix the state of caches/variables used in the
|
104
|
+
# before_request, etc
|
105
|
+
return :retry
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
```
|
110
|
+
|
111
|
+
|
112
|
+
-----
|
113
|
+
|
114
|
+
[< Caching](caching.md) | [Lazy loading >](lazy-loading.md)
|
data/docs/validation.md
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
# *Flexirest:* Validation
|
2
|
+
|
3
|
+
You can create validations on your objects just like Rails' built in ActiveModel validations. For example:
|
4
|
+
|
5
|
+
```ruby
|
6
|
+
class Person < Flexirest::Base
|
7
|
+
validates :first_name, presence: true #ensures that the value is present and not blank
|
8
|
+
validates :last_name, existence: true #ensures that the value is non-nil only
|
9
|
+
validates :password, length: {within:6..12}, message: "Invalid password length, must be 6-12 characters"
|
10
|
+
validates :post_code, length: {minimum:6, maximum:8}
|
11
|
+
validates :salary, numericality: true, minimum: 20_000, maximum: 50_000
|
12
|
+
validates :age, numericality: { minumum: 18, maximum: 65 }
|
13
|
+
validates :suffix, inclusion: { in: %w{Dr. Mr. Mrs. Ms.}}
|
14
|
+
|
15
|
+
validates :first_name do |object, name, value|
|
16
|
+
object._errors[name] << "must be over 4 chars long" if value.length <= 4
|
17
|
+
end
|
18
|
+
|
19
|
+
get :index, '/'
|
20
|
+
end
|
21
|
+
```
|
22
|
+
|
23
|
+
Note: the block based validation is responsible for adding errors to `object._errors[name]` (and this will automatically be ready for `<<` inserting into).
|
24
|
+
|
25
|
+
Validations are run when calling `valid?` or when calling any API on an instance (and then only if it is `valid?` will the API go on to be called).
|
26
|
+
|
27
|
+
`full_error_messages` returns an array of attributes with their associated error messages, i.e. `["age must be at least 18"]`. Custom messages can be specified by passing a `:message` option to `validates`. This differs slightly from ActiveRecord in that it's an option to `validates` itself, not a part of a final hash of other options. This is because the author doesn't like the ActiveRecord format (but will accept pull requests that make both syntaxes valid). To make this clearer, an example may help:
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
# ActiveRecord
|
31
|
+
validates :name, presence: { message: "must be given please" }
|
32
|
+
|
33
|
+
# Flexirest
|
34
|
+
validates :name, :presence, message: "must be given please"
|
35
|
+
```
|
36
|
+
|
37
|
+
## Permitting nil values
|
38
|
+
|
39
|
+
The default behavior for `:length`, `:numericality` and `:inclusion` validators is to fail when a `nil` value is encountered. You can prevent `nil` attribute values from triggering validation errors for attributes that may permit `nil` by adding the `:allow_nil => true` option. Adding this option with a `true` value to `:length`, `:numericality` and `:inclusion` validators will permit `nil` values and not trigger errors. Some examples are:
|
40
|
+
|
41
|
+
```ruby
|
42
|
+
class Person < Flexirest::Base
|
43
|
+
validates :first_name, presence: true
|
44
|
+
validates :middle_name, length: { minimum: 2, maximum: 30 }, allow_nil: true
|
45
|
+
validates :last_name, existence: true
|
46
|
+
validates :nick_name, length: { minimum: 2, maximum: 30 }
|
47
|
+
validates :alias, length: { minimum: 2, maximum: 30 }, allow_nil: false
|
48
|
+
validates :password, length: { within: 6..12 }
|
49
|
+
validates :post_code, length: { minimum: 6, maximum: 8 }
|
50
|
+
validates :salary, numericality: true, minimum: 20_000, maximum: 50_000
|
51
|
+
validates :age, numericality: { minimum: 18, maximum: 65 }
|
52
|
+
validates :suffix, inclusion: { in: %w{Dr. Mr. Mrs. Ms.}}
|
53
|
+
validates :golf_score, numericality: true, allow_nil: true
|
54
|
+
validates :retirement_age, numericality: { minimum: 65 }, allow_nil: true
|
55
|
+
validates :cars_owned, numericality: true
|
56
|
+
validates :houses_owned, numericality: true, allow_nil: false
|
57
|
+
validates :favorite_authors, inclusion: { in: ["George S. Klason", "Robert T. Kiyosaki", "Lee Child"] }, allow_nil: true
|
58
|
+
validates :favorite_artists, inclusion: { in: ["Claude Monet", "Vincent Van Gogh", "Andy Warhol"] }
|
59
|
+
validates :favorite_composers, inclusion: { in: ["Mozart", "Bach", "Pachelbel", "Beethoven"] }, allow_nil: false
|
60
|
+
end
|
61
|
+
```
|
62
|
+
|
63
|
+
In the example above, the following results would occur when calling `valid?` on an instance where all attributes have `nil` values:
|
64
|
+
|
65
|
+
- `:first_name` must be present
|
66
|
+
- `:last_name` must be not be nil
|
67
|
+
- `:nick_name` must be not be nil
|
68
|
+
- `:alias` must not be nil
|
69
|
+
- `:password` must not be nil
|
70
|
+
- `:post_code` must not be nil
|
71
|
+
- `:salary` must not be nil
|
72
|
+
- `:age` must not be nil
|
73
|
+
- `:suffix` must not be nil
|
74
|
+
- `:cars_owned` must not be nil
|
75
|
+
- `:houses_owned` must not be nil
|
76
|
+
- `:favorite_artists` must not be nil
|
77
|
+
- `:favorite_composers` must not be nil
|
78
|
+
|
79
|
+
The following attributes will pass validation since they explicitly `allow_nil`:
|
80
|
+
|
81
|
+
- `:middle_name`
|
82
|
+
- `:golf_score`
|
83
|
+
- `:retirement_age`
|
84
|
+
- `:favorite_authors`
|
85
|
+
|
86
|
+
|
87
|
+
-----
|
88
|
+
|
89
|
+
[< HTTP/parse error handling](httpparse-error-handling.md) | [Filtering result lists >](filtering-result-lists.md)
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# *Flexirest:* XML Responses
|
2
|
+
|
3
|
+
Flexirest uses `Crack` to allow parsing of XML responses. For example, given an XML response of (with a content type of `application/xml` or `text/xml`):
|
4
|
+
|
5
|
+
```xml
|
6
|
+
<?xml version="1.0" encoding="utf-8"?>
|
7
|
+
<feed xmlns="http://www.w3.org/2005/Atom">
|
8
|
+
|
9
|
+
<title>Example Feed</title>
|
10
|
+
<link href="http://example.org/"/>
|
11
|
+
<updated>2003-12-13T18:30:02Z</updated>
|
12
|
+
<author>
|
13
|
+
<name>John Doe</name>
|
14
|
+
</author>
|
15
|
+
<id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id>
|
16
|
+
|
17
|
+
<entry>
|
18
|
+
<title>Atom-Powered Robots Run Amok</title>
|
19
|
+
<link href="http://example.org/2003/12/13/atom03"/>
|
20
|
+
<id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
|
21
|
+
<updated>2003-12-13T18:30:02Z</updated>
|
22
|
+
<summary>Some text.</summary>
|
23
|
+
</entry>
|
24
|
+
|
25
|
+
<entry>
|
26
|
+
<title>Something else cool happened</title>
|
27
|
+
<link href="http://example.org/2015/08/11/andyjeffries"/>
|
28
|
+
<id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6b</id>
|
29
|
+
<updated>2015-08-11T18:30:02Z</updated>
|
30
|
+
<summary>Some other text.</summary>
|
31
|
+
</entry>
|
32
|
+
|
33
|
+
</feed>
|
34
|
+
```
|
35
|
+
|
36
|
+
You can use:
|
37
|
+
|
38
|
+
```ruby
|
39
|
+
class Feed < Flexirest::Base
|
40
|
+
base_url "http://www.example.com/v1/"
|
41
|
+
get :atom, "/atom"
|
42
|
+
end
|
43
|
+
|
44
|
+
@atom = Feed.atom
|
45
|
+
|
46
|
+
puts @atom.feed.title
|
47
|
+
puts @atom.feed.link.href
|
48
|
+
@atom.feed.entry.each do |entry|
|
49
|
+
puts "#{entry.title} -> #{entry.link.href}"
|
50
|
+
end
|
51
|
+
```
|
52
|
+
|
53
|
+
For testing purposes, if you are using a `fake` content response when defining your endpoint, you should also provide `fake_content_type: "application/xml"` so that the parser knows to use XML parsing.
|
54
|
+
|
55
|
+
|
56
|
+
-----
|
57
|
+
|
58
|
+
[< Debugging](debugging.md)
|
@@ -45,22 +45,30 @@ module Flexirest
|
|
45
45
|
@@base_url = value
|
46
46
|
end
|
47
47
|
|
48
|
-
def username(value = nil)
|
48
|
+
def username(value = nil, &block)
|
49
49
|
@username ||= nil
|
50
50
|
@@username ||= nil
|
51
51
|
if value.nil?
|
52
|
-
|
53
|
-
|
52
|
+
if block_given?
|
53
|
+
@username = block
|
54
54
|
else
|
55
|
-
@username
|
56
|
-
|
57
|
-
|
58
|
-
|
55
|
+
value = if @username.nil?
|
56
|
+
@@username
|
57
|
+
else
|
58
|
+
@username
|
59
|
+
end
|
60
|
+
if value.nil? && superclass.respond_to?(:username)
|
61
|
+
value = superclass.username
|
62
|
+
end
|
63
|
+
value
|
59
64
|
end
|
60
|
-
value
|
61
65
|
else
|
62
|
-
|
63
|
-
|
66
|
+
if value.respond_to?(:call)
|
67
|
+
@username = value
|
68
|
+
else
|
69
|
+
value = CGI::escape(value) if value.present? && !value.include?("%")
|
70
|
+
@username = value
|
71
|
+
end
|
64
72
|
end
|
65
73
|
end
|
66
74
|
|
@@ -70,20 +78,28 @@ module Flexirest
|
|
70
78
|
@@username = value
|
71
79
|
end
|
72
80
|
|
73
|
-
def password(value = nil)
|
81
|
+
def password(value = nil, &block)
|
74
82
|
if value.nil?
|
75
|
-
|
76
|
-
|
83
|
+
if block_given?
|
84
|
+
@password = block
|
77
85
|
else
|
78
|
-
@password
|
79
|
-
|
80
|
-
|
81
|
-
|
86
|
+
value = if @password.nil?
|
87
|
+
@@password
|
88
|
+
else
|
89
|
+
@password
|
90
|
+
end
|
91
|
+
if value.nil? && superclass.respond_to?(:password)
|
92
|
+
value = superclass.password
|
93
|
+
end
|
94
|
+
value
|
82
95
|
end
|
83
|
-
value
|
84
96
|
else
|
85
|
-
|
86
|
-
|
97
|
+
if value.respond_to?(:call)
|
98
|
+
@password = value
|
99
|
+
else
|
100
|
+
value = CGI::escape(value) if value.present? && !value.include?("%")
|
101
|
+
@password = value
|
102
|
+
end
|
87
103
|
end
|
88
104
|
end
|
89
105
|
|
data/lib/flexirest/request.rb
CHANGED
@@ -93,19 +93,27 @@ module Flexirest
|
|
93
93
|
end
|
94
94
|
|
95
95
|
def username
|
96
|
+
ret = nil
|
96
97
|
if object_is_class?
|
97
|
-
@object.username
|
98
|
+
ret = @object.username
|
99
|
+
ret = ret.call if ret.respond_to?(:call)
|
98
100
|
else
|
99
|
-
@object.class.username
|
101
|
+
ret = @object.class.username
|
102
|
+
ret = ret.call(@object) if ret.respond_to?(:call)
|
100
103
|
end
|
104
|
+
ret
|
101
105
|
end
|
102
106
|
|
103
107
|
def password
|
108
|
+
ret = nil
|
104
109
|
if object_is_class?
|
105
|
-
@object.password
|
110
|
+
ret = @object.password
|
111
|
+
ret = ret.call if ret.respond_to?(:call)
|
106
112
|
else
|
107
|
-
|
113
|
+
ret = @object.class.password
|
114
|
+
ret = ret.call(@object) if ret.respond_to?(:call)
|
108
115
|
end
|
116
|
+
ret
|
109
117
|
end
|
110
118
|
|
111
119
|
def request_body_type
|
data/lib/flexirest/version.rb
CHANGED
data/spec/lib/request_spec.rb
CHANGED
@@ -62,6 +62,19 @@ describe Flexirest::Request do
|
|
62
62
|
get :all, "/"
|
63
63
|
end
|
64
64
|
|
65
|
+
class AuthenticatedProcExampleClient < Flexirest::Base
|
66
|
+
base_url "http://www.example.com"
|
67
|
+
username Proc.new { |obj| obj ? "bill-#{obj.id}" : "bill" }
|
68
|
+
password do |obj|
|
69
|
+
if obj
|
70
|
+
"jones-#{obj.id}"
|
71
|
+
else
|
72
|
+
"jones"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
get :all, "/"
|
76
|
+
end
|
77
|
+
|
65
78
|
class ProcDefaultExampleClient < Flexirest::Base
|
66
79
|
base_url "http://www.example.com"
|
67
80
|
get :all, "/", defaults: (Proc.new do |params|
|
@@ -167,6 +180,21 @@ describe Flexirest::Request do
|
|
167
180
|
AuthenticatedExampleClient.all
|
168
181
|
end
|
169
182
|
|
183
|
+
it "should get an HTTP connection with authentication using procs when called in a class context" do
|
184
|
+
connection = double(Flexirest::Connection).as_null_object
|
185
|
+
expect(Flexirest::ConnectionManager).to receive(:get_connection).with("http://bill:jones@www.example.com").and_return(connection)
|
186
|
+
expect(connection).to receive(:get).with("/", an_instance_of(Hash)).and_return(::FaradayResponseMock.new(OpenStruct.new(body:'{"result":true}', response_headers:{})))
|
187
|
+
AuthenticatedProcExampleClient.all
|
188
|
+
end
|
189
|
+
|
190
|
+
it "should get an HTTP connection with authentication using procs when called in an object context" do
|
191
|
+
connection = double(Flexirest::Connection).as_null_object
|
192
|
+
expect(Flexirest::ConnectionManager).to receive(:get_connection).with("http://bill-1:jones-1@www.example.com").and_return(connection)
|
193
|
+
expect(connection).to receive(:get).with("/?id=1", an_instance_of(Hash)).and_return(::FaradayResponseMock.new(OpenStruct.new(body:'{"result":true}', response_headers:{})))
|
194
|
+
obj = AuthenticatedProcExampleClient.new(id: 1)
|
195
|
+
obj.all
|
196
|
+
end
|
197
|
+
|
170
198
|
it "should get an HTTP connection when called and call get on it" do
|
171
199
|
expect_any_instance_of(Flexirest::Connection).to receive(:get).with("/", an_instance_of(Hash)).and_return(::FaradayResponseMock.new(OpenStruct.new(body:'{"result":true}', response_headers:{})))
|
172
200
|
ExampleClient.all
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: flexirest
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.6.
|
4
|
+
version: 1.6.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andy Jeffries
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-04-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -218,19 +218,47 @@ files:
|
|
218
218
|
- ".simplecov"
|
219
219
|
- ".travis.yml"
|
220
220
|
- CHANGELOG.md
|
221
|
-
- CONTRIBUTING.md
|
222
221
|
- Gemfile
|
223
222
|
- LICENSE.txt
|
224
|
-
- Migrating-from-ActiveRestClient.md
|
225
223
|
- README.md
|
226
224
|
- Rakefile
|
227
|
-
- Ruby-on-Rails-Integration.md
|
228
225
|
- docs/FLEXIREST.svg
|
229
226
|
- docs/FLEXIREST@2x.png
|
230
|
-
- docs/Flexirest Internals.graffle
|
231
227
|
- docs/Flexirest Internals.png
|
232
|
-
- docs/
|
228
|
+
- docs/associations.md
|
229
|
+
- docs/authentication.md
|
230
|
+
- docs/automatic-conversion-of-fields-to-datedatetime.md
|
231
|
+
- docs/basic-usage.md
|
232
|
+
- docs/body-types.md
|
233
|
+
- docs/caching.md
|
234
|
+
- docs/combined-example.md
|
235
|
+
- docs/debugging.md
|
236
|
+
- docs/default-parameters.md
|
237
|
+
- docs/faking-calls.md
|
238
|
+
- docs/faraday-configuration.md
|
239
|
+
- docs/filtering-result-lists.md
|
240
|
+
- docs/httpparse-error-handling.md
|
241
|
+
- docs/internals.md
|
233
242
|
- docs/issue_template.md
|
243
|
+
- docs/json-api.md
|
244
|
+
- docs/lazy-loading.md
|
245
|
+
- docs/migrating-from-activerestclient.md
|
246
|
+
- docs/parallel-requests.md
|
247
|
+
- docs/per-request-parameter-encoding.md
|
248
|
+
- docs/per-request-timeouts.md
|
249
|
+
- docs/plain-requests.md
|
250
|
+
- docs/proxying-apis.md
|
251
|
+
- docs/raw-requests.md
|
252
|
+
- docs/required-parameters.md
|
253
|
+
- docs/root-elements.md
|
254
|
+
- docs/ruby-on-rails-integration.md
|
255
|
+
- docs/source/Flexirest Internals.graffle
|
256
|
+
- docs/source/Flexirest Logo.sketch
|
257
|
+
- docs/translating-apis.md
|
258
|
+
- docs/updating-only-changed-dirty-attributes.md
|
259
|
+
- docs/using-callbacks.md
|
260
|
+
- docs/validation.md
|
261
|
+
- docs/xml-responses.md
|
234
262
|
- flexirest.gemspec
|
235
263
|
- lib/flexirest.rb
|
236
264
|
- lib/flexirest/associations.rb
|